Merge branch 'master' into dyable-leather-armor
|
@ -1,5 +1,8 @@
|
|||
# This is a game specific minetest.conf file, do not edit
|
||||
|
||||
# If any of these settings are set in your minetest.conf file in ~/.minetest (Linux) or in the root directory of the game (Run in place/Windows)
|
||||
# They will override these settings
|
||||
|
||||
# Basic game rules
|
||||
time_speed = 72
|
||||
|
||||
|
@ -33,7 +36,7 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de
|
|||
keepInventory = false
|
||||
|
||||
# Performance settings
|
||||
# dedicated_server_step = 0.001
|
||||
dedicated_server_step = 0.05 #tick rate
|
||||
# abm_interval = 0.25
|
||||
# max_objects_per_block = 4096
|
||||
# max_packets_per_iteration = 10096
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# controls
|
||||
|
||||
## controls.players
|
||||
Table containing player controls at runtime.
|
||||
WARNING: Never use this table in writing
|
||||
|
||||
## controls.register_on_press(func)
|
||||
Register a function that will be executed with (player, keyname) every time a player press a key.
|
||||
|
||||
## controls.registered_on_press
|
||||
Table containing functions registered with controls.register_on_press().
|
||||
|
||||
## controls.register_on_release(func)
|
||||
Register a function that will be executed with (player, keyname, clock_from_last_press) every time a player release a key.
|
||||
|
||||
## controls.registered_on_release
|
||||
Table containing functions registered with controls.register_on_release().
|
||||
|
||||
## controls.register_on_hold(func)
|
||||
Register a function that will be executed with (player, keyname, clock_from_start_hold) every time a player hold a key.
|
||||
|
||||
## controls.registered_on_hold
|
||||
Table containing functions registered with controls.register_on_hold().
|
|
@ -0,0 +1,45 @@
|
|||
# flowlib
|
||||
Simple flow functions.
|
||||
|
||||
## flowlib.is_touching(realpos, nodepos, radius)
|
||||
Return true if a sphere of <radius> at <realpos> collide with node at <nodepos>.
|
||||
* realpos: position
|
||||
* nodepos: position
|
||||
* radius: number
|
||||
|
||||
## flowlib.is_water(pos)
|
||||
Return true if node at <pos> is water, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_water(node)
|
||||
Return true if <node> is water, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_lava(pos)
|
||||
Return true if node at <pos> is lava, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_lava(node)
|
||||
Return true if <node> is lava, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_liquid(pos)
|
||||
Return true if node at <pos> is liquid, false overwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_liquid(node)
|
||||
Return true if <node> is liquid, false overwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.quick_flow(pos, node)
|
||||
Return direction where the water is flowing (to be use to push mobs, items...).
|
||||
* pos: position
|
||||
* node: node
|
||||
|
||||
## flowlib.move_centre(pos, realpos, node, radius)
|
||||
Return the pos of the nearest not water block near from <pos> in a sphere of <radius> at <realpos>.
|
||||
WARNING: This function is never used in mcl2, use at your own risk. The informations described here may be wrong.
|
||||
* pos: position
|
||||
* realpos: position, position of the entity
|
||||
* node: node
|
||||
* radius: number
|
|
@ -0,0 +1,27 @@
|
|||
# mcl_autogroup
|
||||
This mod emulate digging times from mc.
|
||||
|
||||
## mcl_autogroup.can_harvest(nodename, toolname)
|
||||
Return true if <nodename> can be dig with <toolname>.
|
||||
* nodename: string, valid nodename
|
||||
* toolname: (optional) string, valid toolname
|
||||
|
||||
## mcl_autogroup.get_groupcaps(toolname, efficiency)
|
||||
This function is used to calculate diggroups for tools.
|
||||
WARNING: This function can only be called after mod initialization.
|
||||
* toolname: string, name of the tool being enchanted (like "mcl_tools:diamond_pickaxe")
|
||||
* efficiency: (optional) integer, the efficiency level the tool is enchanted with (default 0)
|
||||
|
||||
## mcl_autogroup.get_wear(toolname, diggroup)
|
||||
Return the max wear of <toolname> with <diggroup>
|
||||
WARNING: This function can only be called after mod initialization.
|
||||
* toolname: string, name of the tool used
|
||||
* diggroup: string, the name of the diggroup the tool is used on
|
||||
|
||||
## mcl_autogroup.register_diggroup(group, def)
|
||||
* group: string, name of the group to register as a digging group
|
||||
* def: (optional) table, table with information about the diggroup (defaults to {} if unspecified)
|
||||
* level: (optional) string, if specified it is an array containing the names of the different digging levels the digging group supports
|
||||
|
||||
## mcl_autogroup.registered_diggroups
|
||||
List of registered diggroups, indexed by name.
|
|
@ -0,0 +1,8 @@
|
|||
# mcl_colors
|
||||
Mod providing global table containing legacity minecraft colors to be used in mods.
|
||||
|
||||
## mcl_colors.*
|
||||
Colors by upper name, in hex value.
|
||||
|
||||
## mcl_colors.background.*
|
||||
Background colors by upper name, in hex value.
|
|
@ -0,0 +1,15 @@
|
|||
# mcl_explosions
|
||||
This mod provide helper functions to create explosions.
|
||||
|
||||
## mcl_explosions.explode(pos, strength, info, puncher)
|
||||
* pos: position, initial position of the explosion
|
||||
* strenght: number, radius of the explosion
|
||||
* info: table, explosion informations:
|
||||
* drop_chance: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength)
|
||||
* max_blast_resistance: int, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value
|
||||
* sound: bool, if true, the explosion will play a sound (default: true)
|
||||
* particles: bool, if true, the explosion will create particles (default: true)
|
||||
* fire: bool, if true, 1/3 nodes become fire (default: false)
|
||||
* griefing: bool, if true, the explosion will destroy nodes (default: true)
|
||||
* grief_protected: bool, if true, the explosion will also destroy nodes which have been protected (default: false)
|
||||
* puncher: (optional) entity, will be used as source for damage done by the explosion
|
|
@ -21,6 +21,9 @@ mcl_vars.gui_bg_img = "background9[1,1;1,1;mcl_base_textures_background9.png;tru
|
|||
-- Legacy
|
||||
mcl_vars.inventory_header = ""
|
||||
|
||||
-- Tool wield size
|
||||
mcl_vars.tool_wield_scale = { x = 1.8, y = 1.8, z = 1 }
|
||||
|
||||
-- Mapgen variables
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
local minecraft_height_limit = 256
|
||||
|
|
|
@ -410,7 +410,7 @@ function mcl_util.get_color(colorstr)
|
|||
local mc_color = mcl_colors[colorstr:upper()]
|
||||
if mc_color then
|
||||
colorstr = mc_color
|
||||
elseif #colorstr ~= 7 or colorstr:sub(1, 1) ~= "#"then
|
||||
elseif #colorstr ~= 7 or colorstr:sub(1, 1) ~= "#" then
|
||||
return
|
||||
end
|
||||
local hex = tonumber(colorstr:sub(2, 7), 16)
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# mcl_worlds
|
||||
This mod provides utility functions about positions and dimensions.
|
||||
|
||||
## mcl_worlds.is_in_void(pos)
|
||||
This function returns:
|
||||
|
||||
* true, true: if pos is in deep void (deadly)
|
||||
* true, false: if the pos is in void (non deadly)
|
||||
* false, false: owerwise
|
||||
|
||||
Params:
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.y_to_layer(y)
|
||||
This function is used to calculate the minetest y layer and dimension of the given <y> minecraft layer.
|
||||
Mainly used for ore generation.
|
||||
Takes an Y coordinate as input and returns:
|
||||
|
||||
* The corresponding Minecraft layer (can be nil if void)
|
||||
* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if <y> is in the void
|
||||
If the Y coordinate is not located in any dimension, it will return: nil, "void"
|
||||
|
||||
Params:
|
||||
|
||||
* y: int
|
||||
|
||||
## mcl_worlds.pos_to_dimension(pos)
|
||||
This function return the Minecraft dimension of <pos> ("overworld", "nether" or "end") or "void" if <y> is in the void.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.layer_to_y(layer, mc_dimension)
|
||||
Takes a Minecraft layer and a “dimension” name and returns the corresponding Y coordinate for MineClone 2.
|
||||
mc_dimension can be "overworld", "nether", "end" (default: "overworld").
|
||||
|
||||
* layer: int
|
||||
* mc_dimension: string
|
||||
|
||||
## mcl_worlds.has_weather(pos)
|
||||
Returns true if <pos> can have weather, false owerwise.
|
||||
Weather can be only in the overworld.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.has_dust(pos)
|
||||
Returns true if <pos> can have nether dust, false owerwise.
|
||||
Nether dust can be only in the nether.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if compasses are working at <pos>, false owerwise.
|
||||
In mc, you cant use compass in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if clock are working at <pos>, false owerwise.
|
||||
In mc, you cant use clock in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.register_on_dimension_change(function(player, dimension))
|
||||
Register a callback function func(player, dimension).
|
||||
It will be called whenever a player changes between dimensions.
|
||||
The void counts as dimension.
|
||||
|
||||
* player: player, the player who changed the dimension
|
||||
* dimension: position, The new dimension of the player ("overworld", "nether", "end", "void").
|
||||
|
||||
|
||||
## mcl_worlds.registered_on_dimension_change
|
||||
Table containing all function registered with mcl_worlds.register_on_dimension_change()
|
||||
|
||||
## mcl_worlds.dimension_change(player, dimension)
|
||||
Notify this mod of a dimmension change of <player> to <dimension>
|
||||
|
||||
* player: player, player who changed the dimension
|
||||
* dimension: string, new dimension ("overworld", "nether", "end", "void")
|
|
@ -1,14 +1,36 @@
|
|||
--these are lua locals, used for higher performance
|
||||
local minetest,math,vector,ipairs = minetest,math,vector,ipairs
|
||||
|
||||
--this is used for the player pool in the sound buffer
|
||||
local pool = {}
|
||||
|
||||
local tick = false
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name
|
||||
name = player:get_player_name()
|
||||
pool[name] = 0
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name
|
||||
name = player:get_player_name()
|
||||
pool[name] = nil
|
||||
end)
|
||||
|
||||
|
||||
local has_awards = minetest.get_modpath("awards")
|
||||
|
||||
mcl_item_entity = {}
|
||||
local mcl_item_entity = {}
|
||||
|
||||
--basic settings
|
||||
local item_drop_settings = {} --settings table
|
||||
item_drop_settings.dug_buffer = 0.65 -- the warm up period before a dug item can be collected
|
||||
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
|
||||
item_drop_settings.radius_magnet = 2.0 --radius of item magnet. MUST BE LARGER THAN radius_collect!
|
||||
item_drop_settings.xp_radius_magnet = 7.25 --radius of xp magnet. MUST BE LARGER THAN radius_collect!
|
||||
item_drop_settings.radius_collect = 0.2 --radius of collection
|
||||
item_drop_settings.player_collect_height = 1.0 --added to their pos y value
|
||||
item_drop_settings.player_collect_height = 0.8 --added to their pos y value
|
||||
item_drop_settings.collection_safety = false --do this to prevent items from flying away on laggy servers
|
||||
item_drop_settings.random_item_velocity = true --this sets random item velocity if velocity is 0
|
||||
item_drop_settings.drop_single_item = false --if true, the drop control drops 1 item instead of the entire stack, and sneak+drop drops the stack
|
||||
|
@ -74,103 +96,71 @@ local disable_physics = function(object, luaentity, ignore_check, reset_movement
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
||||
tick = not tick
|
||||
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
if player:get_hp() > 0 or not minetest.settings:get_bool("enable_damage") then
|
||||
|
||||
|
||||
local name = player:get_player_name()
|
||||
|
||||
local pos = player:get_pos()
|
||||
|
||||
if tick == true and pool[name] > 0 then
|
||||
minetest.sound_play("item_drop_pickup", {
|
||||
pos = pos,
|
||||
gain = 0.7,
|
||||
max_hear_distance = 16,
|
||||
pitch = math.random(70,110)/100
|
||||
})
|
||||
if pool[name] > 6 then
|
||||
pool[name] = 6
|
||||
else
|
||||
pool[name] = pool[name] - 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local inv = player:get_inventory()
|
||||
local checkpos = {x=pos.x,y=pos.y + item_drop_settings.player_collect_height,z=pos.z}
|
||||
|
||||
--magnet and collection
|
||||
for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do
|
||||
if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then
|
||||
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
|
||||
local collected = false
|
||||
|
||||
if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
|
||||
|
||||
-- Collection
|
||||
if vector.distance(checkpos, object:get_pos()) <= item_drop_settings.radius_collect and not object:get_luaentity()._removed then
|
||||
if not object:get_luaentity()._removed then
|
||||
-- Ignore if itemstring is not set yet
|
||||
if object:get_luaentity().itemstring ~= "" then
|
||||
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
|
||||
minetest.sound_play("item_drop_pickup", {
|
||||
pos = pos,
|
||||
max_hear_distance = 16,
|
||||
gain = 1.0,
|
||||
}, true)
|
||||
check_pickup_achievements(object, player)
|
||||
|
||||
check_pickup_achievements(object, player)
|
||||
|
||||
-- Destroy entity
|
||||
-- This just prevents this section to be run again because object:remove() doesn't remove the item immediately.
|
||||
object:get_luaentity().target = checkpos
|
||||
object:get_luaentity()._removed = true
|
||||
object:remove()
|
||||
collected = true
|
||||
|
||||
object:set_velocity({x=0,y=0,z=0})
|
||||
object:set_acceleration({x=0,y=0,z=0})
|
||||
|
||||
object:move_to(checkpos)
|
||||
|
||||
pool[name] = pool[name] + 1
|
||||
|
||||
minetest.after(0.25, function()
|
||||
--safety check
|
||||
if object and object:get_luaentity() then
|
||||
object:remove()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Magnet
|
||||
else
|
||||
|
||||
object:get_luaentity()._magnet_active = true
|
||||
object:get_luaentity()._collector_timer = 0
|
||||
|
||||
-- Move object to player
|
||||
disable_physics(object, object:get_luaentity())
|
||||
|
||||
local opos = object:get_pos()
|
||||
local vec = vector.subtract(checkpos, opos)
|
||||
vec = vector.add(opos, vector.divide(vec, 2))
|
||||
object:move_to(vec)
|
||||
|
||||
|
||||
--fix eternally falling items
|
||||
minetest.after(0, function(object)
|
||||
local lua = object:get_luaentity()
|
||||
if lua then
|
||||
object:set_acceleration({x=0, y=0, z=0})
|
||||
end
|
||||
end, object)
|
||||
|
||||
|
||||
--this is a safety to prevent items flying away on laggy servers
|
||||
if item_drop_settings.collection_safety == true then
|
||||
if object:get_luaentity().init ~= true then
|
||||
object:get_luaentity().init = true
|
||||
minetest.after(1, function(args)
|
||||
local playername = args[1]
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
local object = args[2]
|
||||
local lua = object:get_luaentity()
|
||||
if player == nil or not player:is_player() or object == nil or lua == nil or lua.itemstring == nil then
|
||||
return
|
||||
end
|
||||
if inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
|
||||
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
|
||||
if not object:get_luaentity()._removed then
|
||||
minetest.sound_play("item_drop_pickup", {
|
||||
pos = pos,
|
||||
max_hear_distance = 16,
|
||||
gain = 1.0,
|
||||
}, true)
|
||||
end
|
||||
check_pickup_achievements(object, player)
|
||||
object:get_luaentity()._removed = true
|
||||
object:remove()
|
||||
else
|
||||
enable_physics(object, object:get_luaentity())
|
||||
end
|
||||
end, {player:get_player_name(), object})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not collected then
|
||||
if object:get_luaentity()._magnet_timer > 1 then
|
||||
object:get_luaentity()._magnet_timer = -item_drop_settings.magnet_time
|
||||
object:get_luaentity()._magnet_active = false
|
||||
elseif object:get_luaentity()._magnet_timer < 0 then
|
||||
object:get_luaentity()._magnet_timer = object:get_luaentity()._magnet_timer + dtime
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -230,12 +220,13 @@ local function get_fortune_drops(fortune_drops, fortune_level)
|
|||
return drop or {}
|
||||
end
|
||||
|
||||
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
|
||||
|
||||
function minetest.handle_node_drops(pos, drops, digger)
|
||||
-- NOTE: This function override allows digger to be nil.
|
||||
-- This means there is no digger. This is a special case which allows this function to be called
|
||||
-- by hand. Creative Mode is intentionally ignored in this case.
|
||||
|
||||
local doTileDrops = minetest.settings:get_bool("mcl_doTileDrops", true)
|
||||
if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then
|
||||
return
|
||||
end
|
||||
|
@ -335,6 +326,10 @@ function minetest.handle_node_drops(pos, drops, digger)
|
|||
z = -z
|
||||
end
|
||||
obj:set_velocity({x=1/x, y=obj:get_velocity().y, z=1/z})
|
||||
|
||||
obj:get_luaentity().age = item_drop_settings.dug_buffer
|
||||
|
||||
obj:get_luaentity()._insta_collect = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -401,6 +396,9 @@ minetest.register_entity(":__builtin:item", {
|
|||
-- Number of seconds this item entity has existed so far
|
||||
age = 0,
|
||||
|
||||
-- How old it has become in the collection animation
|
||||
collection_age = 0,
|
||||
|
||||
set_item = function(self, itemstring)
|
||||
self.itemstring = itemstring
|
||||
if self.itemstring == "" then
|
||||
|
@ -566,6 +564,11 @@ minetest.register_entity(":__builtin:item", {
|
|||
|
||||
on_step = function(self, dtime)
|
||||
if self._removed then
|
||||
self.object:set_properties({
|
||||
physical = false
|
||||
})
|
||||
self.object:set_velocity({x=0,y=0,z=0})
|
||||
self.object:set_acceleration({x=0,y=0,z=0})
|
||||
return
|
||||
end
|
||||
self.age = self.age + dtime
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Item_Drop_Pickup - https://freesound.org/people/benniknop/sounds/317848/ (License: CC0)
|
|
@ -61,8 +61,6 @@ end
|
|||
|
||||
-- Load settings
|
||||
local damage_enabled = minetest.settings:get_bool("enable_damage")
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
|
||||
local disable_blood = minetest.settings:get_bool("mobs_disable_blood")
|
||||
local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false
|
||||
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
|
||||
|
@ -84,11 +82,6 @@ if minetest.settings:get_bool("only_peaceful_mobs", false) then
|
|||
end)
|
||||
end
|
||||
|
||||
-- calculate aoc range for mob count
|
||||
local aosrb = tonumber(minetest.settings:get("active_object_send_range_blocks"))
|
||||
local abr = tonumber(minetest.settings:get("active_block_range"))
|
||||
local aoc_range = max(aosrb, abr) * 16
|
||||
|
||||
-- pathfinding settings
|
||||
local enable_pathfinding = true
|
||||
local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching
|
||||
|
@ -735,7 +728,9 @@ local item_drop = function(self, cooked, looting_level)
|
|||
end
|
||||
|
||||
-- add item if it exists
|
||||
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
|
||||
for x = 1, num do
|
||||
obj = minetest.add_item(pos, ItemStack(item .. " " .. 1))
|
||||
end
|
||||
|
||||
if obj and obj:get_luaentity() then
|
||||
|
||||
|
@ -864,10 +859,12 @@ local check_for_death = function(self, cause, cmi_cause)
|
|||
remove_texture_mod(self, "^[colorize:#FF000040")
|
||||
remove_texture_mod(self, "^[brighten")
|
||||
self.passive = true
|
||||
|
||||
self.object:set_properties({
|
||||
pointable = false,
|
||||
collide_with_objects = false,
|
||||
})
|
||||
|
||||
set_velocity(self, 0)
|
||||
local acc = self.object:get_acceleration()
|
||||
acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0
|
||||
|
@ -2817,6 +2814,10 @@ local do_states = function(self, dtime)
|
|||
local arrow, ent
|
||||
local v = 1
|
||||
if not self.shoot_arrow then
|
||||
self.firing = true
|
||||
minetest.after(1, function()
|
||||
self.firing = false
|
||||
end)
|
||||
arrow = minetest.add_entity(p, self.arrow)
|
||||
ent = arrow:get_luaentity()
|
||||
if ent.velocity then
|
||||
|
@ -3520,14 +3521,6 @@ local mob_step = function(self, dtime)
|
|||
|
||||
-- end rotation
|
||||
|
||||
-- knockback timer
|
||||
if self.pause_timer > 0 then
|
||||
|
||||
self.pause_timer = self.pause_timer - dtime
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- run custom function (defined in mob lua file)
|
||||
if self.do_custom then
|
||||
|
||||
|
@ -3537,6 +3530,14 @@ local mob_step = function(self, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
-- knockback timer
|
||||
if self.pause_timer > 0 then
|
||||
|
||||
self.pause_timer = self.pause_timer - dtime
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- attack timer
|
||||
self.timer = self.timer + dtime
|
||||
|
||||
|
@ -3555,7 +3556,7 @@ local mob_step = function(self, dtime)
|
|||
end
|
||||
|
||||
-- mob plays random sound at times
|
||||
if random(1, 100) == 1 then
|
||||
if random(1, 70) == 1 then
|
||||
mob_sound(self, "random", true)
|
||||
end
|
||||
|
||||
|
@ -3735,6 +3736,8 @@ function mobs:register_mob(name, def)
|
|||
local can_despawn
|
||||
if def.can_despawn ~= nil then
|
||||
can_despawn = def.can_despawn
|
||||
elseif def.spawn_class == "passive" then
|
||||
can_despawn = false
|
||||
else
|
||||
can_despawn = true
|
||||
end
|
||||
|
@ -3898,6 +3901,12 @@ minetest.register_entity(name, {
|
|||
on_detach_child = mob_detach_child,
|
||||
|
||||
on_activate = function(self, staticdata, dtime)
|
||||
--this is a temporary hack so mobs stop
|
||||
--glitching and acting really weird with the
|
||||
--default built in engine collision detection
|
||||
self.object:set_properties({
|
||||
collide_with_objects = false,
|
||||
})
|
||||
return mob_activate(self, staticdata, def, dtime)
|
||||
end,
|
||||
|
||||
|
@ -3916,289 +3925,6 @@ end
|
|||
end -- END mobs:register_mob function
|
||||
|
||||
|
||||
-- count how many mobs of one type are inside an area
|
||||
local count_mobs = function(pos, mobtype)
|
||||
|
||||
local num = 0
|
||||
local objs = minetest.get_objects_inside_radius(pos, aoc_range)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
local obj = objs[n]:get_luaentity()
|
||||
|
||||
if obj and obj.name and obj._cmi_is_mob then
|
||||
|
||||
-- count passive mobs only
|
||||
if mobtype == "!passive" then
|
||||
if obj.spawn_class == "passive" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count hostile mobs only
|
||||
elseif mobtype == "!hostile" then
|
||||
if obj.spawn_class == "hostile" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count ambient mobs only
|
||||
elseif mobtype == "!ambient" then
|
||||
if obj.spawn_class == "ambient" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count water mobs only
|
||||
elseif mobtype == "!water" then
|
||||
if obj.spawn_class == "water" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count mob type
|
||||
elseif mobtype and obj.name == mobtype then
|
||||
num = num + 1
|
||||
-- count total mobs
|
||||
elseif not mobtype then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return num
|
||||
end
|
||||
|
||||
|
||||
-- global functions
|
||||
|
||||
function mobs:spawn_abm_check(pos, node, name)
|
||||
-- global function to add additional spawn checks
|
||||
-- return true to stop spawning mob
|
||||
end
|
||||
|
||||
|
||||
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
||||
interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||
|
||||
-- Do mobs spawn at all?
|
||||
if not mobs_spawn then
|
||||
return
|
||||
end
|
||||
|
||||
-- chance/spawn number override in minetest.conf for registered mob
|
||||
local numbers = minetest.settings:get(name)
|
||||
|
||||
if numbers then
|
||||
numbers = numbers:split(",")
|
||||
chance = tonumber(numbers[1]) or chance
|
||||
aoc = tonumber(numbers[2]) or aoc
|
||||
|
||||
if chance == 0 then
|
||||
minetest.log("warning", string.format("[mobs] %s has spawning disabled", name))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action",
|
||||
string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
||||
|
||||
end
|
||||
|
||||
local spawn_action
|
||||
spawn_action = function(pos, node, active_object_count, active_object_count_wider, name)
|
||||
|
||||
local orig_pos = table.copy(pos)
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[name]
|
||||
or not minetest.registered_entities[name] then
|
||||
minetest.log("warning", "Mob spawn of "..name.." failed, unknown entity or mob is not registered for spawning!")
|
||||
return
|
||||
end
|
||||
|
||||
-- additional custom checks for spawning mob
|
||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, ABM check rejected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- count nearby mobs in same spawn class
|
||||
local entdef = minetest.registered_entities[name]
|
||||
local spawn_class = entdef and entdef.spawn_class
|
||||
if not spawn_class then
|
||||
if entdef.type == "monster" then
|
||||
spawn_class = "hostile"
|
||||
else
|
||||
spawn_class = "passive"
|
||||
end
|
||||
end
|
||||
local in_class_cap = count_mobs(pos, "!"..spawn_class) < MOB_CAP[spawn_class]
|
||||
-- do not spawn if too many of same mob in area
|
||||
if active_object_count_wider >= max_per_block -- large-range mob cap
|
||||
or (not in_class_cap) -- spawn class mob cap
|
||||
or count_mobs(pos, name) >= aoc then -- per-mob mob cap
|
||||
-- too many entities
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too crowded!")
|
||||
return
|
||||
end
|
||||
|
||||
-- if toggle set to nil then ignore day/night check
|
||||
if day_toggle ~= nil then
|
||||
|
||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
||||
|
||||
if tod > 4500 and tod < 19500 then
|
||||
-- daylight, but mob wants night
|
||||
if day_toggle == false then
|
||||
-- mob needs night
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs light!")
|
||||
return
|
||||
end
|
||||
else
|
||||
-- night time but mob wants day
|
||||
if day_toggle == true then
|
||||
-- mob needs day
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs daylight!")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn above node
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- only spawn away from player
|
||||
local objs = minetest.get_objects_inside_radius(pos, 24)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
-- player too close
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, player too close!")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, position is protected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are we spawning within height limits?
|
||||
if pos.y > max_height
|
||||
or pos.y < min_height then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, out of height limit!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are light levels ok?
|
||||
local light = minetest.get_node_light(pos)
|
||||
if not light
|
||||
or light > max_light
|
||||
or light < min_light then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, bad light!")
|
||||
return
|
||||
end
|
||||
|
||||
-- do we have enough space to spawn mob?
|
||||
local ent = minetest.registered_entities[name]
|
||||
local width_x = max(1, math.ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
||||
local min_x, max_x
|
||||
if width_x % 2 == 0 then
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -(max_x-1)
|
||||
else
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -max_x
|
||||
end
|
||||
|
||||
local width_z = max(1, math.ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
||||
local min_z, max_z
|
||||
if width_z % 2 == 0 then
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -(max_z-1)
|
||||
else
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -max_z
|
||||
end
|
||||
|
||||
local max_y = max(0, math.ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
||||
|
||||
for y = 0, max_y do
|
||||
for x = min_x, max_x do
|
||||
for z = min_z, max_z do
|
||||
local pos2 = {x = pos.x+x, y = pos.y+y, z = pos.z+z}
|
||||
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
|
||||
-- inside block
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too little space!")
|
||||
if ent.spawn_small_alternative ~= nil and (not minetest.registered_nodes[node_ok(pos).name].walkable) then
|
||||
minetest.log("info", "Trying to spawn smaller alternative mob: "..ent.spawn_small_alternative)
|
||||
spawn_action(orig_pos, node, active_object_count, active_object_count_wider, ent.spawn_small_alternative)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- tweak X/Y/Z spawn pos
|
||||
if width_x % 2 == 0 then
|
||||
pos.x = pos.x + 0.5
|
||||
end
|
||||
if width_z % 2 == 0 then
|
||||
pos.z = pos.z + 0.5
|
||||
end
|
||||
pos.y = pos.y - 0.5
|
||||
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos))
|
||||
|
||||
if on_spawn then
|
||||
|
||||
local ent = mob:get_luaentity()
|
||||
|
||||
on_spawn(ent, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn_abm_action(pos, node, active_object_count, active_object_count_wider)
|
||||
spawn_action(pos, node, active_object_count, active_object_count_wider, name)
|
||||
end
|
||||
|
||||
minetest.register_abm({
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
neighbors = neighbors,
|
||||
interval = interval,
|
||||
chance = floor(max(1, chance * mobs_spawn_chance)),
|
||||
catch_up = false,
|
||||
action = spawn_abm_action,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- compatibility with older mob registration
|
||||
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle)
|
||||
|
||||
mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30,
|
||||
chance, active_object_count, -31000, max_height, day_toggle)
|
||||
end
|
||||
|
||||
|
||||
-- MarkBu's spawn function
|
||||
function mobs:spawn(def)
|
||||
|
||||
local name = def.name
|
||||
local nodes = def.nodes or {"group:soil", "group:stone"}
|
||||
local neighbors = def.neighbors or {"air"}
|
||||
local min_light = def.min_light or 0
|
||||
local max_light = def.max_light or 15
|
||||
local interval = def.interval or 30
|
||||
local chance = def.chance or 5000
|
||||
local active_object_count = def.active_object_count or 1
|
||||
local min_height = def.min_height or -31000
|
||||
local max_height = def.max_height or 31000
|
||||
local day_toggle = def.day_toggle
|
||||
local on_spawn = def.on_spawn
|
||||
|
||||
mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
|
||||
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
|
||||
end
|
||||
|
||||
|
||||
-- register arrow for shoot attack
|
||||
function mobs:register_arrow(name, def)
|
||||
|
||||
|
@ -4221,6 +3947,11 @@ function mobs:register_arrow(name, def)
|
|||
switch = 0,
|
||||
owner_id = def.owner_id,
|
||||
rotate = def.rotate,
|
||||
on_punch = function(self)
|
||||
local vel = self.object:get_velocity()
|
||||
self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1})
|
||||
end,
|
||||
collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0},
|
||||
automatic_face_movement_dir = def.rotate
|
||||
and (def.rotate - (pi / 180)) or false,
|
||||
|
||||
|
@ -4283,7 +4014,7 @@ function mobs:register_arrow(name, def)
|
|||
|
||||
if self.hit_player or self.hit_mob or self.hit_object then
|
||||
|
||||
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do
|
||||
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do
|
||||
|
||||
if self.hit_player
|
||||
and player:is_player() then
|
||||
|
@ -4338,7 +4069,7 @@ end
|
|||
|
||||
-- make explosion with protection and tnt mod check
|
||||
function mobs:boom(self, pos, strength, fire)
|
||||
|
||||
self.object:remove()
|
||||
if mod_explosions then
|
||||
if mobs_griefing and not minetest.is_protected(pos, "") then
|
||||
mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object)
|
||||
|
@ -4619,6 +4350,7 @@ function mobs:alias_mob(old_name, new_name)
|
|||
|
||||
end
|
||||
|
||||
--[[
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime
|
||||
|
@ -4635,3 +4367,4 @@ minetest.register_globalstep(function(dtime)
|
|||
end
|
||||
timer = 0
|
||||
end)
|
||||
]]--
|
|
@ -4,6 +4,9 @@ local path = minetest.get_modpath(minetest.get_current_modname())
|
|||
-- Mob API
|
||||
dofile(path .. "/api.lua")
|
||||
|
||||
-- Spawning Algorithm
|
||||
dofile(path .. "/spawning.lua")
|
||||
|
||||
-- Rideable Mobs
|
||||
dofile(path .. "/mount.lua")
|
||||
|
||||
|
|
|
@ -168,16 +168,20 @@ function mobs.detach(player, offset)
|
|||
|
||||
mcl_player.player_set_animation(player, "stand" , 30)
|
||||
|
||||
local pos = player:get_pos()
|
||||
--local pos = player:get_pos()
|
||||
|
||||
pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
|
||||
--pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z}
|
||||
|
||||
player:add_velocity(vector.new(math.random(-6,6),math.random(5,8),math.random(-6,6))) --throw the rider off
|
||||
|
||||
--[[
|
||||
minetest.after(0.1, function(name, pos)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
player:set_pos(pos)
|
||||
end
|
||||
end, player:get_player_name(), pos)
|
||||
]]--
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,647 @@
|
|||
--lua locals
|
||||
local get_node = minetest.get_node
|
||||
local get_item_group = minetest.get_item_group
|
||||
local get_node_light = minetest.get_node_light
|
||||
local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
|
||||
local new_vector = vector.new
|
||||
local math_random = math.random
|
||||
local get_biome_name = minetest.get_biome_name
|
||||
local max = math.max
|
||||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
local vector_distance = vector.distance
|
||||
|
||||
-- range for mob count
|
||||
local aoc_range = 32
|
||||
--[[
|
||||
|
||||
THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
||||
|
||||
underground:
|
||||
"FlowerForest_underground",
|
||||
"JungleEdge_underground",local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)]
|
||||
"ColdTaiga_underground",
|
||||
"IcePlains_underground",
|
||||
"IcePlainsSpikes_underground",
|
||||
"MegaTaiga_underground",
|
||||
"Taiga_underground",
|
||||
"ExtremeHills+_underground",
|
||||
"JungleM_underground",
|
||||
"ExtremeHillsM_underground",
|
||||
"JungleEdgeM_underground",
|
||||
|
||||
ocean:
|
||||
"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",
|
||||
|
||||
water or beach?
|
||||
"MesaPlateauFM_sandlevel",
|
||||
"MesaPlateauF_sandlevel",
|
||||
"MesaBryce_sandlevel",
|
||||
"Mesa_sandlevel",
|
||||
|
||||
beach:
|
||||
"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",
|
||||
|
||||
dimension biome:
|
||||
"Nether",
|
||||
"End",
|
||||
|
||||
Overworld regular:
|
||||
"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",
|
||||
]]--
|
||||
|
||||
|
||||
|
||||
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
-- count how many mobs of one type are inside an area
|
||||
|
||||
local count_mobs = function(pos,mobtype)
|
||||
local num = 0
|
||||
local objs = get_objects_inside_radius(pos, aoc_range)
|
||||
for n = 1, #objs do
|
||||
local obj = objs[n]:get_luaentity()
|
||||
if obj and obj.name and obj._cmi_is_mob then
|
||||
-- count hostile mobs only
|
||||
if mobtype == "hostile" then
|
||||
if obj.spawn_class == "hostile" then
|
||||
num = num + 1
|
||||
end
|
||||
-- count passive mobs only
|
||||
else
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return num
|
||||
end
|
||||
|
||||
|
||||
-- global functions
|
||||
|
||||
function mobs:spawn_abm_check(pos, node, name)
|
||||
-- global function to add additional spawn checks
|
||||
-- return true to stop spawning mob
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Custom elements changed:
|
||||
|
||||
name:
|
||||
the mobs name
|
||||
|
||||
dimension:
|
||||
"overworld"
|
||||
"nether"
|
||||
"end"
|
||||
|
||||
types of spawning:
|
||||
"water"
|
||||
"ground"
|
||||
"lava"
|
||||
|
||||
biomes: tells the spawner to allow certain mobs to spawn in certain biomes
|
||||
{"this", "that", "grasslands", "whatever"}
|
||||
|
||||
|
||||
what is aoc??? objects in area
|
||||
|
||||
WARNING: BIOME INTEGRATION NEEDED -> How to get biome through lua??
|
||||
]]--
|
||||
|
||||
|
||||
--this is where all of the spawning information is kept
|
||||
local spawn_dictionary = {}
|
||||
|
||||
function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||
|
||||
--print(dump(biomes))
|
||||
|
||||
-- Do mobs spawn at all?
|
||||
if not mobs_spawn then
|
||||
return
|
||||
end
|
||||
|
||||
-- chance/spawn number override in minetest.conf for registered mob
|
||||
local numbers = minetest.settings:get(name)
|
||||
|
||||
if numbers then
|
||||
numbers = numbers:split(",")
|
||||
chance = tonumber(numbers[1]) or chance
|
||||
aoc = tonumber(numbers[2]) or aoc
|
||||
|
||||
if chance == 0 then
|
||||
minetest.log("warning", string.format("[mobs] %s has spawning disabled", name))
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action",
|
||||
string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
||||
end
|
||||
|
||||
--[[
|
||||
local spawn_action
|
||||
spawn_action = function(pos, node, active_object_count, active_object_count_wider, name)
|
||||
|
||||
local orig_pos = table.copy(pos)
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[name]
|
||||
or not minetest.registered_entities[name] then
|
||||
minetest.log("warning", "Mob spawn of "..name.." failed, unknown entity or mob is not registered for spawning!")
|
||||
return
|
||||
end
|
||||
|
||||
-- additional custom checks for spawning mob
|
||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, ABM check rejected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- count nearby mobs in same spawn class
|
||||
local entdef = minetest.registered_entities[name]
|
||||
local spawn_class = entdef and entdef.spawn_class
|
||||
if not spawn_class then
|
||||
if entdef.type == "monster" then
|
||||
spawn_class = "hostile"
|
||||
else
|
||||
spawn_class = "passive"
|
||||
end
|
||||
end
|
||||
local in_class_cap = count_mobs(pos, "!"..spawn_class) < MOB_CAP[spawn_class]
|
||||
-- do not spawn if too many of same mob in area
|
||||
if active_object_count_wider >= max_per_block -- large-range mob cap
|
||||
or (not in_class_cap) -- spawn class mob cap
|
||||
or count_mobs(pos, name) >= aoc then -- per-mob mob cap
|
||||
-- too many entities
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too crowded!")
|
||||
return
|
||||
end
|
||||
|
||||
-- if toggle set to nil then ignore day/night check
|
||||
if day_toggle ~= nil then
|
||||
|
||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
||||
|
||||
if tod > 4500 and tod < 19500 then
|
||||
-- daylight, but mob wants night
|
||||
if day_toggle == false then
|
||||
-- mob needs night
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs light!")
|
||||
return
|
||||
end
|
||||
else
|
||||
-- night time but mob wants day
|
||||
if day_toggle == true then
|
||||
-- mob needs day
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs daylight!")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn above node
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- only spawn away from player
|
||||
local objs = minetest.get_objects_inside_radius(pos, 24)
|
||||
|
||||
for n = 1, #objs do
|
||||
|
||||
if objs[n]:is_player() then
|
||||
-- player too close
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, player too close!")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, position is protected!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are we spawning within height limits?
|
||||
if pos.y > max_height
|
||||
or pos.y < min_height then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, out of height limit!")
|
||||
return
|
||||
end
|
||||
|
||||
-- are light levels ok?
|
||||
local light = minetest.get_node_light(pos)
|
||||
if not light
|
||||
or light > max_light
|
||||
or light < min_light then
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, bad light!")
|
||||
return
|
||||
end
|
||||
|
||||
-- do we have enough space to spawn mob?
|
||||
local ent = minetest.registered_entities[name]
|
||||
local width_x = max(1, math.ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
||||
local min_x, max_x
|
||||
if width_x % 2 == 0 then
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -(max_x-1)
|
||||
else
|
||||
max_x = math.floor(width_x/2)
|
||||
min_x = -max_x
|
||||
end
|
||||
|
||||
local width_z = max(1, math.ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
||||
local min_z, max_z
|
||||
if width_z % 2 == 0 then
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -(max_z-1)
|
||||
else
|
||||
max_z = math.floor(width_z/2)
|
||||
min_z = -max_z
|
||||
end
|
||||
|
||||
local max_y = max(0, math.ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
||||
|
||||
for y = 0, max_y do
|
||||
for x = min_x, max_x do
|
||||
for z = min_z, max_z do
|
||||
local pos2 = {x = pos.x+x, y = pos.y+y, z = pos.z+z}
|
||||
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
|
||||
-- inside block
|
||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too little space!")
|
||||
if ent.spawn_small_alternative ~= nil and (not minetest.registered_nodes[node_ok(pos).name].walkable) then
|
||||
minetest.log("info", "Trying to spawn smaller alternative mob: "..ent.spawn_small_alternative)
|
||||
spawn_action(orig_pos, node, active_object_count, active_object_count_wider, ent.spawn_small_alternative)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- tweak X/Y/Z spawn pos
|
||||
if width_x % 2 == 0 then
|
||||
pos.x = pos.x + 0.5
|
||||
end
|
||||
if width_z % 2 == 0 then
|
||||
pos.z = pos.z + 0.5
|
||||
end
|
||||
pos.y = pos.y - 0.5
|
||||
|
||||
local mob = minetest.add_entity(pos, name)
|
||||
minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos))
|
||||
|
||||
if on_spawn then
|
||||
|
||||
local ent = mob:get_luaentity()
|
||||
|
||||
on_spawn(ent, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn_abm_action(pos, node, active_object_count, active_object_count_wider)
|
||||
spawn_action(pos, node, active_object_count, active_object_count_wider, name)
|
||||
end
|
||||
]]--
|
||||
|
||||
local entdef = minetest.registered_entities[name]
|
||||
local spawn_class
|
||||
if entdef.type == "monster" then
|
||||
spawn_class = "hostile"
|
||||
else
|
||||
spawn_class = "passive"
|
||||
end
|
||||
|
||||
--load information into the spawn dictionary
|
||||
local key = #spawn_dictionary + 1
|
||||
spawn_dictionary[key] = {}
|
||||
spawn_dictionary[key]["name"] = name
|
||||
spawn_dictionary[key]["dimension"] = dimension
|
||||
spawn_dictionary[key]["type_of_spawning"] = type_of_spawning
|
||||
spawn_dictionary[key]["biomes"] = biomes
|
||||
spawn_dictionary[key]["min_light"] = min_light
|
||||
spawn_dictionary[key]["max_light"] = max_light
|
||||
spawn_dictionary[key]["interval"] = interval
|
||||
spawn_dictionary[key]["chance"] = chance
|
||||
spawn_dictionary[key]["aoc"] = aoc
|
||||
spawn_dictionary[key]["min_height"] = min_height
|
||||
spawn_dictionary[key]["max_height"] = max_height
|
||||
spawn_dictionary[key]["day_toggle"] = day_toggle
|
||||
--spawn_dictionary[key]["on_spawn"] = spawn_abm_action
|
||||
spawn_dictionary[key]["spawn_class"] = spawn_class
|
||||
|
||||
--[[
|
||||
minetest.register_abm({
|
||||
label = name .. " spawning",
|
||||
nodenames = nodes,
|
||||
neighbors = neighbors,
|
||||
interval = interval,
|
||||
chance = floor(max(1, chance * mobs_spawn_chance)),
|
||||
catch_up = false,
|
||||
action = spawn_abm_action,
|
||||
})
|
||||
]]--
|
||||
end
|
||||
|
||||
-- compatibility with older mob registration
|
||||
-- we're going to forget about this for now -j4i
|
||||
--[[
|
||||
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle)
|
||||
|
||||
mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30,
|
||||
chance, active_object_count, -31000, max_height, day_toggle)
|
||||
end
|
||||
]]--
|
||||
|
||||
|
||||
--Don't disable this yet-j4i
|
||||
-- MarkBu's spawn function
|
||||
|
||||
function mobs:spawn(def)
|
||||
--does nothing for now
|
||||
--[[
|
||||
local name = def.name
|
||||
local nodes = def.nodes or {"group:soil", "group:stone"}
|
||||
local neighbors = def.neighbors or {"air"}
|
||||
local min_light = def.min_light or 0
|
||||
local max_light = def.max_light or 15
|
||||
local interval = def.interval or 30
|
||||
local chance = def.chance or 5000
|
||||
local active_object_count = def.active_object_count or 1
|
||||
local min_height = def.min_height or -31000
|
||||
local max_height = def.max_height or 31000
|
||||
local day_toggle = def.day_toggle
|
||||
local on_spawn = def.on_spawn
|
||||
|
||||
mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
|
||||
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
|
||||
]]--
|
||||
end
|
||||
|
||||
|
||||
|
||||
local axis
|
||||
--inner and outer part of square donut radius
|
||||
local inner = 1
|
||||
local outer = 65
|
||||
local int = {-1,1}
|
||||
local position_calculation = function(pos)
|
||||
|
||||
pos = vector.floor(pos)
|
||||
|
||||
--this is used to determine the axis buffer from the player
|
||||
axis = math.random(0,1)
|
||||
|
||||
--cast towards the direction
|
||||
if axis == 0 then --x
|
||||
pos.x = pos.x + math.random(inner,outer)*int[math.random(1,2)]
|
||||
pos.z = pos.z + math.random(-outer,outer)
|
||||
else --z
|
||||
pos.z = pos.z + math.random(inner,outer)*int[math.random(1,2)]
|
||||
pos.x = pos.x + math.random(-outer,outer)
|
||||
end
|
||||
return(pos)
|
||||
end
|
||||
|
||||
--[[
|
||||
local decypher_limits_dictionary = {
|
||||
["overworld"] = {mcl_vars.mg_overworld_min,mcl_vars.mg_overworld_max},
|
||||
["nether"] = {mcl_vars.mg_nether_min, mcl_vars.mg_nether_max},
|
||||
["end"] = {mcl_vars.mg_end_min, mcl_vars.mg_end_max}
|
||||
}
|
||||
]]--
|
||||
|
||||
local function decypher_limits(posy)
|
||||
--local min_max_table = decypher_limits_dictionary[dimension]
|
||||
--return min_max_table[1],min_max_table[2]
|
||||
posy = math.floor(posy)
|
||||
return posy - 32, posy + 32
|
||||
end
|
||||
|
||||
--a simple helper function for mob_spawn
|
||||
local function biome_check(biome_list, biome_goal)
|
||||
for _,data in ipairs(biome_list) do
|
||||
if data == biome_goal then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--todo mob limiting
|
||||
--MAIN LOOP
|
||||
|
||||
if mobs_spawn then
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime
|
||||
if timer >= 8 then
|
||||
timer = 0
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
for i = 1,math_random(3,8) do
|
||||
repeat -- after this line each "break" means "continue"
|
||||
local player_pos = player:get_pos()
|
||||
|
||||
local _,dimension = mcl_worlds.y_to_layer(player_pos.y)
|
||||
|
||||
if dimension == "void" or dimension == "default" then
|
||||
break -- ignore void and unloaded area
|
||||
end
|
||||
|
||||
local min,max = decypher_limits(player_pos.y)
|
||||
|
||||
local goal_pos = position_calculation(player_pos)
|
||||
|
||||
local spawning_position_list = find_nodes_in_area_under_air(new_vector(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:solid", "group:water", "group:lava"})
|
||||
|
||||
--couldn't find node
|
||||
if #spawning_position_list <= 0 then
|
||||
break
|
||||
end
|
||||
|
||||
local spawning_position = spawning_position_list[math_random(1,#spawning_position_list)]
|
||||
|
||||
--Prevent strange behavior/too close to player
|
||||
if not spawning_position or vector_distance(player_pos, spawning_position) < 15 then
|
||||
break
|
||||
end
|
||||
|
||||
local gotten_node = get_node(spawning_position).name
|
||||
|
||||
if not gotten_node or gotten_node == "air" then --skip air nodes
|
||||
break
|
||||
end
|
||||
|
||||
local gotten_biome = minetest.get_biome_data(spawning_position)
|
||||
|
||||
if not gotten_biome then
|
||||
break --skip if in unloaded area
|
||||
end
|
||||
|
||||
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
||||
|
||||
--grab random mob
|
||||
local mob_def = spawn_dictionary[math.random(1,#spawn_dictionary)]
|
||||
|
||||
if not mob_def then
|
||||
break --skip if something ridiculous happens (nil mob def)
|
||||
end
|
||||
|
||||
--skip if not correct dimension
|
||||
if mob_def.dimension ~= dimension then
|
||||
break
|
||||
end
|
||||
|
||||
--skip if not in correct biome
|
||||
if not biome_check(mob_def.biomes, gotten_biome) then
|
||||
break
|
||||
end
|
||||
|
||||
--add this so mobs don't spawn inside nodes
|
||||
spawning_position.y = spawning_position.y + 1
|
||||
|
||||
if spawning_position.y < mob_def.min_height or spawning_position.y > mob_def.max_height then
|
||||
break
|
||||
end
|
||||
|
||||
--only need to poll for node light if everything else worked
|
||||
local gotten_light = get_node_light(spawning_position)
|
||||
|
||||
--don't spawn if not in light limits
|
||||
if gotten_light < mob_def.min_light or gotten_light > mob_def.max_light then
|
||||
break
|
||||
end
|
||||
|
||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
||||
|
||||
if mob_def.type_of_spawning == "ground" and is_water then
|
||||
break
|
||||
end
|
||||
|
||||
if mob_def.type_of_spawning == "ground" and is_lava then
|
||||
break
|
||||
end
|
||||
|
||||
--finally do the heavy check (for now) of mobs in area
|
||||
if count_mobs(spawning_position, mob_def.spawn_class) >= mob_def.aoc then
|
||||
break
|
||||
end
|
||||
|
||||
--adjust the position for water and lava mobs
|
||||
if mob_def.type_of_spawning == "water" or mob_def.type_of_spawning == "lava" then
|
||||
spawning_position.y = spawning_position.y - 1
|
||||
end
|
||||
|
||||
--everything is correct, spawn mob
|
||||
minetest.add_entity(spawning_position, mob_def.name)
|
||||
until true --this is a safety catch
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
|
@ -290,13 +290,13 @@ mobs_mc.spawn = {
|
|||
mobs_mc.spawn_height = {
|
||||
water = tonumber(minetest.settings:get("water_level")) or 0, -- Water level in the Overworld
|
||||
|
||||
-- Overworld boundaries (inclusive)
|
||||
overworld_min = -2999,
|
||||
-- Overworld boundaries (inclusive) --I adjusted this to be more reasonable
|
||||
overworld_min = -64,-- -2999,
|
||||
overworld_max = 31000,
|
||||
|
||||
-- Nether boundaries (inclusive)
|
||||
nether_min = -3369,
|
||||
nether_max = -3000,
|
||||
nether_min = -29067,-- -3369,
|
||||
nether_max = -28939,-- -3000,
|
||||
|
||||
-- End boundaries (inclusive)
|
||||
end_min = -6200,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--###################
|
||||
--################### AGENT
|
||||
--################### AGENT - seemingly unused
|
||||
--###################
|
||||
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
|
|
@ -64,7 +64,81 @@ else
|
|||
end
|
||||
|
||||
-- Spawn on solid blocks at or below Sea level and the selected light level
|
||||
mobs:spawn_specific("mobs_mc:bat", mobs_mc.spawn.solid, {"air"}, 0, maxlight, 20, 5000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-1)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:bat",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
},
|
||||
0,
|
||||
maxlight,
|
||||
20,
|
||||
5000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.water-1)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
-- daufinsyd
|
||||
-- My work is under the LGPL terms
|
||||
-- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models
|
||||
-- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models -hi 22i ~jordan4ibanez
|
||||
-- blaze.lua partial copy of mobs_mc/ghast.lua
|
||||
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
@ -75,9 +75,71 @@ mobs:register_mob("mobs_mc:blaze", {
|
|||
fear_height = 0,
|
||||
glow = 14,
|
||||
fire_resistant = true,
|
||||
do_custom = function(self)
|
||||
if self.state == "attack" and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then
|
||||
mcl_burning.set_on_fire(self.attack, 5)
|
||||
end
|
||||
local pos = self.object:get_pos()
|
||||
minetest.add_particle({
|
||||
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
|
||||
velocity = {x=0, y=math.random(1,1), z=0},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(1, 4),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_particles_smoke_anim.png^[colorize:#2c2c2c:255",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
length = 2.05,
|
||||
},
|
||||
})
|
||||
minetest.add_particle({
|
||||
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
|
||||
velocity = {x=0, y=math.random(1,1), z=0},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(1, 4),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_particles_smoke_anim.png^[colorize:#424242:255",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
length = 2.05,
|
||||
},
|
||||
})
|
||||
minetest.add_particle({
|
||||
pos = {x=pos.x+math.random(-0.7,0.7)*math.random()/2,y=pos.y+math.random(0.7,1.2),z=pos.z+math.random(-0.7,0.7)*math.random()/2},
|
||||
velocity = {x=0, y=math.random(1,1), z=0},
|
||||
expirationtime = math.random(),
|
||||
size = math.random(1, 4),
|
||||
collisiondetection = true,
|
||||
vertical = false,
|
||||
texture = "mcl_particles_smoke_anim.png^[colorize:#0f0f0f:255",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
length = 2.05,
|
||||
},
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:blaze", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:blaze",
|
||||
"nether",
|
||||
"ground",
|
||||
{"Nether"},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
5000,
|
||||
3,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- Blaze fireball
|
||||
mobs:register_arrow("mobs_mc:blaze_fireball", {
|
||||
|
|
|
@ -100,7 +100,34 @@ mobs:register_mob("mobs_mc:chicken", {
|
|||
})
|
||||
|
||||
--spawn
|
||||
mobs:spawn_specific("mobs_mc:chicken", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:chicken",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30, 17000,
|
||||
3,
|
||||
mobs_mc.spawn_height.water,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:chicken", S("Chicken"), "mobs_mc_spawn_icon_chicken.png", 0)
|
||||
|
|
|
@ -145,8 +145,53 @@ mobs:register_mob("mobs_mc:mooshroom", mooshroom_def)
|
|||
|
||||
|
||||
-- Spawning
|
||||
mobs:spawn_specific("mobs_mc:cow", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 10, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:mooshroom", mobs_mc.spawn.mushroom_island, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 5, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:cow",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
17000,
|
||||
10,
|
||||
mobs_mc.spawn_height.water,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:mooshroom",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"MushroomIslandShore",
|
||||
"MushroomIsland"
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
17000,
|
||||
5,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn egg
|
||||
mobs:register_egg("mobs_mc:cow", S("Cow"), "mobs_mc_spawn_icon_cow.png", 0)
|
||||
|
|
|
@ -39,6 +39,8 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" },
|
||||
attack_type = "explode",
|
||||
|
||||
--hssssssssssss
|
||||
|
||||
explosion_strength = 3,
|
||||
explosion_radius = 3.5,
|
||||
explosion_damage_radius = 3.5,
|
||||
|
@ -76,7 +78,6 @@ mobs:register_mob("mobs_mc:creeper", {
|
|||
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
|
||||
if self._forced_explosion_countdown_timer <= 0 then
|
||||
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
@ -139,6 +140,9 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
|||
pathfinding = 1,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_creeper.b3d",
|
||||
|
||||
--BOOM
|
||||
|
||||
textures = {
|
||||
{"mobs_mc_creeper.png",
|
||||
"mobs_mc_creeper_charge.png"},
|
||||
|
@ -195,7 +199,6 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
|||
self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime
|
||||
if self._forced_explosion_countdown_timer <= 0 then
|
||||
mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
@ -250,7 +253,158 @@ mobs:register_mob("mobs_mc:creeper_charged", {
|
|||
glow = 3,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:creeper", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 16500, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:creeper",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
7,
|
||||
20,
|
||||
16500,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:creeper", S("Creeper"), "mobs_mc_spawn_icon_creeper.png", 0)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mcl_mobs
|
|
@ -50,8 +50,8 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
arrow = "mobs_mc:dragon_fireball",
|
||||
shoot_interval = 0.5,
|
||||
shoot_offset = -1.0,
|
||||
xp_min = 12000,
|
||||
xp_max = 12000,
|
||||
xp_min = 500,
|
||||
xp_max = 500,
|
||||
animation = {
|
||||
fly_speed = 8, stand_speed = 8,
|
||||
stand_start = 0, stand_end = 20,
|
||||
|
@ -59,15 +59,47 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
run_start = 0, run_end = 20,
|
||||
},
|
||||
ignores_nametag = true,
|
||||
on_die = function(self, own_pos)
|
||||
if self._egg_spawn_pos then
|
||||
local pos = minetest.string_to_pos(self._egg_spawn_pos)
|
||||
--if minetest.get_node(pos).buildable_to then
|
||||
minetest.set_node(pos, {name = mobs_mc.items.dragon_egg})
|
||||
return
|
||||
--end
|
||||
do_custom = function(self)
|
||||
mcl_bossbars.update_boss(self.object, "Ender Dragon", "light_purple")
|
||||
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.name == "mcl_end:crystal" then
|
||||
if luaentity.beam then
|
||||
if luaentity.beam == self.beam then
|
||||
break
|
||||
end
|
||||
else
|
||||
if self.beam then
|
||||
self.beam:remove()
|
||||
end
|
||||
minetest.add_entity(self.object:get_pos(), "mcl_end:crystal_beam"):get_luaentity():init(self.object, obj)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if self._portal_pos then
|
||||
-- migrate old format
|
||||
if type(self._portal_pos) == "string" then
|
||||
self._portal_pos = minetest.string_to_pos(self._portal_pos)
|
||||
end
|
||||
local portal_center = vector.add(self._portal_pos, vector.new(3, 11, 3))
|
||||
local pos = self.object:get_pos()
|
||||
if vector.distance(pos, portal_center) > 50 then
|
||||
self.object:set_pos(self._last_good_pos or portal_center)
|
||||
else
|
||||
self._last_good_pos = pos
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_die = function(self, pos)
|
||||
if self._portal_pos then
|
||||
mcl_portals.spawn_gateway_portal()
|
||||
mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open")
|
||||
if self._initial then
|
||||
mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000
|
||||
minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg})
|
||||
end
|
||||
end
|
||||
minetest.add_item(own_pos, mobs_mc.items.dragon_egg)
|
||||
end,
|
||||
fire_resistant = true,
|
||||
})
|
||||
|
|
|
@ -295,7 +295,8 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
-- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE.
|
||||
-- Check for arrows and people nearby.
|
||||
local enderpos = self.object:get_pos()
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 4)
|
||||
enderpos.y = enderpos.y + 1.5
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 2)
|
||||
for n = 1, #objs do
|
||||
local obj = objs[n]
|
||||
if obj then
|
||||
|
@ -307,7 +308,7 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
else
|
||||
local lua = obj:get_luaentity()
|
||||
if lua then
|
||||
if lua.name == "mcl_bows:arrow_entity" then
|
||||
if lua.name == "mcl_bows:arrow_entity" or lua.name == "mcl_throwing:snowball_entity" then
|
||||
self:teleport(nil)
|
||||
end
|
||||
end
|
||||
|
@ -328,35 +329,44 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
--end
|
||||
end
|
||||
-- Check to see if people are near by enough to look at us.
|
||||
local objs = minetest.get_objects_inside_radius(enderpos, 64)
|
||||
local obj
|
||||
for n = 1, #objs do
|
||||
obj = objs[n]
|
||||
if obj then
|
||||
if minetest.is_player(obj) then
|
||||
for _,obj in pairs(minetest.get_connected_players()) do
|
||||
|
||||
--check if they are within radius
|
||||
local player_pos = obj:get_pos()
|
||||
if player_pos then -- prevent crashing in 1 in a million scenario
|
||||
|
||||
local ender_distance = vector.distance(enderpos, player_pos)
|
||||
if ender_distance <= 64 then
|
||||
|
||||
-- Check if they are looking at us.
|
||||
local player_pos = obj:get_pos()
|
||||
local look_dir_not_normalized = obj:get_look_dir()
|
||||
local look_dir = vector.normalize(look_dir_not_normalized)
|
||||
local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod.
|
||||
-- Cast up to 64 to see if player is looking at enderman.
|
||||
for n = 1,64,.25 do
|
||||
local node = minetest.get_node(look_pos)
|
||||
if node.name ~= "air" then
|
||||
break
|
||||
end
|
||||
if look_pos.x-1<enderpos.x and look_pos.x+1>enderpos.x and look_pos.y-2.89<enderpos.y and look_pos.y-2>enderpos.y and look_pos.z-1<enderpos.z and look_pos.z+1>enderpos.z then
|
||||
local player_eye_height = obj:get_properties().eye_height
|
||||
|
||||
--skip player if they have no data - log it
|
||||
if not player_eye_height then
|
||||
minetest.log("error", "Enderman at location: ".. dump(enderpos).." has indexed a null player!")
|
||||
else
|
||||
|
||||
--calculate very quickly the exact location the player is looking
|
||||
--within the distance between the two "heads" (player and enderman)
|
||||
local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z)
|
||||
local look_pos_base = look_pos
|
||||
local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z)
|
||||
local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos)
|
||||
look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player))
|
||||
|
||||
--if looking in general head position, turn hostile
|
||||
if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then
|
||||
self.provoked = "staring"
|
||||
self.attack = minetest.get_player_by_name(obj:get_player_name())
|
||||
break
|
||||
else
|
||||
else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez
|
||||
if self.provoked == "staring" then
|
||||
self.provoked = "broke_contact"
|
||||
end
|
||||
end
|
||||
look_pos.x = look_pos.x + (.25 * look_dir.x)
|
||||
look_pos.y = look_pos.y + (.25 * look_dir.y)
|
||||
look_pos.z = look_pos.z + (.25 * look_dir.z)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -534,9 +544,11 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
--if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then
|
||||
-- self:teleport(nil)
|
||||
--else
|
||||
if pr:next(1, 8) == 8 then --FIXME: real mc rate
|
||||
self:teleport(hitter)
|
||||
self.attack=hitter
|
||||
self.state="attack"
|
||||
end
|
||||
self.attack=hitter
|
||||
self.state="attack"
|
||||
--end
|
||||
end
|
||||
end,
|
||||
|
@ -549,11 +561,189 @@ mobs:register_mob("mobs_mc:enderman", {
|
|||
|
||||
|
||||
-- End spawn
|
||||
mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 3000, 12, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"end",
|
||||
"ground",
|
||||
{
|
||||
"End"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
3000,
|
||||
12,
|
||||
mobs_mc.spawn_height.end_min,
|
||||
mobs_mc.spawn_height.end_max)
|
||||
-- Overworld spawn
|
||||
mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 19000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
7,
|
||||
30,
|
||||
19000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- Nether spawn (rare)
|
||||
mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 27500, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:enderman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
27500,
|
||||
4,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0)
|
||||
|
|
|
@ -63,10 +63,32 @@ mobs:register_mob("mobs_mc:ghast", {
|
|||
makes_footstep_sound = false,
|
||||
instant_death = true,
|
||||
fire_resistant = true,
|
||||
do_custom = function(self)
|
||||
if self.firing == true then
|
||||
self.base_texture = {"mobs_mc_ghast_firing.png"}
|
||||
self.object:set_properties({textures=self.base_texture})
|
||||
else
|
||||
self.base_texture = {"mobs_mc_ghast.png"}
|
||||
self.object:set_properties({textures=self.base_texture})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:ghast", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 18000, 2, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:ghast",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
18000,
|
||||
2,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- fireball (projectile)
|
||||
mobs:register_arrow("mobs_mc:fireball", {
|
||||
|
@ -74,6 +96,7 @@ mobs:register_arrow("mobs_mc:fireball", {
|
|||
visual_size = {x = 1, y = 1},
|
||||
textures = {"mcl_fire_fire_charge.png"},
|
||||
velocity = 15,
|
||||
collisionbox = {-.5, -.5, -.5, .5, .5, .5},
|
||||
|
||||
hit_player = function(self, player)
|
||||
if rawget(_G, "armor") and armor.last_damage_types then
|
||||
|
|
|
@ -106,7 +106,7 @@ mobs:register_mob("mobs_mc:guardian_elder", {
|
|||
view_range = 16,
|
||||
})
|
||||
|
||||
-- Spawning disabled due to size issues
|
||||
-- Spawning disabled due to size issues <- what do you mean? -j4i
|
||||
-- TODO: Re-enable spawning
|
||||
-- mobs:spawn_specific("mobs_mc:guardian_elder", mobs_mc.spawn.water, mobs_mc.spawn_water, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-18)
|
||||
|
||||
|
|
|
@ -157,8 +157,29 @@ local horse = {
|
|||
self._regentimer = 0
|
||||
end
|
||||
|
||||
-- if driver present allow control of horse
|
||||
if self.driver then
|
||||
-- Some weird human is riding. Buck them off?
|
||||
if self.driver and not self.tamed and self.buck_off_time <= 0 then
|
||||
if math.random() < 0.2 then
|
||||
mobs.detach(self.driver, {x = 1, y = 0, z = 1})
|
||||
-- TODO bucking animation
|
||||
else
|
||||
-- Nah, can't be bothered. Think about it again in one second
|
||||
self.buck_off_time = 20
|
||||
end
|
||||
end
|
||||
|
||||
-- Tick the timer for trying to buck the player off
|
||||
if self.buck_off_time then
|
||||
if self.driver then
|
||||
self.buck_off_time = self.buck_off_time - 1
|
||||
else
|
||||
-- Player isn't riding anymore so no need to count
|
||||
self.buck_off_time = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- if driver present and horse has a saddle allow control of horse
|
||||
if self.driver and self._saddle then
|
||||
|
||||
mobs.drive(self, "walk", "stand", false, dtime)
|
||||
|
||||
|
@ -191,6 +212,49 @@ local horse = {
|
|||
local item = clicker:get_wielded_item()
|
||||
local iname = item:get_name()
|
||||
local heal = 0
|
||||
|
||||
-- Taming
|
||||
self.temper = self.temper or (math.random(1,100))
|
||||
|
||||
if not self.tamed then
|
||||
local temper_increase = 0
|
||||
|
||||
-- Feeding, intentionally not using mobs:feed_tame because horse taming is
|
||||
-- different and more complicated
|
||||
if (iname == mobs_mc.items.sugar) then
|
||||
temper_increase = 3
|
||||
elseif (iname == mobs_mc.items.wheat) then
|
||||
temper_increase = 3
|
||||
elseif (iname == mobs_mc.items.apple) then
|
||||
temper_increase = 3
|
||||
elseif (iname == mobs_mc.items.golden_carrot) then
|
||||
temper_increase = 5
|
||||
elseif (iname == mobs_mc.items.golden_apple) then
|
||||
temper_increase = 10
|
||||
-- Trying to ride
|
||||
elseif not self.driver then
|
||||
self.object:set_properties({stepheight = 1.1})
|
||||
mobs.attach(self, clicker)
|
||||
self.buck_off_time = 40 -- TODO how long does it take in minecraft?
|
||||
if self.temper > 100 then
|
||||
self.tamed = true -- NOTE taming can only be finished by riding the horse
|
||||
if not self.owner or self.owner == "" then
|
||||
self.owner = clicker:get_player_name()
|
||||
end
|
||||
end
|
||||
temper_increase = 5
|
||||
|
||||
-- Clicking on the horse while riding ==> unmount
|
||||
elseif self.driver and self.driver == clicker then
|
||||
mobs.detach(clicker, {x = 1, y = 0, z = 1})
|
||||
end
|
||||
|
||||
-- If nothing happened temper_increase = 0 and addition does nothing
|
||||
self.temper = self.temper + temper_increase
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if can_breed(self.name) then
|
||||
-- Breed horse with golden apple or golden carrot
|
||||
if (iname == mobs_mc.items.golden_apple) then
|
||||
|
@ -202,7 +266,8 @@ local horse = {
|
|||
return
|
||||
end
|
||||
end
|
||||
-- Feed/tame with anything else
|
||||
-- Feed with anything else
|
||||
-- TODO heal amounts don't work
|
||||
if (iname == mobs_mc.items.sugar) then
|
||||
heal = 1
|
||||
elseif (iname == mobs_mc.items.wheat) then
|
||||
|
@ -212,7 +277,7 @@ local horse = {
|
|||
elseif (iname == mobs_mc.items.hay_bale) then
|
||||
heal = 20
|
||||
end
|
||||
if heal > 0 and mobs:feed_tame(self, clicker, heal, false, true) then
|
||||
if heal > 0 and mobs:feed_tame(self, clicker, heal, false, false) then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -445,8 +510,56 @@ mobs:register_mob("mobs_mc:mule", mule)
|
|||
|
||||
--===========================
|
||||
--Spawn Function
|
||||
mobs:spawn_specific("mobs_mc:horse", mobs_mc.spawn.grassland_savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:donkey", mobs_mc.spawn.grassland_savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:horse",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
4,
|
||||
mobs_mc.spawn_height.water+3,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:donkey",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
4,
|
||||
mobs_mc.spawn_height.water+3,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
|
||||
|
|
|
@ -217,7 +217,25 @@ mobs:register_mob("mobs_mc:llama", {
|
|||
})
|
||||
|
||||
--spawn
|
||||
mobs:spawn_specific("mobs_mc:llama", mobs_mc.spawn.savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 5, mobs_mc.spawn_height.water+15, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:llama",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Mesa",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"MesaPlateauF",
|
||||
"MesaPlateauFM",
|
||||
"MesaPlateauF_grasstop",
|
||||
"MesaBryce",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
5,
|
||||
mobs_mc.spawn_height.water+15,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0)
|
||||
|
|
|
@ -152,6 +152,25 @@ mobs:register_mob("mobs_mc:cat", cat)
|
|||
local base_spawn_chance = 5000
|
||||
|
||||
-- Spawn ocelot
|
||||
--they get the same as the llama because I'm trying to rework so much of this code right now -j4i
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:ocelot",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Jungle",
|
||||
"JungleEdgeM",
|
||||
"JungleM",
|
||||
"JungleEdge",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
5,
|
||||
mobs_mc.spawn_height.water+15,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
--[[
|
||||
mobs:spawn({
|
||||
name = "mobs_mc:ocelot",
|
||||
nodes = mobs_mc.spawn.jungle,
|
||||
|
@ -163,8 +182,8 @@ mobs:spawn({
|
|||
min_height = mobs_mc.spawn_height.water+1, -- Right above ocean level
|
||||
max_height = mobs_mc.spawn_height.overworld_max,
|
||||
on_spawn = function(self, pos)
|
||||
--[[ Note: Minecraft has a 1/3 spawn failure rate.
|
||||
In this mod it is emulated by reducing the spawn rate accordingly (see above). ]]
|
||||
Note: Minecraft has a 1/3 spawn failure rate.
|
||||
In this mod it is emulated by reducing the spawn rate accordingly (see above).
|
||||
|
||||
-- 1/7 chance to spawn 2 ocelot kittens
|
||||
if pr:next(1,7) == 1 then
|
||||
|
@ -207,6 +226,7 @@ mobs:spawn({
|
|||
end
|
||||
end,
|
||||
})
|
||||
]]--
|
||||
|
||||
-- spawn eggs
|
||||
-- FIXME: The spawn icon shows a cat texture, not an ocelot texture
|
||||
|
|
|
@ -90,8 +90,24 @@ mobs:register_mob("mobs_mc:parrot", {
|
|||
|
||||
})
|
||||
|
||||
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome*
|
||||
mobs:spawn_specific("mobs_mc:parrot", {"mcl_core:jungletree", "mcl_core:jungleleaves"}, {"air"}, 0, minetest.LIGHT_MAX+1, 7, 30000, 1, mobs_mc.spawn_height.water+7, mobs_mc.spawn_height.overworld_max)
|
||||
-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome* <- I'll get to this eventually -j4i
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:parrot",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Jungle",
|
||||
"JungleEdgeM",
|
||||
"JungleM",
|
||||
"JungleEdge",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
7,
|
||||
30000,
|
||||
1,
|
||||
mobs_mc.spawn_height.water+7,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0)
|
||||
|
|
|
@ -182,7 +182,35 @@ mobs:register_mob("mobs_mc:pig", {
|
|||
end,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:pig", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 15000, 8, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:pig",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
8,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:pig", S("Pig"), "mobs_mc_spawn_icon_pig.png", 0)
|
||||
|
|
|
@ -67,7 +67,23 @@ mobs:register_mob("mobs_mc:polar_bear", {
|
|||
})
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:polar_bear", mobs_mc.spawn.snow, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 7000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:polar_bear",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"ColdTaiga",
|
||||
"IcePlainsSpikes",
|
||||
"IcePlains",
|
||||
"ExtremeHills+_snowtop",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
7000,
|
||||
3,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn egg
|
||||
mobs:register_egg("mobs_mc:polar_bear", S("Polar Bear"), "mobs_mc_spawn_icon_polarbear.png", 0)
|
||||
|
|
|
@ -107,8 +107,39 @@ end
|
|||
mobs:register_mob("mobs_mc:killer_bunny", killer_bunny)
|
||||
|
||||
-- Mob spawning rules.
|
||||
-- Different skins depending on spawn location
|
||||
-- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:rabbit",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
9,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
8,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
--[[
|
||||
local spawn = {
|
||||
name = "mobs_mc:rabbit",
|
||||
neighbors = {"air"},
|
||||
|
@ -165,6 +196,7 @@ spawn_grass.on_spawn = function(self, pos)
|
|||
self.object:set_properties({textures = self.base_texture})
|
||||
end
|
||||
mobs:spawn(spawn_grass)
|
||||
]]--
|
||||
|
||||
-- Spawn egg
|
||||
mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0)
|
||||
|
|
|
@ -303,7 +303,35 @@ mobs:register_mob("mobs_mc:sheep", {
|
|||
end
|
||||
end,
|
||||
})
|
||||
mobs:spawn_specific("mobs_mc:sheep", mobs_mc.spawn.grassland, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:sheep",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
3,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:sheep", S("Sheep"), "mobs_mc_spawn_icon_sheep.png", 0)
|
||||
|
|
|
@ -81,4 +81,17 @@ mobs:register_arrow("mobs_mc:shulkerbullet", {
|
|||
|
||||
mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0)
|
||||
|
||||
mobs:spawn_specific("mobs_mc:shulker", mobs_mc.spawn.end_city, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 2, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:shulker",
|
||||
"end",
|
||||
"ground",
|
||||
{
|
||||
"End"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
5000,
|
||||
2,
|
||||
mobs_mc.spawn_height.end_min,
|
||||
mobs_mc.spawn_height.end_max)
|
||||
|
|
|
@ -139,13 +139,195 @@ table.insert(stray.drops, {
|
|||
mobs:register_mob("mobs_mc:stray", stray)
|
||||
|
||||
-- Overworld spawn
|
||||
mobs:spawn_specific("mobs_mc:skeleton", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:skeleton",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
7,
|
||||
20,
|
||||
17000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
-- Nether spawn
|
||||
mobs:spawn_specific("mobs_mc:skeleton", mobs_mc.spawn.nether_fortress, {"air"}, 0, 7, 30, 10000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:skeleton",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
10000,
|
||||
3,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- Stray spawn
|
||||
-- TODO: Spawn directly under the sky
|
||||
mobs:spawn_specific("mobs_mc:stray", mobs_mc.spawn.snow, {"air"}, 0, 7, 20, 19000, 2, mobs_mc.spawn_height.water, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:stray",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"ColdTaiga",
|
||||
"IcePlainsSpikes",
|
||||
"IcePlains",
|
||||
"ExtremeHills+_snowtop",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
20,
|
||||
19000,
|
||||
2,
|
||||
mobs_mc.spawn_height.water,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -94,7 +94,20 @@ mobs:register_mob("mobs_mc:witherskeleton", {
|
|||
})
|
||||
|
||||
--spawn
|
||||
mobs:spawn_specific("mobs_mc:witherskeleton", mobs_mc.spawn.nether_fortress, {"air"}, 0, 7, 30, 5000, 5, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:witherskeleton",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
5000,
|
||||
5,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:witherskeleton", S("Wither Skeleton"), "mobs_mc_spawn_icon_witherskeleton.png", 0)
|
|
@ -51,7 +51,6 @@ local spawn_children_on_die = function(child_mob, children_count, spawn_distance
|
|||
end
|
||||
end, children, self.attack)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -158,9 +157,137 @@ mobs:register_mob("mobs_mc:slime_tiny", slime_tiny)
|
|||
local smin = mobs_mc.spawn_height.overworld_min
|
||||
local smax = mobs_mc.spawn_height.water - 23
|
||||
|
||||
mobs:spawn_specific("mobs_mc:slime_tiny", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 12000, 4, smin, smax)
|
||||
mobs:spawn_specific("mobs_mc:slime_small", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 8500, 4, smin, smax)
|
||||
mobs:spawn_specific("mobs_mc:slime_big", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 10000, 4, smin, smax)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:slime_tiny",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
12000,
|
||||
4,
|
||||
smin,
|
||||
smax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:slime_small",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
8500,
|
||||
4,
|
||||
smin,
|
||||
smax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:slime_big",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
10000,
|
||||
4,
|
||||
smin,
|
||||
smax)
|
||||
|
||||
-- Magma cube
|
||||
local magma_cube_big = {
|
||||
|
@ -273,13 +400,55 @@ mobs:register_mob("mobs_mc:magma_cube_tiny", magma_cube_tiny)
|
|||
local mmin = mobs_mc.spawn_height.nether_min
|
||||
local mmax = mobs_mc.spawn_height.nether_max
|
||||
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15500, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 16000, 4, mmin, mmax)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:magma_cube_tiny",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15000,
|
||||
4,
|
||||
mmin,
|
||||
mmax)
|
||||
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax)
|
||||
mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:magma_cube_small",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
15500,
|
||||
4,
|
||||
mmin,
|
||||
mmax)
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:magma_cube_big",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
16000,
|
||||
4,
|
||||
mmin,
|
||||
mmax)
|
||||
|
||||
--mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax)
|
||||
--mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax)
|
||||
--mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax)
|
||||
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -87,7 +87,158 @@ cave_spider.sounds.base_pitch = 1.25
|
|||
mobs:register_mob("mobs_mc:cave_spider", cave_spider)
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:spider", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:spider",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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,
|
||||
7,
|
||||
30,
|
||||
17000,
|
||||
2,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:spider", S("Spider"), "mobs_mc_spawn_icon_spider.png", 0)
|
||||
|
|
|
@ -62,7 +62,158 @@ mobs:register_mob("mobs_mc:squid", {
|
|||
|
||||
local water = mobs_mc.spawn_height.water
|
||||
--name, nodes, neighbours, minlight, maxlight, interval, chance, active_object_count, min_height, max_height
|
||||
mobs:spawn_specific("mobs_mc:squid", mobs_mc.spawn.water, {mobs_mc.items.water_source}, 0, minetest.LIGHT_MAX+1, 30, 5500, 3, water-16, water)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:squid",
|
||||
"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,
|
||||
5500,
|
||||
3,
|
||||
water-16,
|
||||
water+1)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:squid", S("Squid"), "mobs_mc_spawn_icon_squid.png", 0)
|
||||
|
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -1074,7 +1074,35 @@ mobs:register_mob("mobs_mc:villager", {
|
|||
|
||||
|
||||
|
||||
mobs:spawn_specific("mobs_mc:villager", mobs_mc.spawn.village, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 20, 4, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:villager",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"FlowerForest",
|
||||
"Swampland",
|
||||
"Taiga",
|
||||
"ExtremeHills",
|
||||
"BirchForest",
|
||||
"MegaSpruceTaiga",
|
||||
"MegaTaiga",
|
||||
"ExtremeHills+",
|
||||
"Forest",
|
||||
"Plains",
|
||||
"ColdTaiga",
|
||||
"SunflowerPlains",
|
||||
"RoofedForest",
|
||||
"MesaPlateauFM_grasstop",
|
||||
"ExtremeHillsM",
|
||||
"BirchForestM",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
20,
|
||||
4,
|
||||
mobs_mc.spawn_height.water+1,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0)
|
||||
|
|
|
@ -146,8 +146,99 @@ mobs:register_mob("mobs_mc:villager_zombie", {
|
|||
harmed_by_heal = true,
|
||||
})
|
||||
|
||||
mobs:spawn_specific("mobs_mc:villager_zombie", mobs_mc.spawn.village, {"air"}, 0, 7, 30, 4090, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:villager_zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:villager_zombie",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
4090,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
--mobs:spawn_specific("mobs_mc:villager_zombie", "overworld", "ground", 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:villager_zombie", S("Zombie Villager"), "mobs_mc_spawn_icon_zombie_villager.png", 0)
|
||||
|
|
|
@ -99,7 +99,7 @@ mobs:register_arrow("mobs_mc:potion_arrow", {
|
|||
end
|
||||
})
|
||||
|
||||
-- TODO: Spawn when witch works properly
|
||||
-- TODO: Spawn when witch works properly <- eventually -j4i
|
||||
--mobs:spawn_specific("mobs_mc:witch", mobs_mc.spawn.jungle, {"air"}, 0, minetest.LIGHT_MAX-6, 12, 20000, 2, mobs_mc.spawn_height.water-6, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
|
|
|
@ -73,6 +73,7 @@ mobs:register_mob("mobs_mc:wither", {
|
|||
self.object:set_properties({textures={self.base_texture}})
|
||||
self.armor = {undead = 80, fleshy = 80}
|
||||
end
|
||||
mcl_bossbars.update_boss(self.object, "Wither", "dark_purple")
|
||||
end,
|
||||
on_spawn = function(self)
|
||||
minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64})
|
||||
|
|
|
@ -232,6 +232,34 @@ end
|
|||
mobs:register_mob("mobs_mc:dog", dog)
|
||||
|
||||
-- Spawn
|
||||
mobs:spawn_specific("mobs_mc:wolf", mobs_mc.spawn.wolf, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 9000, 7, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max)
|
||||
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",
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
9000,
|
||||
7,
|
||||
mobs_mc.spawn_height.water+3,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
mobs:register_egg("mobs_mc:wolf", S("Wolf"), "mobs_mc_spawn_icon_wolf.png", 0)
|
||||
|
|
|
@ -135,11 +135,227 @@ mobs:register_mob("mobs_mc:baby_husk", baby_husk)
|
|||
|
||||
-- Spawning
|
||||
|
||||
mobs:spawn_specific("mobs_mc:zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 6000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:zombie",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
6000,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
-- Baby zombie is 20 times less likely than regular zombies
|
||||
mobs:spawn_specific("mobs_mc:baby_zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:husk", mobs_mc.spawn.desert, {"air"}, 0, 7, 30, 6500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific("mobs_mc:baby_husk", mobs_mc.spawn.desert, {"air"}, 0, 7, 30, 65000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:baby_zombie",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
60000,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:husk",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Desert",
|
||||
"SavannaM",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
6500,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:baby_husk",
|
||||
"overworld",
|
||||
"ground",
|
||||
{
|
||||
"Desert",
|
||||
"SavannaM",
|
||||
"Savanna",
|
||||
"Savanna_beach",
|
||||
},
|
||||
0,
|
||||
7,
|
||||
30,
|
||||
65000,
|
||||
4,
|
||||
mobs_mc.spawn_height.overworld_min,
|
||||
mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- Spawn eggs
|
||||
mobs:register_egg("mobs_mc:husk", S("Husk"), "mobs_mc_spawn_icon_husk.png", 0)
|
||||
|
|
|
@ -111,12 +111,38 @@ baby_pigman.child = 1
|
|||
mobs:register_mob("mobs_mc:baby_pigman", baby_pigman)
|
||||
|
||||
-- Regular spawning in the Nether
|
||||
mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 6000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:pigman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
6000,
|
||||
3,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
-- Baby zombie is 20 times less likely than regular zombies
|
||||
mobs:spawn_specific("mobs_mc:baby_pigman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 100000, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max)
|
||||
mobs:spawn_specific(
|
||||
"mobs_mc:baby_pigman",
|
||||
"nether",
|
||||
"ground",
|
||||
{
|
||||
"Nether"
|
||||
},
|
||||
0,
|
||||
minetest.LIGHT_MAX+1,
|
||||
30,
|
||||
100000,
|
||||
4,
|
||||
mobs_mc.spawn_height.nether_min,
|
||||
mobs_mc.spawn_height.nether_max)
|
||||
|
||||
-- Spawning in Nether portals in the Overworld
|
||||
mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.nether_portal, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
--mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.nether_portal, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max)
|
||||
|
||||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:pigman", S("Zombie Pigman"), "mobs_mc_spawn_icon_zombie_pigman.png", 0)
|
||||
|
|
|
@ -45,7 +45,7 @@ a vertical gradient.
|
|||
### Icon
|
||||
A 16×16 image shown left of the HUD bar. This is optional.
|
||||
|
||||
### `hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)`
|
||||
### `hb.register_hudbar(identifier, text_color, label, textures, direction, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)`
|
||||
This function registers a new custom HUD bar definition to the HUD bars mod, so it can be later used to be displayed, changed, hidden
|
||||
and unhidden on a per-player basis.
|
||||
Note this does not yet display the HUD bar.
|
||||
|
@ -63,6 +63,7 @@ for more information.
|
|||
* `bar`: The file name of the bar image (as string). This is only used for the `progress_bar` bar type (see `README.txt`, settings section).
|
||||
* `icon`: The file name of the icon, as string. For the `progress_bar` type, it is shown as single image left of the bar, for the two statbar bar types, it is used as the statbar icon and will be repeated. This field can be `nil`, in which case no icon will be used, but this is not recommended, because the HUD bar will be invisible if the one of the statbar bar types is used.
|
||||
* `bgicon`: The file name of the background icon, it is used as the background for the modern statbar mode only. This field can be `nil`, in which case no background icon will be displayed in this mode.
|
||||
* `direction`: Either left to right(0), or right to left(1).
|
||||
* `default_start_value`: If this HUD bar is added to a player, and no initial value is specified, this value will be used as initial current value
|
||||
* `default_max_value`: If this HUD bar is added to a player, and no initial maximum value is specified, this value will be used as initial maximum value
|
||||
* `default_start_hidden`: The HUD bar will be initially start hidden by default when added to a player. Use `hb.unhide_hudbar` to unhide it.
|
||||
|
|
|
@ -20,9 +20,9 @@ if hb.settings.bar_type == "progress_bar" then
|
|||
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_offset_right_x", "number", 15)
|
||||
hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_offset_right_y", "number", -86)
|
||||
else
|
||||
hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -265)
|
||||
hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -258)
|
||||
hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_statbar_offset_left_y", "number", -90)
|
||||
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 25)
|
||||
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 16)
|
||||
hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_statbar_offset_right_y", "number", -90)
|
||||
end
|
||||
-- Modified in MCL2!
|
||||
|
|
|
@ -124,7 +124,7 @@ function hb.get_hudbar_position_index(identifier)
|
|||
end
|
||||
end
|
||||
|
||||
function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)
|
||||
function hb.register_hudbar(identifier, text_color, label, textures, direction, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)
|
||||
minetest.log("action", "hb.register_hudbar: "..tostring(identifier))
|
||||
local hudtable = {}
|
||||
local pos, offset
|
||||
|
@ -133,30 +133,33 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
if hb.settings.alignment_pattern == "stack_up" then
|
||||
pos = hb.settings.pos_left
|
||||
offset = {
|
||||
x = hb.settings.start_offset_left.x,
|
||||
x = direction == 0 and hb.settings.start_offset_left.x or -hb.settings.start_offset_right.x,
|
||||
y = hb.settings.start_offset_left.y - hb.settings.vmargin * index
|
||||
}
|
||||
elseif hb.settings.alignment_pattern == "stack_down" then
|
||||
pos = hb.settings.pos_left
|
||||
offset = {
|
||||
x = hb.settings.start_offset_left.x,
|
||||
x = direction == 0 and hb.settings.start_offset_right.x or -hb.settings.start_offset_left.x,
|
||||
y = hb.settings.start_offset_left.y + hb.settings.vmargin * index
|
||||
}
|
||||
else
|
||||
else -- zigzag
|
||||
if index % 2 == 0 then
|
||||
pos = hb.settings.pos_left
|
||||
offset = {
|
||||
x = hb.settings.start_offset_left.x,
|
||||
-- -(24+18) = -42. using linear eq, -42 = -258m - 24.
|
||||
x = direction == 0 and hb.settings.start_offset_left.x or (-42+24)/(-258.0) * hb.settings.start_offset_left.x - 24,
|
||||
y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2)
|
||||
}
|
||||
else
|
||||
pos = hb.settings.pos_right
|
||||
offset = {
|
||||
x = hb.settings.start_offset_right.x,
|
||||
-- 24*10+30 - 24 = 234. using linear eq, 234 = 16m - 24.
|
||||
x = direction == 0 and hb.settings.start_offset_right.x or (234+24)/(16) * hb.settings.start_offset_right.x - 24,
|
||||
y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if format_string == nil then
|
||||
format_string = N("@1: @2/@3")
|
||||
end
|
||||
|
@ -181,6 +184,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
local state = {}
|
||||
local name = player:get_player_name()
|
||||
local bgscale, iconscale, text, barnumber, bgiconnumber
|
||||
|
||||
if start_max == 0 or start_hidden then
|
||||
bgscale = { x=0, y=0 }
|
||||
else
|
||||
|
@ -197,6 +201,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
bgiconnumber = hb.settings.statbar_length
|
||||
text = make_label(format_string, format_string_config, label, start_value, start_max)
|
||||
end
|
||||
|
||||
if hb.settings.bar_type == "progress_bar" then
|
||||
ids.bg = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
|
@ -219,6 +224,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
})
|
||||
end
|
||||
end
|
||||
|
||||
local bar_image, bgicon, bar_size
|
||||
if hb.settings.bar_type == "progress_bar" then
|
||||
bar_image = textures.bar
|
||||
|
@ -234,10 +240,12 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
bgicon = textures.bgicon
|
||||
bar_size = {x=24, y=24}
|
||||
end
|
||||
|
||||
local text2
|
||||
if hb.settings.bar_type == "statbar_modern" then
|
||||
text2 = bgicon
|
||||
end
|
||||
|
||||
ids.bar = player:hud_add({
|
||||
hud_elem_type = "statbar",
|
||||
position = pos,
|
||||
|
@ -247,7 +255,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
item = bgiconnumber,
|
||||
alignment = {x=-1,y=-1},
|
||||
offset = offset,
|
||||
direction = 0,
|
||||
direction = direction,
|
||||
size = bar_size,
|
||||
z_index = 1,
|
||||
})
|
||||
|
@ -258,7 +266,7 @@ function hb.register_hudbar(identifier, text_color, label, textures, default_sta
|
|||
text = text,
|
||||
alignment = {x=1,y=1},
|
||||
number = text_color,
|
||||
direction = 0,
|
||||
direction = direction,
|
||||
offset = { x = offset.x + 2, y = offset.y - 1},
|
||||
z_index = 2,
|
||||
})
|
||||
|
@ -359,6 +367,7 @@ function hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon
|
|||
if new_text_color ~= nil then
|
||||
player:hud_change(hudtable.hudids[name].text, "number", new_text_color)
|
||||
end
|
||||
|
||||
else
|
||||
if new_icon ~= nil and hudtable.hudids[name].bar ~= nil then
|
||||
player:hud_change(hudtable.hudids[name].bar, "text", new_icon)
|
||||
|
@ -474,8 +483,8 @@ end
|
|||
|
||||
--register built-in HUD bars
|
||||
if minetest.settings:get_bool("enable_damage") or hb.settings.forceload_default_hudbars then
|
||||
hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 20, 20, false)
|
||||
hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png", bgicon = "hudbars_bgicon_breath.png" }, 10, 10, true)
|
||||
hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 0, 20, 20, false)
|
||||
hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png", bgicon = "hudbars_bgicon_breath.png" }, 1, 10, 10, true)
|
||||
end
|
||||
|
||||
local function hide_builtin(player)
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
mcl_bossbars = {
|
||||
bars = {},
|
||||
huds = {},
|
||||
static = {},
|
||||
colors = {"light_purple", "blue", "red", "green", "yellow", "dark_purple", "white"},
|
||||
max_bars = tonumber(minetest.settings:get("max_bossbars")) or 4
|
||||
}
|
||||
|
||||
function mcl_bossbars.recalculate_colors()
|
||||
local sorted = {}
|
||||
local colors = mcl_bossbars.colors
|
||||
local color_count = #colors
|
||||
local frame_count = color_count * 2
|
||||
for i, color in ipairs(colors) do
|
||||
local idx = i * 2 - 1
|
||||
local image = "mcl_bossbars.png"
|
||||
.. "^[transformR270"
|
||||
.. "^[verticalframe:" .. frame_count .. ":" .. (idx - 1)
|
||||
.. "^(mcl_bossbars_empty.png"
|
||||
.. "^[lowpart:%d:mcl_bossbars.png"
|
||||
.. "^[transformR270"
|
||||
.. "^[verticalframe:" .. frame_count .. ":" .. idx .. ")"
|
||||
local _, hex = mcl_util.get_color(color)
|
||||
sorted[color] = {
|
||||
image = image,
|
||||
hex = hex,
|
||||
}
|
||||
end
|
||||
mcl_bossbars.colors_sorted = sorted
|
||||
end
|
||||
|
||||
local function get_color_info(color, percentage)
|
||||
local cdef = mcl_bossbars.colors_sorted[color]
|
||||
return cdef.hex, string.format(cdef.image, percentage)
|
||||
end
|
||||
|
||||
local last_id = 0
|
||||
|
||||
function mcl_bossbars.add_bar(player, def, dynamic, priority)
|
||||
local name = player:get_player_name()
|
||||
local bars = mcl_bossbars.bars[name]
|
||||
local bar = {text = def.text, priority = priority or 0, timeout = def.timeout}
|
||||
bar.color, bar.image = get_color_info(def.color, def.percentage)
|
||||
if dynamic then
|
||||
for _, other in pairs(bars) do
|
||||
if not other.id and other.color == bar.color and (other.original_text or other.text) == bar.text and other.image == bar.image then
|
||||
if not other.count then
|
||||
other.count = 1
|
||||
other.original_text = other.text
|
||||
end
|
||||
other.count = other.count + 1
|
||||
other.text = other.original_text .. " x" .. other.count
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(bars, bar)
|
||||
if not dynamic then
|
||||
bar.raw_color = def.color
|
||||
bar.id = last_id + 1
|
||||
last_id = bar.id
|
||||
mcl_bossbars.static[bar.id] = bar
|
||||
return bar.id
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_bossbars.remove_bar(id)
|
||||
mcl_bossbars.static[id].id = nil
|
||||
mcl_bossbars.static[id] = nil
|
||||
end
|
||||
|
||||
function mcl_bossbars.update_bar(id, def, priority)
|
||||
local old = mcl_bossbars.static[id]
|
||||
old.color = get_color_info(def.color or old.raw_color, def.percentage or old.percentage)
|
||||
old.text = def.text or old.text
|
||||
old.priority = priority or old.priority
|
||||
end
|
||||
|
||||
function mcl_bossbars.update_boss(object, name, color)
|
||||
local props = object:get_luaentity()
|
||||
if not props or not props._cmi_is_mob then
|
||||
props = object:get_properties()
|
||||
props.health = object:get_hp()
|
||||
end
|
||||
|
||||
local bardef = {
|
||||
color = color,
|
||||
text = props.nametag,
|
||||
percentage = math.floor(props.health / props.hp_max * 100),
|
||||
}
|
||||
|
||||
if not bardef.text or bardef.text == "" then
|
||||
bardef.text = name
|
||||
end
|
||||
|
||||
local pos = object:get_pos()
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
local d = vector.distance(pos, player:get_pos())
|
||||
if d <= 80 then
|
||||
mcl_bossbars.add_bar(player, bardef, true, d)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mcl_bossbars.huds[name] = {}
|
||||
mcl_bossbars.bars[name] = {}
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
mcl_bossbars.huds[name] = nil
|
||||
for _, bar in pairs(mcl_bossbars.bars[name]) do
|
||||
if bar.id then
|
||||
mcl_bossbars.static[bar.id] = nil
|
||||
end
|
||||
end
|
||||
mcl_bossbars.bars[name] = nil
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local bars = mcl_bossbars.bars[name]
|
||||
local huds = mcl_bossbars.huds[name]
|
||||
table.sort(bars, function(a, b) return a.priority < b.priority end)
|
||||
local huds_new = {}
|
||||
local bars_new = {}
|
||||
local i = 0
|
||||
|
||||
while #huds > 0 or #bars > 0 do
|
||||
local bar = table.remove(bars, 1)
|
||||
local hud = table.remove(huds, 1)
|
||||
|
||||
if bar and bar.id then
|
||||
if bar.timeout then
|
||||
bar.timeout = bar.timeout - dtime
|
||||
end
|
||||
if not bar.timeout or bar.timeout > 0 then
|
||||
table.insert(bars_new, bar)
|
||||
end
|
||||
end
|
||||
|
||||
if bar and not hud then
|
||||
if i < mcl_bossbars.max_bars then
|
||||
hud = {
|
||||
color = bar.color,
|
||||
image = bar.image,
|
||||
text = bar.text,
|
||||
text_id = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
text = bar.text,
|
||||
number = bar.color,
|
||||
position = {x = 0.5, y = 0},
|
||||
alignment = {x = 0, y = 1},
|
||||
offset = {x = 0, y = i * 40},
|
||||
}),
|
||||
image_id = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
text = bar.image,
|
||||
position = {x = 0.5, y = 0},
|
||||
alignment = {x = 0, y = 1},
|
||||
offset = {x = 0, y = i * 40 + 25},
|
||||
scale = {x = 3, y = 3},
|
||||
}),
|
||||
}
|
||||
end
|
||||
elseif hud and not bar then
|
||||
player:hud_remove(hud.text_id)
|
||||
player:hud_remove(hud.image_id)
|
||||
hud = nil
|
||||
else
|
||||
if bar.text ~= hud.text then
|
||||
player:hud_change(hud.text_id, "text", bar.text)
|
||||
hud.text = bar.text
|
||||
end
|
||||
|
||||
if bar.color ~= hud.color then
|
||||
player:hud_change(hud.text_id, "number", bar.color)
|
||||
hud.color = bar.color
|
||||
end
|
||||
|
||||
if bar.image ~= hud.image then
|
||||
player:hud_change(hud.image_id, "text", bar.image)
|
||||
hud.image = bar.image
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(huds_new, hud)
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
mcl_bossbars.huds[name] = huds_new
|
||||
mcl_bossbars.bars[name] = bars_new
|
||||
end
|
||||
end)
|
||||
|
||||
mcl_bossbars.recalculate_colors()
|
|
@ -0,0 +1,4 @@
|
|||
name = mcl_bossbars
|
||||
author = Fleckenstein
|
||||
description = Show enderdragon & wither boss bars. Also allows custom bars.
|
||||
depends = mcl_util, mcl_colors
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.3 KiB |
|
@ -0,0 +1,209 @@
|
|||
mcl_credits = {
|
||||
players = {},
|
||||
}
|
||||
|
||||
mcl_credits.description = "A faithful Open Source clone of Minecraft"
|
||||
|
||||
-- Sub-lists are sorted by number of commits, but the list should not be rearranged (-> new contributors are just added at the end of the list)
|
||||
mcl_credits.people = {
|
||||
{"Creator of MineClone", 0x0A9400, {
|
||||
"davedevils",
|
||||
}},
|
||||
{"Creator of MineClone2", 0xFBF837, {
|
||||
"Wuzzy",
|
||||
}},
|
||||
{"Maintainers", 0xFF51D5, {
|
||||
"Fleckenstein",
|
||||
"kay27",
|
||||
"oilboi",
|
||||
}},
|
||||
{"Developers", 0xF84355, {
|
||||
"bzoss",
|
||||
"AFCMS",
|
||||
"epCode",
|
||||
"ryvnf",
|
||||
"iliekprogrammar",
|
||||
"MysticTempest",
|
||||
"Rootyjr",
|
||||
"Nicu",
|
||||
"aligator",
|
||||
}},
|
||||
{"Contributors", 0x52FF00, {
|
||||
"Code-Sploit",
|
||||
"Laurent Rocher",
|
||||
"HimbeerserverDE",
|
||||
"TechDudie",
|
||||
"Alexander Minges",
|
||||
"ArTee3",
|
||||
"ZeDique la Ruleta",
|
||||
"pitchum",
|
||||
"wuniversales",
|
||||
"Bu-Gee",
|
||||
"David McMackins II",
|
||||
"Nicholas Niro",
|
||||
"Wouters Dorian",
|
||||
"Blue Blancmange",
|
||||
"Jared Moody",
|
||||
"Li0n",
|
||||
"Midgard",
|
||||
"NO11",
|
||||
"Saku Laesvuori",
|
||||
"Yukitty",
|
||||
"ZedekThePD",
|
||||
"aldum",
|
||||
"dBeans",
|
||||
"nickolas360",
|
||||
"yutyo",
|
||||
"ztianyang",
|
||||
}},
|
||||
{"MineClone5", 0xA60014, {
|
||||
"kay27",
|
||||
"Debiankaios",
|
||||
"epCode",
|
||||
"NO11",
|
||||
"j45",
|
||||
}},
|
||||
{"3D Models", 0x0019FF, {
|
||||
"22i",
|
||||
"tobyplowy",
|
||||
"epCode",
|
||||
}},
|
||||
{"Textures", 0xFF9705, {
|
||||
"XSSheep",
|
||||
"Wuzzy",
|
||||
"kingoscargames",
|
||||
"leorockway",
|
||||
"xMrVizzy",
|
||||
"yutyo"
|
||||
}},
|
||||
{"Translations", 0x00FF60, {
|
||||
"Wuzzy",
|
||||
"Rocher Laurent",
|
||||
"wuniversales",
|
||||
"kay27",
|
||||
"pitchum",
|
||||
}},
|
||||
}
|
||||
|
||||
local function add_hud_element(def, huds, y)
|
||||
def.alignment = {x = 0, y = 0}
|
||||
def.position = {x = 0.5, y = 0}
|
||||
def.offset = {x = 0, y = y}
|
||||
def.z_index = 1001
|
||||
local id = huds.player:hud_add(def)
|
||||
table.insert(huds.ids, id)
|
||||
huds.moving[id] = y
|
||||
return id
|
||||
end
|
||||
|
||||
function mcl_credits.show(player)
|
||||
local name = player:get_player_name()
|
||||
if mcl_credits.players[name] then
|
||||
return
|
||||
end
|
||||
local huds = {
|
||||
new = true, -- workaround for MT < 5.5 (sending hud_add and hud_remove in the same tick)
|
||||
player = player,
|
||||
moving = {},
|
||||
ids = {
|
||||
player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
text = "menu_bg.png",
|
||||
position = {x = 0, y = 0},
|
||||
alignment = {x = 1, y = 1},
|
||||
scale = {x = -100, y = -100},
|
||||
z_index = 1000,
|
||||
}),
|
||||
player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
text = "Sneak to skip",
|
||||
position = {x = 1, y = 1},
|
||||
alignment = {x = -1, y = -1},
|
||||
offset = {x = -5, y = -5},
|
||||
z_index = 1001,
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
},
|
||||
}
|
||||
add_hud_element({
|
||||
hud_elem_type = "image",
|
||||
text = "mineclone2_logo.png",
|
||||
scale = {x = 1, y = 1},
|
||||
}, huds, 300, 0)
|
||||
add_hud_element({
|
||||
hud_elem_type = "text",
|
||||
text = mcl_credits.description,
|
||||
number = 0x757575,
|
||||
scale = {x = 5, y = 5},
|
||||
}, huds, 350, 0)
|
||||
local y = 450
|
||||
for _, group in ipairs(mcl_credits.people) do
|
||||
add_hud_element({
|
||||
hud_elem_type = "text",
|
||||
text = group[1],
|
||||
number = group[2],
|
||||
scale = {x = 3, y = 3},
|
||||
}, huds, y, 0)
|
||||
y = y + 25
|
||||
for _, name in ipairs(group[3]) do
|
||||
y = y + 25
|
||||
add_hud_element({
|
||||
hud_elem_type = "text",
|
||||
text = name,
|
||||
number = 0xFFFFFF,
|
||||
scale = {x = 1, y = 1},
|
||||
}, huds, y, 0)
|
||||
end
|
||||
y = y + 200
|
||||
end
|
||||
huds.icon = add_hud_element({
|
||||
hud_elem_type = "image",
|
||||
text = "mineclone2_icon.png",
|
||||
scale = {x = 1, y = 1},
|
||||
}, huds, y)
|
||||
mcl_credits.players[name] = huds
|
||||
end
|
||||
|
||||
function mcl_credits.hide(player)
|
||||
local name = player:get_player_name()
|
||||
local huds = mcl_credits.players[name]
|
||||
if huds then
|
||||
for _, id in pairs(huds.ids) do
|
||||
player:hud_remove(id)
|
||||
end
|
||||
end
|
||||
mcl_credits.players[name] = nil
|
||||
end
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
mcl_credits.players[player:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, huds in pairs(mcl_credits.players) do
|
||||
local player = huds.player
|
||||
if not huds.new and player:get_player_control().sneak then
|
||||
mcl_credits.hide(player)
|
||||
else
|
||||
local moving = {}
|
||||
local any
|
||||
for id, y in pairs(huds.moving) do
|
||||
y = y - 1
|
||||
if y > -100 then
|
||||
if id == huds.icon then
|
||||
y = math.max(400, y)
|
||||
else
|
||||
any = true
|
||||
end
|
||||
player:hud_change(id, "offset", {x = 0, y = y})
|
||||
moving[id] = y
|
||||
end
|
||||
end
|
||||
if not any then
|
||||
mcl_credits.hide(player)
|
||||
end
|
||||
huds.moving = moving
|
||||
end
|
||||
huds.new = false
|
||||
end
|
||||
end)
|
|
@ -0,0 +1,3 @@
|
|||
name = mcl_credits
|
||||
author = Fleckenstein
|
||||
description = Show a HUD containing the credits
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 76 KiB |
|
@ -57,7 +57,7 @@ local function custom_hud(player)
|
|||
end
|
||||
|
||||
--register and define armor HUD bar
|
||||
hb.register_hudbar("armor", 0xFFFFFF, S("Armor"), { icon = "hbarmor_icon.png", bgicon = "hbarmor_bgicon.png", bar = "hbarmor_bar.png" }, 0, 20, mcl_hbarmor.autohide)
|
||||
hb.register_hudbar("armor", 0xFFFFFF, S("Armor"), { icon = "hbarmor_icon.png", bgicon = "hbarmor_bgicon.png", bar = "hbarmor_bar.png" }, 0, 0, 20, mcl_hbarmor.autohide)
|
||||
|
||||
function mcl_hbarmor.get_armor(player)
|
||||
if not player or not armor.def then
|
||||
|
|
|
@ -47,28 +47,34 @@
|
|||
-- mesecon.rotate_rules_down(rules)
|
||||
-- These functions return rules that have been rotated in the specific direction
|
||||
|
||||
local equals = vector.equals
|
||||
local get_node_force = mesecon.get_node_force
|
||||
local invertRule = mesecon.invertRule
|
||||
local copy, insert = table.copy, table.insert
|
||||
local registered_nodes = minetest.registered_nodes
|
||||
|
||||
-- General
|
||||
function mesecon.get_effector(nodename)
|
||||
if minetest.registered_nodes[nodename]
|
||||
and minetest.registered_nodes[nodename].mesecons
|
||||
and minetest.registered_nodes[nodename].mesecons.effector then
|
||||
return minetest.registered_nodes[nodename].mesecons.effector
|
||||
if registered_nodes[nodename]
|
||||
and registered_nodes[nodename].mesecons
|
||||
and registered_nodes[nodename].mesecons.effector then
|
||||
return registered_nodes[nodename].mesecons.effector
|
||||
end
|
||||
end
|
||||
|
||||
function mesecon.get_receptor(nodename)
|
||||
if minetest.registered_nodes[nodename]
|
||||
and minetest.registered_nodes[nodename].mesecons
|
||||
and minetest.registered_nodes[nodename].mesecons.receptor then
|
||||
return minetest.registered_nodes[nodename].mesecons.receptor
|
||||
if registered_nodes[nodename]
|
||||
and registered_nodes[nodename].mesecons
|
||||
and registered_nodes[nodename].mesecons.receptor then
|
||||
return registered_nodes[nodename].mesecons.receptor
|
||||
end
|
||||
end
|
||||
|
||||
function mesecon.get_conductor(nodename)
|
||||
if minetest.registered_nodes[nodename]
|
||||
and minetest.registered_nodes[nodename].mesecons
|
||||
and minetest.registered_nodes[nodename].mesecons.conductor then
|
||||
return minetest.registered_nodes[nodename].mesecons.conductor
|
||||
if registered_nodes[nodename]
|
||||
and registered_nodes[nodename].mesecons
|
||||
and registered_nodes[nodename].mesecons.conductor then
|
||||
return registered_nodes[nodename].mesecons.conductor
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -103,13 +109,14 @@ end
|
|||
|
||||
-- Receptors
|
||||
-- Nodes that can power mesecons
|
||||
function mesecon.is_receptor_on(nodename)
|
||||
local function is_receptor_on(nodename)
|
||||
local receptor = mesecon.get_receptor(nodename)
|
||||
if receptor and receptor.state == mesecon.state.on then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
mesecon.is_receptor_on = is_receptor_on
|
||||
|
||||
function mesecon.is_receptor_off(nodename)
|
||||
local receptor = mesecon.get_receptor(nodename)
|
||||
|
@ -127,7 +134,7 @@ function mesecon.is_receptor(nodename)
|
|||
return false
|
||||
end
|
||||
|
||||
function mesecon.receptor_get_rules(node)
|
||||
local function receptor_get_rules(node)
|
||||
local receptor = mesecon.get_receptor(node.name)
|
||||
if receptor then
|
||||
local rules = receptor.rules
|
||||
|
@ -140,6 +147,7 @@ function mesecon.receptor_get_rules(node)
|
|||
|
||||
return mesecon.rules.default
|
||||
end
|
||||
mesecon.receptor_get_rules = receptor_get_rules
|
||||
|
||||
-- Effectors
|
||||
-- Nodes that can be powered by mesecons
|
||||
|
@ -186,7 +194,7 @@ end
|
|||
|
||||
-- Activation:
|
||||
mesecon.queue:add_function("activate", function (pos, rulename)
|
||||
local node = mesecon.get_node_force(pos)
|
||||
local node = get_node_force(pos)
|
||||
if not node then return end
|
||||
|
||||
local effector = mesecon.get_effector(node.name)
|
||||
|
@ -198,7 +206,7 @@ end)
|
|||
|
||||
function mesecon.activate(pos, node, rulename, depth)
|
||||
if rulename == nil then
|
||||
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
for _,rule in pairs(mesecon.effector_get_rules(node)) do
|
||||
mesecon.activate(pos, node, rule, depth + 1)
|
||||
end
|
||||
return
|
||||
|
@ -209,7 +217,7 @@ end
|
|||
|
||||
-- Deactivation
|
||||
mesecon.queue:add_function("deactivate", function (pos, rulename)
|
||||
local node = mesecon.get_node_force(pos)
|
||||
local node = get_node_force(pos)
|
||||
if not node then return end
|
||||
|
||||
local effector = mesecon.get_effector(node.name)
|
||||
|
@ -221,7 +229,7 @@ end)
|
|||
|
||||
function mesecon.deactivate(pos, node, rulename, depth)
|
||||
if rulename == nil then
|
||||
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
for _,rule in pairs(mesecon.effector_get_rules(node)) do
|
||||
mesecon.deactivate(pos, node, rule, depth + 1)
|
||||
end
|
||||
return
|
||||
|
@ -232,7 +240,7 @@ end
|
|||
|
||||
-- Change
|
||||
mesecon.queue:add_function("change", function (pos, rulename, changetype)
|
||||
local node = mesecon.get_node_force(pos)
|
||||
local node = get_node_force(pos)
|
||||
if not node then return end
|
||||
|
||||
local effector = mesecon.get_effector(node.name)
|
||||
|
@ -244,7 +252,7 @@ end)
|
|||
|
||||
function mesecon.changesignal(pos, node, rulename, newstate, depth)
|
||||
if rulename == nil then
|
||||
for _,rule in ipairs(mesecon.effector_get_rules(node)) do
|
||||
for _,rule in pairs(mesecon.effector_get_rules(node)) do
|
||||
mesecon.changesignal(pos, node, rule, newstate, depth + 1)
|
||||
end
|
||||
return
|
||||
|
@ -356,15 +364,15 @@ end
|
|||
-- some more general high-level stuff
|
||||
|
||||
function mesecon.is_power_on(pos, rulename)
|
||||
local node = mesecon.get_node_force(pos)
|
||||
if node and (mesecon.is_conductor_on(node, rulename) or mesecon.is_receptor_on(node.name)) then
|
||||
local node = get_node_force(pos)
|
||||
if node and (mesecon.is_conductor_on(node, rulename) or is_receptor_on(node.name)) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function mesecon.is_power_off(pos, rulename)
|
||||
local node = mesecon.get_node_force(pos)
|
||||
local node = get_node_force(pos)
|
||||
if node and (mesecon.is_conductor_off(node, rulename) or mesecon.is_receptor_off(node.name)) then
|
||||
return true
|
||||
end
|
||||
|
@ -381,7 +389,7 @@ function mesecon.turnon(pos, link)
|
|||
local depth = 1
|
||||
while frontiers[1] do
|
||||
local f = table.remove(frontiers, 1)
|
||||
local node = mesecon.get_node_force(f.pos)
|
||||
local node = get_node_force(f.pos)
|
||||
|
||||
if not node then
|
||||
-- Area does not exist; do nothing
|
||||
|
@ -389,10 +397,10 @@ function mesecon.turnon(pos, link)
|
|||
local rules = mesecon.conductor_get_rules(node)
|
||||
|
||||
-- Call turnon on neighbors
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
|
||||
local np = vector.add(f.pos, r)
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
table.insert(frontiers, {pos = np, link = l})
|
||||
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
insert(frontiers, {pos = np, link = l})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -406,12 +414,12 @@ function mesecon.turnon(pos, link)
|
|||
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
|
||||
-- Call turnon on neighbors
|
||||
-- Warning: A LOT of nodes need to be looked at for this to work
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
|
||||
for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
|
||||
local np = vector.add(f.pos, r)
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
local nlink = table.copy(l)
|
||||
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
local nlink = copy(l)
|
||||
nlink.spread = false
|
||||
table.insert(frontiers, {pos = np, link = nlink})
|
||||
insert(frontiers, {pos = np, link = nlink})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -443,33 +451,33 @@ function mesecon.turnoff(pos, link)
|
|||
local depth = 1
|
||||
while frontiers[1] do
|
||||
local f = table.remove(frontiers, 1)
|
||||
local node = mesecon.get_node_force(f.pos)
|
||||
local node = get_node_force(f.pos)
|
||||
|
||||
if not node then
|
||||
-- No-op
|
||||
elseif mesecon.is_conductor_on(node, f.link) then
|
||||
local rules = mesecon.conductor_get_rules(node)
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, rules)) do
|
||||
for _, r in pairs(mesecon.rule2meta(f.link, rules)) do
|
||||
local np = vector.add(f.pos, r)
|
||||
|
||||
-- Check if an onstate receptor is connected. If that is the case,
|
||||
-- abort this turnoff process by returning false. `receptor_off` will
|
||||
-- discard all the changes that we made in the voxelmanip:
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
|
||||
if mesecon.is_receptor_on(mesecon.get_node_force(np).name) then
|
||||
for _, l in pairs(mesecon.rules_link_rule_all_inverted(f.pos, r)) do
|
||||
if is_receptor_on(get_node_force(np).name) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Call turnoff on neighbors
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
table.insert(frontiers, {pos = np, link = l})
|
||||
for _, l in pairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
insert(frontiers, {pos = np, link = l})
|
||||
end
|
||||
end
|
||||
|
||||
mesecon.swap_node_force(f.pos, mesecon.get_conductor_off(node, f.link))
|
||||
elseif mesecon.is_effector(node.name) then
|
||||
table.insert(signals, {
|
||||
insert(signals, {
|
||||
pos = f.pos,
|
||||
node = node,
|
||||
link = f.link,
|
||||
|
@ -480,21 +488,22 @@ function mesecon.turnoff(pos, link)
|
|||
if node and f.link.spread and minetest.get_item_group(node.name, "opaque") == 1 then
|
||||
-- Call turnoff on neighbors
|
||||
-- Warning: A LOT of nodes need to be looked at for this to work
|
||||
for _, r in ipairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
|
||||
local np = vector.add(f.pos, r)
|
||||
local n = mesecon.get_node_force(np)
|
||||
if mesecon.is_receptor_on(n.name) then
|
||||
local receptorrules = mesecon.receptor_get_rules(n)
|
||||
local fpos = f.pos
|
||||
for _, r in pairs(mesecon.rule2meta(f.link, mesecon.rules.mcl_alldirs_spread)) do
|
||||
local np = {x=fpos.x+r.x, y=fpos.y+r.y, z=fpos.z+r.z}
|
||||
local n = get_node_force(np)
|
||||
if n and is_receptor_on(n.name) then
|
||||
local receptorrules = receptor_get_rules(n)
|
||||
for _, rr in pairs(receptorrules) do
|
||||
if rr.spread and vector.equals(mesecon.invertRule(rr), r) then
|
||||
if rr.spread and equals(invertRule(rr), r) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, l in ipairs(mesecon.rules_link_rule_all(f.pos, r)) do
|
||||
local nlink = table.copy(l)
|
||||
for _, l in pairs(mesecon.rules_link_rule_all(fpos, r)) do
|
||||
local nlink = copy(l)
|
||||
nlink.spread = false
|
||||
table.insert(frontiers, {pos = np, link = nlink})
|
||||
insert(frontiers, {pos = np, link = nlink})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -502,7 +511,7 @@ function mesecon.turnoff(pos, link)
|
|||
depth = depth + 1
|
||||
end
|
||||
|
||||
for _, sig in ipairs(signals) do
|
||||
for _, sig in pairs(signals) do
|
||||
mesecon.changesignal(sig.pos, sig.node, sig.link, mesecon.state.off, sig.depth)
|
||||
if mesecon.is_effector_on(sig.node.name) and not mesecon.is_powered(sig.pos) then
|
||||
mesecon.deactivate(sig.pos, sig.node, sig.link, sig.depth)
|
||||
|
@ -516,19 +525,19 @@ end
|
|||
-- outputnode (receptor or conductor) at position `output` and has an output in direction `rule`
|
||||
function mesecon.rules_link_rule_all(output, rule)
|
||||
local input = vector.add(output, rule)
|
||||
local inputnode = mesecon.get_node_force(input)
|
||||
local inputnode = get_node_force(input)
|
||||
local inputrules = mesecon.get_any_inputrules(inputnode)
|
||||
if not inputrules then
|
||||
return {}
|
||||
end
|
||||
local rules = {}
|
||||
|
||||
for _, inputrule in ipairs(mesecon.flattenrules(inputrules)) do
|
||||
for _, inputrule in pairs(mesecon.flattenrules(inputrules)) do
|
||||
-- Check if input accepts from output
|
||||
if vector.equals(vector.add(input, inputrule), output) then
|
||||
local newrule = table.copy(inputrule)
|
||||
if equals(vector.add(input, inputrule), output) then
|
||||
local newrule = copy(inputrule)
|
||||
newrule.spread = rule.spread
|
||||
table.insert(rules, newrule)
|
||||
insert(rules, newrule)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -539,19 +548,19 @@ end
|
|||
-- inputnode (effector or conductor) at position `input` and has an input in direction `rule`
|
||||
function mesecon.rules_link_rule_all_inverted(input, rule)
|
||||
local output = vector.add(input, rule)
|
||||
local outputnode = mesecon.get_node_force(output)
|
||||
local outputnode = get_node_force(output)
|
||||
local outputrules = mesecon.get_any_outputrules(outputnode)
|
||||
if not outputrules then
|
||||
return {}
|
||||
end
|
||||
local rules = {}
|
||||
|
||||
for _, outputrule in ipairs(mesecon.flattenrules(outputrules)) do
|
||||
if vector.equals(vector.add(output, outputrule), input) then
|
||||
local newrule = table.copy(outputrule)
|
||||
newrule = mesecon.invertRule(newrule)
|
||||
for _, outputrule in pairs(mesecon.flattenrules(outputrules)) do
|
||||
if equals(vector.add(output, outputrule), input) then
|
||||
local newrule = copy(outputrule)
|
||||
newrule = invertRule(newrule)
|
||||
newrule.spread = rule.spread
|
||||
table.insert(rules, newrule)
|
||||
insert(rules, newrule)
|
||||
end
|
||||
end
|
||||
return rules
|
||||
|
@ -562,7 +571,7 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
|
|||
if depth > 1 then
|
||||
return false, false
|
||||
end
|
||||
local node = mesecon.get_node_force(pos)
|
||||
local node = get_node_force(pos)
|
||||
local rules = mesecon.get_any_inputrules(node)
|
||||
if not rules then
|
||||
return false, false
|
||||
|
@ -578,23 +587,23 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
|
|||
|
||||
local function power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
|
||||
local spread = false
|
||||
for _, rname in ipairs(rulenames) do
|
||||
for _, rname in pairs(rulenames) do
|
||||
local np = vector.add(pos, rname)
|
||||
local nn = mesecon.get_node_force(np)
|
||||
if (mesecon.is_conductor_on (nn, mesecon.invertRule(rname))
|
||||
or mesecon.is_receptor_on (nn.name)) then
|
||||
if not vector.equals(home_pos, np) then
|
||||
local nn = get_node_force(np)
|
||||
if (mesecon.is_conductor_on (nn, invertRule(rname))
|
||||
or is_receptor_on (nn.name)) then
|
||||
if not equals(home_pos, np) then
|
||||
local rulez = mesecon.get_any_outputrules(nn)
|
||||
local spread_tmp = false
|
||||
for r=1, #rulez do
|
||||
if vector.equals(mesecon.invertRule(rname), rulez[r]) then
|
||||
if equals(invertRule(rname), rulez[r]) then
|
||||
if rulez[r].spread then
|
||||
spread_tmp = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if depth == 0 or spread_tmp then
|
||||
table.insert(sourcepos, np)
|
||||
insert(sourcepos, np)
|
||||
if spread_tmp then
|
||||
spread = true
|
||||
end
|
||||
|
@ -612,7 +621,7 @@ function mesecon.is_powered(pos, rule, depth, sourcepos, home_pos)
|
|||
|
||||
local spread = false
|
||||
if not rule then
|
||||
for _, rule in ipairs(mesecon.flattenrules(rules)) do
|
||||
for _, rule in pairs(mesecon.flattenrules(rules)) do
|
||||
local spread_temp
|
||||
local rulenames = mesecon.rules_link_rule_all_inverted(pos, rule)
|
||||
sourcepos, spread_temp = power_walk(pos, home_pos, sourcepos, rulenames, rule, depth)
|
||||
|
|
|
@ -117,83 +117,90 @@ minetest.register_craft({
|
|||
{"mcl_core:stick"},}
|
||||
})
|
||||
|
||||
mcl_torches.register_torch("mesecon_torch_off", S("Redstone Torch (off)"),
|
||||
nil,
|
||||
nil,
|
||||
"jeija_torches_off.png",
|
||||
"mcl_torches_torch_floor.obj", "mcl_torches_torch_wall.obj",
|
||||
{"jeija_torches_off.png"},
|
||||
0,
|
||||
{dig_immediate=3, dig_by_water=1, redstone_torch=2, mesecon_ignore_opaque_dig=1, not_in_creative_inventory=1},
|
||||
mcl_sounds.node_sound_wood_defaults(),
|
||||
{
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = torch_get_output_rules,
|
||||
},
|
||||
effector = {
|
||||
state = mesecon.state.on,
|
||||
rules = torch_get_input_rules,
|
||||
action_off = torch_action_off,
|
||||
},
|
||||
local off_def = {
|
||||
name = "mesecon_torch_off",
|
||||
description = S("Redstone Torch (off)"),
|
||||
doc_items_create_entry = false,
|
||||
icon = "jeija_torches_off.png",
|
||||
tiles = {"jeija_torches_off.png"},
|
||||
light = 0,
|
||||
groups = {dig_immediate=3, dig_by_water=1, redstone_torch=2, mesecon_ignore_opaque_dig=1, not_in_creative_inventory=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
drop = "mesecons_torch:mesecon_torch_on",
|
||||
}
|
||||
|
||||
mcl_torches.register_torch(off_def)
|
||||
|
||||
local off_override = {
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = torch_get_output_rules,
|
||||
},
|
||||
effector = {
|
||||
state = mesecon.state.on,
|
||||
rules = torch_get_input_rules,
|
||||
action_off = torch_action_off,
|
||||
},
|
||||
drop = "mesecons_torch:mesecon_torch_on",
|
||||
_doc_items_create_entry = false,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mcl_torches.register_torch("mesecon_torch_overheated", S("Redstone Torch (overheated)"),
|
||||
nil,
|
||||
nil,
|
||||
"jeija_torches_off.png",
|
||||
"mcl_torches_torch_floor.obj", "mcl_torches_torch_wall.obj",
|
||||
{"jeija_torches_off.png"},
|
||||
0,
|
||||
{dig_immediate=3, dig_by_water=1, redstone_torch=2, mesecon_ignore_opaque_dig=1, not_in_creative_inventory=1},
|
||||
mcl_sounds.node_sound_wood_defaults(),
|
||||
{
|
||||
drop = "mesecons_torch:mesecon_torch_on",
|
||||
_doc_items_create_entry = false,
|
||||
on_timer = function(pos, elapsed)
|
||||
if not mesecon.is_powered(pos) then
|
||||
local node = minetest.get_node(pos)
|
||||
torch_action_off(pos, node)
|
||||
end
|
||||
end,
|
||||
}
|
||||
)
|
||||
minetest.override_item("mesecons_torch:mesecon_torch_off", off_override)
|
||||
minetest.override_item("mesecons_torch:mesecon_torch_off_wall", off_override)
|
||||
|
||||
local overheated_def = table.copy(off_def)
|
||||
overheated_def.name = "mesecon_torch_overheated"
|
||||
overheated_def.description = S("Redstone Torch (overheated)")
|
||||
|
||||
mcl_torches.register_torch(overheated_def)
|
||||
|
||||
mcl_torches.register_torch("mesecon_torch_on", S("Redstone Torch"),
|
||||
S("A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything."),
|
||||
S("Redstone torches can be placed at the side and on the top of full solid opaque blocks."),
|
||||
"jeija_torches_on.png",
|
||||
"mcl_torches_torch_floor.obj", "mcl_torches_torch_wall.obj",
|
||||
{"jeija_torches_on.png"},
|
||||
7,
|
||||
{dig_immediate=3, dig_by_water=1, redstone_torch=1, mesecon_ignore_opaque_dig=1},
|
||||
mcl_sounds.node_sound_wood_defaults(),
|
||||
{
|
||||
on_destruct = function(pos, oldnode)
|
||||
local overheated_override = {
|
||||
on_timer = function(pos, elapsed)
|
||||
if not mesecon.is_powered(pos) then
|
||||
local node = minetest.get_node(pos)
|
||||
torch_action_on(pos, node)
|
||||
end,
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.on,
|
||||
rules = torch_get_output_rules
|
||||
},
|
||||
effector = {
|
||||
state = mesecon.state.off,
|
||||
rules = torch_get_input_rules,
|
||||
action_on = torch_action_on,
|
||||
},
|
||||
torch_action_off(pos, node)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
minetest.override_item("mesecons_torch:mesecon_torch_overheated", overheated_override)
|
||||
minetest.override_item("mesecons_torch:mesecon_torch_overheated_wall", overheated_override)
|
||||
|
||||
local on_def = {
|
||||
name = "mesecon_torch_on",
|
||||
description = S("Redstone Torch"),
|
||||
doc_items_longdesc = S("A redstone torch is a redstone component which can be used to invert a redstone signal. It supplies its surrounding blocks with redstone power, except for the block it is attached to. A redstone torch is normally lit, but it can also be turned off by powering the block it is attached to. While unlit, a redstone torch does not power anything."),
|
||||
doc_items_usagehelp = S("Redstone torches can be placed at the side and on the top of full solid opaque blocks."),
|
||||
icon = "jeija_torches_on.png",
|
||||
tiles = {"jeija_torches_on.png"},
|
||||
light = 7,
|
||||
groups = {dig_immediate=3, dig_by_water=1, redstone_torch=1, mesecon_ignore_opaque_dig=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
}
|
||||
|
||||
mcl_torches.register_torch(on_def)
|
||||
|
||||
local on_override = {
|
||||
on_destruct = function(pos, oldnode)
|
||||
local node = minetest.get_node(pos)
|
||||
torch_action_on(pos, node)
|
||||
end,
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.on,
|
||||
rules = torch_get_output_rules
|
||||
},
|
||||
_tt_help = S("Provides redstone power when it's not powered itself"),
|
||||
}
|
||||
)
|
||||
effector = {
|
||||
state = mesecon.state.off,
|
||||
rules = torch_get_input_rules,
|
||||
action_on = torch_action_on,
|
||||
},
|
||||
},
|
||||
_tt_help = S("Provides redstone power when it's not powered itself"),
|
||||
}
|
||||
|
||||
minetest.override_item("mesecons_torch:mesecon_torch_on", on_override)
|
||||
minetest.override_item("mesecons_torch:mesecon_torch_on_wall", on_override)
|
||||
|
||||
minetest.register_node("mesecons_torch:redstoneblock", {
|
||||
description = S("Block of Redstone"),
|
||||
|
|
|
@ -382,6 +382,7 @@ mcl_player.player_register_model("mcl_armor_character.b3d", {
|
|||
run_walk_mine = {x=461, y=480},
|
||||
sit_mount = {x=484, y=484},
|
||||
die = {x=498, y=498},
|
||||
fly = {x=502, y=581},
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -410,6 +411,8 @@ mcl_player.player_register_model("mcl_armor_character_female.b3d", {
|
|||
run_walk = {x=440, y=459},
|
||||
run_walk_mine = {x=461, y=480},
|
||||
sit_mount = {x=484, y=484},
|
||||
die = {x=498, y=498},
|
||||
fly = {x=502, y=581},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -9,6 +9,20 @@ dofile(modpath.."/alias.lua")
|
|||
local longdesc = S("This is a piece of equippable armor which reduces the amount of damage you receive.")
|
||||
local usage = S("To equip it, put it on the corresponding armor slot in your inventory menu.")
|
||||
|
||||
minetest.register_tool("mcl_armor:elytra", {
|
||||
description = S("Elytra"),
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = usage,
|
||||
inventory_image = "mcl_armor_inv_elytra.png",
|
||||
groups = {armor_torso=1, mcl_armor_points=0, mcl_armor_uses=10, enchantability=0},
|
||||
sounds = {
|
||||
_mcl_armor_equip = "mcl_armor_equip_leather",
|
||||
_mcl_armor_unequip = "mcl_armor_unequip_leather",
|
||||
},
|
||||
on_place = armor.on_armor_use,
|
||||
on_secondary_use = armor.on_armor_use,
|
||||
})
|
||||
|
||||
minetest.register_tool("mcl_armor:helmet_leather", {
|
||||
description = S("Leather Cap"),
|
||||
_doc_items_longdesc = longdesc,
|
||||
|
|
After Width: | Height: | Size: 746 B |
After Width: | Height: | Size: 355 B |
|
@ -133,7 +133,7 @@ S("The speed and damage of the arrow increases the longer you charge. The regula
|
|||
_doc_items_usagehelp = S("To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot."),
|
||||
_doc_items_durability = BOW_DURABILITY,
|
||||
inventory_image = "mcl_bows_bow.png",
|
||||
wield_scale = { x = 1.8, y = 1.8, z = 1 },
|
||||
wield_scale = mcl_vars.tool_wield_scale,
|
||||
stack_max = 1,
|
||||
range = 4,
|
||||
-- Trick to disable digging as well
|
||||
|
@ -198,7 +198,7 @@ for level=0, 2 do
|
|||
description = S("Bow"),
|
||||
_doc_items_create_entry = false,
|
||||
inventory_image = "mcl_bows_bow_"..level..".png",
|
||||
wield_scale = { x = 1.8, y = 1.8, z = 1 },
|
||||
wield_scale = mcl_vars.tool_wield_scale,
|
||||
stack_max = 1,
|
||||
range = 0, -- Pointing range to 0 to prevent punching with bow :D
|
||||
groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name = mcl_bows
|
||||
author = Arcelmi
|
||||
description = This mod adds bows and arrows for MineClone 2.
|
||||
depends = controls, mcl_particles, mcl_enchanting
|
||||
depends = controls, mcl_particles, mcl_enchanting, mcl_init
|
||||
optional_depends = awards, mcl_achievements, mcl_core, mcl_mobitems, playerphysics, doc, doc_identifier, mesecons_button
|
||||
|
||||
|
|
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 672 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 961 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 674 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 965 B |
|
@ -46,6 +46,56 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
-- Stripped Bark
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:stripped_oak_bark 3",
|
||||
recipe = {
|
||||
{ "mcl_core:stripped_oak", "mcl_core:stripped_oak" },
|
||||
{ "mcl_core:stripped_oak", "mcl_core:stripped_oak" },
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:stripped_acacia_bark 3",
|
||||
recipe = {
|
||||
{ "mcl_core:stripped_acacia", "mcl_core:stripped_acacia" },
|
||||
{ "mcl_core:stripped_acacia", "mcl_core:stripped_acacia" },
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:stripped_dark_oak_bark 3",
|
||||
recipe = {
|
||||
{ "mcl_core:stripped_dark_oak", "mcl_core:stripped_dark_oak" },
|
||||
{ "mcl_core:stripped_dark_oak", "mcl_core:stripped_dark_oak" },
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:stripped_birch_bark 3",
|
||||
recipe = {
|
||||
{ "mcl_core:stripped_birch", "mcl_core:stripped_birch" },
|
||||
{ "mcl_core:stripped_birch", "mcl_core:stripped_birch" },
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:stripped_spruce_bark 3",
|
||||
recipe = {
|
||||
{ "mcl_core:stripped_spruce", "mcl_core:stripped_spruce" },
|
||||
{ "mcl_core:stripped_spruce", "mcl_core:stripped_spruce" },
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:stripped_jungle_bark 3",
|
||||
recipe = {
|
||||
{ "mcl_core:stripped_jungle", "mcl_core:stripped_jungle" },
|
||||
{ "mcl_core:stripped_jungle", "mcl_core:stripped_jungle" },
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
type = 'shapeless',
|
||||
output = 'mcl_core:mossycobble',
|
||||
|
|
|
@ -7,10 +7,10 @@ local WATER_ALPHA = 179
|
|||
local WATER_VISC = 1
|
||||
local LAVA_VISC = 7
|
||||
local LIGHT_LAVA = minetest.LIGHT_MAX
|
||||
local USE_TEXTURE_ALPHA
|
||||
local USE_TEXTURE_ALPHA = true
|
||||
|
||||
if minetest.features.use_texture_alpha_string_modes then
|
||||
USE_TEXTURE_ALPHA = "blend"
|
||||
WATER_ALPHA = nil
|
||||
end
|
||||
|
||||
local lava_death_messages = {
|
||||
|
@ -40,7 +40,6 @@ minetest.register_node("mcl_core:water_flowing", {
|
|||
},
|
||||
sounds = mcl_sounds.node_sound_water_defaults(),
|
||||
is_ground_content = false,
|
||||
alpha = WATER_ALPHA,
|
||||
use_texture_alpha = USE_TEXTURE_ALPHA,
|
||||
paramtype = "light",
|
||||
paramtype2 = "flowingliquid",
|
||||
|
@ -86,7 +85,6 @@ S("• When water is directly below lava, the water turns into stone."),
|
|||
},
|
||||
sounds = mcl_sounds.node_sound_water_defaults(),
|
||||
is_ground_content = false,
|
||||
alpha = WATER_ALPHA,
|
||||
use_texture_alpha = USE_TEXTURE_ALPHA,
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-- Tree nodes: Wood, Wooden Planks, Sapling, Leaves
|
||||
-- Tree nodes: Wood, Wooden Planks, Sapling, Leaves, Stripped Wood
|
||||
local S = minetest.get_translator("mcl_core")
|
||||
|
||||
local mod_screwdriver = minetest.get_modpath("screwdriver") ~= nil
|
||||
|
@ -48,6 +48,166 @@ local register_tree_trunk = function(subname, description_trunk, description_bar
|
|||
})
|
||||
end
|
||||
|
||||
-- Register stripped trunk
|
||||
minetest.register_node("mcl_core:stripped_oak", {
|
||||
description = "Stripped Oak Log",
|
||||
_doc_items_longdesc = "Stripped Oak Log is a log that has been stripped of it's bark.",
|
||||
tiles = {"mcl_core_stripped_oak_top.png", "mcl_core_stripped_oak_top.png", "mcl_core_stripped_oak_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5, tree=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_acacia", {
|
||||
description = "Stripped Acacia Log",
|
||||
_doc_items_longdesc = "Stripped Acacia Log is a log that has been stripped of it's bark.",
|
||||
tiles = {"mcl_core_stripped_acacia_top.png", "mcl_core_stripped_acacia_top.png", "mcl_core_stripped_acacia_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5, tree=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_dark_oak", {
|
||||
description = "Stripped Dark Oak Log",
|
||||
_doc_items_longdesc = "Stripped Dark Oak Log is a log that has been stripped of it's bark.",
|
||||
tiles = {"mcl_core_stripped_dark_oak_top.png", "mcl_core_stripped_dark_oak_top.png", "mcl_core_stripped_dark_oak_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5, tree=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_birch", {
|
||||
description = "Stripped Birch Log",
|
||||
_doc_items_longdesc = "Stripped Birch Log is a log that has been stripped of it's bark.",
|
||||
tiles = {"mcl_core_stripped_birch_top.png", "mcl_core_stripped_birch_top.png", "mcl_core_stripped_birch_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5, tree=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_spruce", {
|
||||
description = "Stripped Spruce Log",
|
||||
_doc_items_longdesc = "Stripped Spruce Log is a log that has been stripped of it's bark.",
|
||||
tiles = {"mcl_core_stripped_spruce_top.png", "mcl_core_stripped_spruce_top.png", "mcl_core_stripped_spruce_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5, tree=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_jungle", {
|
||||
description = "Stripped Jungle Log",
|
||||
_doc_items_longdesc = "Stripped Jungle Log is a log that has been stripped of it's bark.",
|
||||
tiles = {"mcl_core_stripped_jungle_top.png", "mcl_core_stripped_jungle_top.png", "mcl_core_stripped_jungle_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5, tree=1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
|
||||
-- Register stripped bark
|
||||
minetest.register_node("mcl_core:stripped_oak_bark", {
|
||||
description = "Stripped Oak Bark",
|
||||
_doc_items_longdesc = "Stripped Oak Bark is a bark that has been stripped.",
|
||||
tiles = {"mcl_core_stripped_oak_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_acacia_bark", {
|
||||
description = "Stripped Acacia Bark",
|
||||
_doc_items_longdesc = "Stripped Acacia Bark is a bark that has been stripped.",
|
||||
tiles = {"mcl_core_stripped_acacia_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_dark_oak_bark", {
|
||||
description = "Stripped Dark Oak Bark",
|
||||
_doc_items_longdesc = "Stripped Dark Oak Bark is a bark that has been stripped.",
|
||||
tiles = {"mcl_core_stripped_dark_oak_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_birch_bark", {
|
||||
description = "Stripped Birch Bark",
|
||||
_doc_items_longdesc = "Stripped Birch Bark is a bark that has been stripped.",
|
||||
tiles = {"mcl_core_stripped_birch_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_spruce_bark", {
|
||||
description = "Stripped Spruce Bark",
|
||||
_doc_items_longdesc = "Stripped Spruce Bark is a bark that has been stripped.",
|
||||
tiles = {"mcl_core_stripped_spruce_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:stripped_jungle_bark", {
|
||||
description = "Stripped Jungle Bark",
|
||||
_doc_items_longdesc = "Stripped Jungles Bark is a bark that has been stripped.",
|
||||
tiles = {"mcl_core_stripped_jungle_side.png"},
|
||||
is_ground_content = false,
|
||||
paramtype2 = "facedir",
|
||||
on_place = mcl_util.rotate_axis,
|
||||
groups = {handy=1,axey=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 10,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
|
||||
local register_wooden_planks = function(subname, description, tiles)
|
||||
minetest.register_node("mcl_core:"..subname, {
|
||||
description = description,
|
||||
|
|
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 531 B |
After Width: | Height: | Size: 439 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 438 B |
After Width: | Height: | Size: 415 B |
After Width: | Height: | Size: 480 B |
After Width: | Height: | Size: 551 B |
After Width: | Height: | Size: 523 B |
After Width: | Height: | Size: 447 B |
After Width: | Height: | Size: 556 B |
|
@ -169,7 +169,16 @@ minetest.register_node("mcl_end:dragon_egg", {
|
|||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
_mcl_blast_resistance = 9,
|
||||
_mcl_hardness = 3,
|
||||
-- TODO: Make dragon egg teleport on punching
|
||||
on_punch = function(pos, node)
|
||||
local max_dist = vector.new(15, 7, 15)
|
||||
local positions = minetest.find_nodes_in_area(vector.subtract(pos, max_dist), vector.add(pos, max_dist), "air", false)
|
||||
if #positions > 0 then
|
||||
local tpos = positions[math.random(#positions)]
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(tpos, node)
|
||||
minetest.check_for_falling(tpos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -58,8 +58,9 @@ local function spawn_crystal(pos)
|
|||
for _, crystal in pairs(crystals) do
|
||||
crystal_explode(crystal)
|
||||
end
|
||||
local dragon = minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon")
|
||||
dragon:get_luaentity()._egg_spawn_pos = minetest.pos_to_string(vector.add(portal_center, {x = 0, y = 4, z = 0}))
|
||||
local portal_pos = vector.add(portal_center, vector.new(-3, -1, -3))
|
||||
mcl_structures.call_struct(portal_pos, "end_exit_portal")
|
||||
minetest.add_entity(vector.add(portal_pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity()._portal_pos = portal_pos
|
||||
end
|
||||
|
||||
minetest.register_entity("mcl_end:crystal", {
|
||||
|
@ -70,7 +71,7 @@ minetest.register_entity("mcl_end:crystal", {
|
|||
collisionbox = {-1, 0.5, -1, 1, 2.5, 1},
|
||||
mesh = "mcl_end_crystal.b3d",
|
||||
textures = {"mcl_end_crystal.png"},
|
||||
collide_with_objects = true,
|
||||
collide_with_objects = false,
|
||||
},
|
||||
on_punch = crystal_explode,
|
||||
on_activate = set_crystal_animation,
|
||||
|
@ -78,6 +79,54 @@ minetest.register_entity("mcl_end:crystal", {
|
|||
_hittable_by_projectile = true
|
||||
})
|
||||
|
||||
minetest.register_entity("mcl_end:crystal_beam", {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
visual = "cube",
|
||||
visual_size = {x = 1, y = 1, z = 1},
|
||||
textures = {
|
||||
"mcl_end_crystal_beam.png^[transformR90",
|
||||
"mcl_end_crystal_beam.png^[transformR90",
|
||||
"mcl_end_crystal_beam.png",
|
||||
"mcl_end_crystal_beam.png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
},
|
||||
static_save = false,
|
||||
},
|
||||
spin = 0,
|
||||
init = function(self, dragon, crystal)
|
||||
self.dragon, self.crystal = dragon, crystal
|
||||
crystal:get_luaentity().beam = self.object
|
||||
dragon:get_luaentity().beam = self.object
|
||||
end,
|
||||
on_deactivate = function(self)
|
||||
if self.crystal and self.crystal:get_luaentity() then
|
||||
self.crystal:get_luaentity().beam = nil
|
||||
end
|
||||
if self.dragon and self.dragon:get_luaentity() then
|
||||
self.dragon:get_luaentity().beam = nil
|
||||
end
|
||||
end,
|
||||
on_step = function(self, dtime)
|
||||
if self.dragon and self.dragon:get_luaentity() and self.crystal and self.crystal:get_luaentity() then
|
||||
self.spin = self.spin + dtime * math.pi * 2 / 4
|
||||
local dragon_pos, crystal_pos = self.dragon:get_pos(), self.crystal:get_pos()
|
||||
|
||||
dragon_pos.y = dragon_pos.y + 4
|
||||
crystal_pos.y = crystal_pos.y + 2
|
||||
|
||||
self.object:set_pos(vector.divide(vector.add(dragon_pos, crystal_pos), 2))
|
||||
local rot = vector.dir_to_rotation(vector.direction(dragon_pos, crystal_pos))
|
||||
rot.z = self.spin
|
||||
self.object:set_rotation(rot)
|
||||
self.object:set_properties({visual_size = {x = 0.5, y = 0.5, z = vector.distance(dragon_pos, crystal_pos)}})
|
||||
else
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("mcl_end:crystal", {
|
||||
inventory_image = "mcl_end_crystal_item.png",
|
||||
description = S("End Crystal"),
|
||||
|
|
After Width: | Height: | Size: 2.0 KiB |