mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-11-28 13:53:45 +01:00
Merge branch 'master' into biome_colored_foliage
This commit is contained in:
commit
c88f0047c1
BIN
menu/footer.png
BIN
menu/footer.png
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -556,6 +556,11 @@ function mcl_util.deal_damage(target, damage, mcl_reason)
|
||||
end
|
||||
end
|
||||
|
||||
local is_immortal = target:get_armor_groups().immortal or 0
|
||||
if is_immortal>0 then
|
||||
return
|
||||
end
|
||||
|
||||
local hp = target:get_hp()
|
||||
|
||||
if hp > 0 then
|
||||
|
@ -317,7 +317,7 @@ local function update_timers (self, dtime)
|
||||
return true
|
||||
end
|
||||
|
||||
-- attack timer
|
||||
-- attack timer. Not anymore, it seems. Used for also occassionally processing mob step too!
|
||||
self.timer = self.timer + dtime
|
||||
|
||||
if self.state ~= "attack" and self.state ~= PATHFINDING then
|
||||
@ -392,7 +392,6 @@ function mob_class:on_step(dtime)
|
||||
self:check_water_flow()
|
||||
self:env_danger_movement_checks (dtime)
|
||||
|
||||
|
||||
self:follow_flop() -- Mob following code.
|
||||
|
||||
self:set_animation_speed() -- set animation speed relative to velocity
|
||||
@ -408,20 +407,25 @@ function mob_class:on_step(dtime)
|
||||
self:npc_attack()
|
||||
self:check_aggro(dtime)
|
||||
|
||||
if self.do_custom and self.do_custom(self, dtime) == false then return end
|
||||
|
||||
|
||||
-- In certain circumstances, we abandon processing of certain functionality
|
||||
local skip_processing = false
|
||||
if update_timers(self, dtime) then
|
||||
skip_processing = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
if not skip_processing then
|
||||
self:check_breeding()
|
||||
|
||||
self:check_item_pickup()
|
||||
self:set_armor_texture()
|
||||
|
||||
if self.do_custom and self.do_custom(self, dtime) == false then return end
|
||||
|
||||
if update_timers(self, dtime) then return end
|
||||
|
||||
self:check_particlespawners(dtime)
|
||||
|
||||
if self:env_damage (dtime, pos) then return end
|
||||
if self:do_states(dtime) then return end
|
||||
|
||||
if self.opinion_sound_cooloff > 0 then
|
||||
self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime
|
||||
end
|
||||
@ -431,6 +435,9 @@ function mob_class:on_step(dtime)
|
||||
end
|
||||
|
||||
if self:do_states(dtime) then return end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if mobs_debug then self:update_tag() end
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
|
||||
local mob_class = mcl_mobs.mob_class
|
||||
|
||||
local HORNY_TIME = 30*20
|
||||
local HORNY_AGAIN_TIME = 30*20 -- was 300 or 15*20
|
||||
local CHILD_GROW_TIME = 60*20
|
||||
local HORNY_TIME = 30
|
||||
local HORNY_AGAIN_TIME = 30 -- was 300 or 15*20
|
||||
local CHILD_GROW_TIME = 60
|
||||
|
||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_villager",false)
|
||||
|
||||
|
@ -460,7 +460,7 @@ end
|
||||
|
||||
|
||||
-- find and replace what mob is looking for (grass, wheat etc.)
|
||||
function mob_class:replace(pos)
|
||||
function mob_class:replace_node(pos)
|
||||
|
||||
if not self.replace_rate
|
||||
or not self.replace_what
|
||||
|
@ -3,6 +3,9 @@ local mob_class = mcl_mobs.mob_class
|
||||
|
||||
local PATHFINDING_FAIL_THRESHOLD = 100 -- no. of ticks to fail before giving up. 20p/s. 5s helps them get through door
|
||||
local PATHFINDING_FAIL_WAIT = 30 -- how long to wait before trying to path again
|
||||
local PATHING_START_DELAY = 4 -- When doing non-prioritised pathing, how long to wait until last mob pathed
|
||||
|
||||
local PATHFINDING_SEARCH_DISTANCE = 50 -- How big the square is that pathfinding will look
|
||||
|
||||
local PATHFINDING = "gowp"
|
||||
|
||||
@ -107,16 +110,22 @@ local function generate_enriched_path(wp_in, door_open_pos, door_close_pos, cur_
|
||||
return wp_out
|
||||
end
|
||||
|
||||
function mob_class:ready_to_path()
|
||||
local last_pathing_time = os.time()
|
||||
|
||||
function mob_class:ready_to_path(prioritised)
|
||||
mcl_log("Check ready to path")
|
||||
if self._pf_last_failed and (os.time() - self._pf_last_failed) < PATHFINDING_FAIL_WAIT then
|
||||
mcl_log("Not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed))
|
||||
return false
|
||||
else
|
||||
local time_since_path_start = os.time() - last_pathing_time
|
||||
mcl_log("time_since_path_start: " .. tostring(time_since_path_start))
|
||||
if prioritised or (time_since_path_start) > PATHING_START_DELAY then
|
||||
mcl_log("We are ready to pathfind, no previous fail or we are past threshold")
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function is used to see if we can path. We could use to check a route, rather than making people move.
|
||||
local function calculate_path_through_door (p, cur_door_pos, t)
|
||||
@ -144,7 +153,7 @@ local function calculate_path_through_door (p, cur_door_pos, t)
|
||||
if n.name == "air" then
|
||||
mcl_log("We have air space next to door at: " .. minetest.pos_to_string(pos_closest_to_door))
|
||||
|
||||
prospective_wp = minetest.find_path(p,pos_closest_to_door,150,1,4)
|
||||
prospective_wp = minetest.find_path(p, pos_closest_to_door, PATHFINDING_SEARCH_DISTANCE, 1, 4)
|
||||
|
||||
if prospective_wp then
|
||||
mcl_log("Found a path to next to door".. minetest.pos_to_string(pos_closest_to_door))
|
||||
@ -154,7 +163,7 @@ local function calculate_path_through_door (p, cur_door_pos, t)
|
||||
|
||||
if t then
|
||||
mcl_log("We have t, lets go from door to target")
|
||||
local wp_otherside_door_to_target = minetest.find_path(other_side_of_door,t,150,1,4)
|
||||
local wp_otherside_door_to_target = minetest.find_path(other_side_of_door, t, PATHFINDING_SEARCH_DISTANCE, 1, 4)
|
||||
|
||||
if wp_otherside_door_to_target and #wp_otherside_door_to_target > 0 then
|
||||
append_paths (prospective_wp, wp_otherside_door_to_target)
|
||||
@ -190,9 +199,13 @@ local function calculate_path_through_door (p, cur_door_pos, t)
|
||||
return enriched_path
|
||||
end
|
||||
|
||||
function mob_class:gopath(target,callback_arrived)
|
||||
|
||||
|
||||
function mob_class:gopath(target, callback_arrived, prioritised)
|
||||
if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end
|
||||
if not self:ready_to_path() then return end
|
||||
if not self:ready_to_path(prioritised) then return end
|
||||
|
||||
last_pathing_time = os.time()
|
||||
|
||||
self.order = nil
|
||||
|
||||
@ -200,7 +213,7 @@ function mob_class:gopath(target,callback_arrived)
|
||||
local t = vector.offset(target,0,1,0)
|
||||
|
||||
--Check direct route
|
||||
local wp = minetest.find_path(p,t,150,1,4)
|
||||
local wp = minetest.find_path(p, t, PATHFINDING_SEARCH_DISTANCE, 1, 4)
|
||||
|
||||
if not wp then
|
||||
mcl_log("### No direct path. Path through door closest to target.")
|
||||
@ -410,7 +423,7 @@ function mob_class:check_gowp(dtime)
|
||||
mcl_log("No current target")
|
||||
end
|
||||
|
||||
local final_wp = minetest.find_path(p,self._target,150,1,4)
|
||||
local final_wp = minetest.find_path(p, self._target, PATHFINDING_SEARCH_DISTANCE, 1, 4)
|
||||
if final_wp then
|
||||
mcl_log("We can get to target here.")
|
||||
-- self.waypoints = final_wp
|
||||
|
@ -659,7 +659,6 @@ function mob_class:do_env_damage()
|
||||
-- rain
|
||||
if self.rain_damage > 0 then
|
||||
if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then
|
||||
|
||||
self.health = self.health - self.rain_damage
|
||||
|
||||
if self:check_for_death("rain", {type = "environment",
|
||||
@ -672,13 +671,9 @@ function mob_class:do_env_damage()
|
||||
pos.y = pos.y + 1 -- for particle effect position
|
||||
|
||||
-- water damage
|
||||
if self.water_damage > 0
|
||||
and nodef.groups.water then
|
||||
|
||||
if self.water_damage > 0 and nodef.groups.water then
|
||||
if self.water_damage ~= 0 then
|
||||
|
||||
self.health = self.health - self.water_damage
|
||||
|
||||
mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil)
|
||||
|
||||
if self:check_for_death("water", {type = "environment",
|
||||
@ -686,27 +681,10 @@ function mob_class:do_env_damage()
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- magma damage
|
||||
elseif self.fire_damage > 0
|
||||
and (nodef2.groups.fire) then
|
||||
|
||||
if self.fire_damage ~= 0 then
|
||||
|
||||
self.health = self.health - self.fire_damage
|
||||
|
||||
if self:check_for_death("fire", {type = "environment",
|
||||
pos = pos, node = self.standing_in}) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif self.lava_damage > 0 and (nodef.groups.lava) then
|
||||
-- lava damage
|
||||
elseif self.lava_damage > 0
|
||||
and (nodef.groups.lava) then
|
||||
|
||||
if self.lava_damage ~= 0 then
|
||||
|
||||
self.health = self.health - self.lava_damage
|
||||
|
||||
mcl_mobs.effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil)
|
||||
mcl_burning.set_on_fire(self.object, 10)
|
||||
|
||||
@ -715,15 +693,20 @@ function mob_class:do_env_damage()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- fire damage
|
||||
elseif self.fire_damage > 0
|
||||
and (nodef.groups.fire) then
|
||||
|
||||
elseif self.fire_damage > 0 and (nodef2.groups.fire) then
|
||||
-- magma damage
|
||||
if self.fire_damage ~= 0 then
|
||||
|
||||
self.health = self.health - self.fire_damage
|
||||
|
||||
if self:check_for_death("fire", {type = "environment",
|
||||
pos = pos, node = self.standing_in}) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif self.fire_damage > 0 and (nodef.groups.fire) then
|
||||
-- fire damage
|
||||
if self.fire_damage ~= 0 then
|
||||
self.health = self.health - self.fire_damage
|
||||
mcl_mobs.effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil)
|
||||
mcl_burning.set_on_fire(self.object, 5)
|
||||
|
||||
@ -732,12 +715,9 @@ function mob_class:do_env_damage()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- damage_per_second node check
|
||||
elseif nodef.damage_per_second ~= 0 and not nodef.groups.lava and not nodef.groups.fire then
|
||||
|
||||
-- damage_per_second node check
|
||||
self.health = self.health - nodef.damage_per_second
|
||||
|
||||
mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png")
|
||||
|
||||
if self:check_for_death("dps", {type = "environment",
|
||||
@ -749,6 +729,7 @@ function mob_class:do_env_damage()
|
||||
-- Drowning damage
|
||||
if self.breath_max ~= -1 then
|
||||
local drowning = false
|
||||
|
||||
if self.breathes_in_water then
|
||||
if minetest.get_item_group(self.standing_in, "water") == 0 then
|
||||
drowning = true
|
||||
@ -756,10 +737,9 @@ function mob_class:do_env_damage()
|
||||
elseif nodef.drowning > 0 then
|
||||
drowning = true
|
||||
end
|
||||
|
||||
if drowning then
|
||||
|
||||
self.breath = math.max(0, self.breath - 1)
|
||||
|
||||
mcl_mobs.effect(pos, 2, "bubble.png", nil, nil, 1, nil)
|
||||
if self.breath <= 0 then
|
||||
local dmg
|
||||
@ -817,18 +797,18 @@ function mob_class:env_damage (dtime, pos)
|
||||
-- environmental damage timer (every 1 second)
|
||||
self.env_damage_timer = self.env_damage_timer + dtime
|
||||
|
||||
if (self.state == "attack" and self.env_damage_timer > 1)
|
||||
or self.state ~= "attack" then
|
||||
self:check_entity_cramming()
|
||||
|
||||
if self.env_damage_timer > 1 then
|
||||
self.env_damage_timer = 0
|
||||
|
||||
self:check_entity_cramming()
|
||||
|
||||
-- check for environmental damage (water, fire, lava etc.)
|
||||
if self:do_env_damage() then
|
||||
return true
|
||||
end
|
||||
|
||||
-- node replace check (cow eats grass etc.)
|
||||
self:replace(pos)
|
||||
self:replace_node(pos) -- (sheep eats grass etc.)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -24,25 +24,60 @@ local vector_floor = vector.floor
|
||||
|
||||
local table_copy = table.copy
|
||||
local table_remove = table.remove
|
||||
|
||||
local pairs = pairs
|
||||
|
||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_spawning", false)
|
||||
local function mcl_log (message)
|
||||
if LOGGING_ON then
|
||||
mcl_util.mcl_log (message, "[Mobs spawn]", true)
|
||||
end
|
||||
end
|
||||
|
||||
local dbg_spawn_attempts = 0
|
||||
local dbg_spawn_succ = 0
|
||||
local dbg_spawn_counts = {}
|
||||
-- range for mob count
|
||||
local aoc_range = 136
|
||||
|
||||
local remove_far = true
|
||||
|
||||
local WAIT_FOR_SPAWN_ATTEMPT = 10
|
||||
local FIND_SPAWN_POS_RETRIES = 16
|
||||
local FIND_SPAWN_POS_RETRIES_SUCCESS_RESPIN = 8
|
||||
|
||||
local MOB_SPAWN_ZONE_INNER = 24
|
||||
local MOB_SPAWN_ZONE_MIDDLE = 32
|
||||
local MOB_SPAWN_ZONE_OUTER = 128
|
||||
|
||||
-- range for mob count
|
||||
local MOB_CAP_INNER_RADIUS = 32
|
||||
local aoc_range = 136
|
||||
|
||||
local MISSING_CAP_DEFAULT = 15
|
||||
local MOBS_CAP_CLOSE = 5
|
||||
|
||||
local SPAWN_MAPGEN_LIMIT = mcl_vars.mapgen_limit - 150
|
||||
|
||||
local mob_cap = {
|
||||
monster = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70,
|
||||
animal = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10,
|
||||
hostile = tonumber(minetest.settings:get("mcl_mob_cap_monster")) or 70,
|
||||
passive = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 13,
|
||||
ambient = tonumber(minetest.settings:get("mcl_mob_cap_ambient")) or 15,
|
||||
water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 5, --currently unused
|
||||
water = tonumber(minetest.settings:get("mcl_mob_cap_water")) or 8,
|
||||
water_ambient = tonumber(minetest.settings:get("mcl_mob_cap_water_ambient")) or 20, --currently unused
|
||||
player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75,
|
||||
total = tonumber(minetest.settings:get("mcl_mob_cap_total")) or 500,
|
||||
}
|
||||
|
||||
local peaceful_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_percentage_spawned")) or 35
|
||||
local peaceful_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_peaceful_group_percentage_spawned")) or 15
|
||||
local hostile_group_percentage_spawned = tonumber(minetest.settings:get("mcl_mob_hostile_group_percentage_spawned")) or 20
|
||||
|
||||
mcl_log("Mob cap hostile: " .. mob_cap.hostile)
|
||||
mcl_log("Mob cap water: " .. mob_cap.water)
|
||||
mcl_log("Mob cap passive: " .. mob_cap.passive)
|
||||
|
||||
mcl_log("Percentage of peacefuls spawned: " .. peaceful_percentage_spawned)
|
||||
mcl_log("Percentage of peaceful spawns are group: " .. peaceful_group_percentage_spawned)
|
||||
mcl_log("Percentage of hostile spawns are group: " .. hostile_group_percentage_spawned)
|
||||
|
||||
--do mobs spawn?
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
|
||||
@ -250,22 +285,58 @@ local function count_mobs_total(mob_type)
|
||||
return num
|
||||
end
|
||||
|
||||
local function count_mobs_all()
|
||||
local mobs_found = {}
|
||||
local function count_mobs_add_entry (mobs_list, mob_cat)
|
||||
if mobs_list[mob_cat] then
|
||||
mobs_list[mob_cat] = mobs_list[mob_cat] + 1
|
||||
else
|
||||
mobs_list[mob_cat] = 1
|
||||
end
|
||||
end
|
||||
|
||||
--categorise_by can be name or type or spawn_class
|
||||
local function count_mobs_all(categorise_by, pos)
|
||||
local mobs_found_wide = {}
|
||||
local mobs_found_close = {}
|
||||
|
||||
local num = 0
|
||||
for _,entity in pairs(minetest.luaentities) do
|
||||
if entity.is_mob then
|
||||
local mob_type = entity.type -- animal / monster / npc
|
||||
local mob_name = entity.name
|
||||
if mobs_found[mob_name] then
|
||||
mobs_found[mob_name] = mobs_found[mob_name] + 1
|
||||
if entity and entity.is_mob then
|
||||
|
||||
local add_entry = false
|
||||
--local mob_type = entity.type -- animal / monster / npc
|
||||
local mob_cat = entity[categorise_by]
|
||||
|
||||
if pos then
|
||||
local mob_pos = entity.object:get_pos()
|
||||
if mob_pos then
|
||||
local distance = vector.distance(pos, mob_pos)
|
||||
--mcl_log("distance: ".. distance)
|
||||
if distance <= MOB_SPAWN_ZONE_MIDDLE then
|
||||
--mcl_log("distance is close")
|
||||
count_mobs_add_entry (mobs_found_close, mob_cat)
|
||||
count_mobs_add_entry (mobs_found_wide, mob_cat)
|
||||
add_entry = true
|
||||
elseif distance <= MOB_SPAWN_ZONE_OUTER then
|
||||
--mcl_log("distance is wide")
|
||||
count_mobs_add_entry (mobs_found_wide, mob_cat)
|
||||
add_entry = true
|
||||
else
|
||||
mobs_found[mob_name] = 1
|
||||
--mcl_log("mob_pos: " .. minetest.pos_to_string(mob_pos))
|
||||
end
|
||||
end
|
||||
else
|
||||
count_mobs_add_entry (mobs_found_wide, mob_cat)
|
||||
add_entry = true
|
||||
end
|
||||
|
||||
|
||||
if add_entry then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
return mobs_found, num
|
||||
end
|
||||
--mcl_log("num: ".. num)
|
||||
return mobs_found_close, mobs_found_wide, num
|
||||
end
|
||||
|
||||
local function count_mobs_total_cap(mob_type)
|
||||
@ -280,6 +351,32 @@ local function count_mobs_total_cap(mob_type)
|
||||
return num
|
||||
end
|
||||
|
||||
local function output_mob_stats(mob_counts, total_mobs, chat_display)
|
||||
if (total_mobs) then
|
||||
local total_output = "Total mobs found: " .. total_mobs
|
||||
if chat_display then
|
||||
minetest.log(total_output)
|
||||
else
|
||||
minetest.log("action", total_output)
|
||||
end
|
||||
|
||||
end
|
||||
local detailed = ""
|
||||
if mob_counts then
|
||||
for k, v1 in pairs(mob_counts) do
|
||||
detailed = detailed .. tostring(k) .. ": " .. tostring(v1) .. "; "
|
||||
end
|
||||
end
|
||||
if detailed and detailed ~= "" then
|
||||
if chat_display then
|
||||
minetest.log(detailed)
|
||||
else
|
||||
minetest.log("action", detailed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- global functions
|
||||
|
||||
function mcl_mobs:spawn_abm_check(pos, node, name)
|
||||
@ -422,18 +519,23 @@ function mcl_mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_
|
||||
summary_chance = summary_chance + chance
|
||||
end
|
||||
|
||||
|
||||
local two_pi = 2 * math.pi
|
||||
local function get_next_mob_spawn_pos(pos)
|
||||
local distance = math_random(25, 32)
|
||||
-- TODO We should consider spawning something a little further away sporadically.
|
||||
-- It would be good for sky farms and variance, rather than all being on the 24 - 32 block away radius
|
||||
local distance = math_random(MOB_SPAWN_ZONE_INNER, MOB_SPAWN_ZONE_MIDDLE)
|
||||
local angle = math_random() * two_pi
|
||||
|
||||
-- TODO Floor xoff and zoff and add 0.5 so it tries to spawn in the middle of the square. Less failed attempts.
|
||||
local xoff = math_round(distance * math_cos(angle))
|
||||
local yoff = math_round(distance * math_sin(angle))
|
||||
return vector.offset(pos, xoff, 0, yoff)
|
||||
local zoff = math_round(distance * math_sin(angle))
|
||||
return vector.offset(pos, xoff, 0, zoff)
|
||||
end
|
||||
|
||||
local function decypher_limits(posy)
|
||||
posy = math_floor(posy)
|
||||
return posy - 32, posy + 32
|
||||
return posy - MOB_SPAWN_ZONE_MIDDLE, posy + MOB_SPAWN_ZONE_MIDDLE
|
||||
end
|
||||
|
||||
--a simple helper function for mob_spawn
|
||||
@ -484,7 +586,9 @@ local function has_room(self,pos)
|
||||
return true
|
||||
end
|
||||
|
||||
local function spawn_check(pos,spawn_def,ignore_caps)
|
||||
|
||||
|
||||
local function spawn_check(pos, spawn_def)
|
||||
if not spawn_def then return end
|
||||
dbg_spawn_attempts = dbg_spawn_attempts + 1
|
||||
local dimension = mcl_worlds.pos_to_dimension(pos)
|
||||
@ -507,17 +611,8 @@ local function spawn_check(pos,spawn_def,ignore_caps)
|
||||
local is_leaf = get_item_group(gotten_node, "leaves") ~= 0
|
||||
local is_bedrock = gotten_node == "mcl_core:bedrock"
|
||||
local is_grass = minetest.get_item_group(gotten_node,"grass_block") ~= 0
|
||||
local mob_count_wide = 0
|
||||
|
||||
local mob_count = 0
|
||||
if not ignore_caps then
|
||||
mob_count = count_mobs(pos,32,mob_type)
|
||||
mob_count_wide = count_mobs(pos,aoc_range,mob_type)
|
||||
end
|
||||
|
||||
if pos and spawn_def
|
||||
and ( mob_count_wide < (mob_cap[mob_type] or 15) )
|
||||
and ( mob_count < 5 )
|
||||
and pos.y >= spawn_def.min_height
|
||||
and pos.y <= spawn_def.max_height
|
||||
and spawn_def.dimension == dimension
|
||||
@ -553,8 +648,7 @@ function mcl_mobs.spawn(pos,id)
|
||||
end
|
||||
|
||||
|
||||
local function spawn_group(p,mob,spawn_on,group_max,group_min)
|
||||
if not group_min then group_min = 1 end
|
||||
local function spawn_group(p,mob,spawn_on,amount_to_spawn)
|
||||
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
|
||||
local o
|
||||
table.shuffle(nn)
|
||||
@ -562,9 +656,10 @@ local function spawn_group(p,mob,spawn_on,group_max,group_min)
|
||||
nn = {}
|
||||
table.insert(nn,p)
|
||||
end
|
||||
for i = 1, math.random(group_min,group_max) do
|
||||
|
||||
for i = 1, amount_to_spawn do
|
||||
local sp = vector.offset(nn[math.random(#nn)],0,1,0)
|
||||
if spawn_check(nn[math.random(#nn)],mob,true) then
|
||||
if spawn_check(nn[math.random(#nn)],mob) then
|
||||
if mob.type_of_spawning == "water" then
|
||||
sp = get_water_spawn(sp)
|
||||
end
|
||||
@ -655,25 +750,113 @@ if mobs_spawn then
|
||||
-- Get pos to spawn, x and z are randomised, y is range
|
||||
|
||||
|
||||
local function spawn_a_mob(pos, dimension, y_min, y_max)
|
||||
--create a disconnected clone of the spawn dictionary
|
||||
--prevents memory leak
|
||||
local mob_library_worker_table = table_copy(spawn_dictionary)
|
||||
local function mob_cap_space (pos, mob_type, mob_counts_close, mob_counts_wide)
|
||||
|
||||
-- Some mob examples
|
||||
--type = "monster", spawn_class = "hostile",
|
||||
--type = "animal", spawn_class = "passive",
|
||||
--local cod = { type = "animal", spawn_class = "water",
|
||||
|
||||
local type_cap = mob_cap[mob_type] or MISSING_CAP_DEFAULT
|
||||
local close_zone_cap = MOBS_CAP_CLOSE
|
||||
|
||||
local mob_total_wide = mob_counts_wide[mob_type]
|
||||
if not mob_total_wide then
|
||||
--mcl_log("none of type found. set as 0")
|
||||
mob_total_wide = 0
|
||||
end
|
||||
|
||||
local cap_space_wide = type_cap - mob_total_wide
|
||||
if cap_space_wide < 1 then
|
||||
cap_space_wide = 0
|
||||
end
|
||||
|
||||
local mob_total_close = mob_counts_close[mob_type]
|
||||
if not mob_total_close then
|
||||
--mcl_log("none of type found. set as 0")
|
||||
mob_total_close = 0
|
||||
end
|
||||
|
||||
local cap_space_close = close_zone_cap - mob_total_close
|
||||
if cap_space_close < 1 then
|
||||
cap_space_close = 0
|
||||
end
|
||||
|
||||
--mcl_log("spawn_class: " .. spawn_class)
|
||||
|
||||
if false and mob_type == "water" then
|
||||
mcl_log("mob_type: " .. mob_type .. " and pos: " .. minetest.pos_to_string(pos))
|
||||
mcl_log("wide: " .. mob_total_wide .. "/" .. type_cap)
|
||||
mcl_log("cap_space_wide: " .. cap_space_wide)
|
||||
mcl_log("close: " .. mob_total_close .. "/" .. close_zone_cap)
|
||||
mcl_log("cap_space_close: " .. cap_space_close)
|
||||
end
|
||||
|
||||
return cap_space_wide, cap_space_close
|
||||
end
|
||||
|
||||
local function find_spawning_position(pos, max_times)
|
||||
local spawning_position
|
||||
|
||||
local max_loops = 1
|
||||
if max_times then max_loops = max_times end
|
||||
|
||||
local y_min, y_max = decypher_limits(pos.y)
|
||||
|
||||
mcl_log("mapgen_limit: " .. SPAWN_MAPGEN_LIMIT)
|
||||
local i = 0
|
||||
repeat
|
||||
local goal_pos = get_next_mob_spawn_pos(pos)
|
||||
--grab mob that fits into the spawning location
|
||||
--randomly grab a mob, don't exclude any possibilities
|
||||
|
||||
if math.abs(goal_pos.x) <= SPAWN_MAPGEN_LIMIT and math.abs(pos.y) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.z) <= SPAWN_MAPGEN_LIMIT then
|
||||
local spawning_position_list = find_nodes_in_area_under_air(
|
||||
{x = goal_pos.x, y = y_min, z = goal_pos.z},
|
||||
{x = goal_pos.x, y = y_max, z = goal_pos.z},
|
||||
{"group:solid", "group:water", "group:lava"}
|
||||
)
|
||||
if #spawning_position_list <= 0 then return end
|
||||
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
||||
if #spawning_position_list > 0 then
|
||||
mcl_log("Spawning positions available: " .. minetest.pos_to_string(goal_pos))
|
||||
spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
||||
else
|
||||
mcl_log("Spawning position isn't good. Do not spawn: " .. minetest.pos_to_string(goal_pos))
|
||||
end
|
||||
|
||||
else
|
||||
mcl_log("Pos outside mapgen limits: " .. minetest.pos_to_string(goal_pos))
|
||||
end
|
||||
|
||||
|
||||
i = i + 1
|
||||
if i >= max_loops then
|
||||
mcl_log("Cancel finding spawn positions at: " .. max_loops)
|
||||
break
|
||||
end
|
||||
until spawning_position
|
||||
return spawning_position
|
||||
end
|
||||
|
||||
local function spawn_a_mob(pos)
|
||||
--create a disconnected clone of the spawn dictionary, prevents memory leak
|
||||
local mob_library_worker_table = table_copy(spawn_dictionary)
|
||||
|
||||
local spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES)
|
||||
if not spawning_position then
|
||||
minetest.log("action", "[Mobs spawn] Cannot find a valid spawn position after retries: " .. FIND_SPAWN_POS_RETRIES)
|
||||
return
|
||||
end
|
||||
|
||||
local mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("spawn_class", spawning_position)
|
||||
--output_mob_stats(mob_counts_close, total_mobs)
|
||||
--output_mob_stats(mob_counts_wide)
|
||||
|
||||
--grab mob that fits into the spawning location
|
||||
--randomly grab a mob, don't exclude any possibilities
|
||||
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||
local noise = perlin_noise:get_3d(spawning_position)
|
||||
local current_summary_chance = summary_chance
|
||||
|
||||
table.shuffle(mob_library_worker_table)
|
||||
|
||||
while #mob_library_worker_table > 0 do
|
||||
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
||||
local mob_index = 1
|
||||
@ -684,13 +867,32 @@ if mobs_spawn then
|
||||
mob_chance = mob_library_worker_table[mob_index].chance
|
||||
step_chance = step_chance + mob_chance
|
||||
end
|
||||
local mob_def = mob_library_worker_table[mob_index]
|
||||
--minetest.log(mob_def.name.." "..step_chance.. " "..mob_chance)
|
||||
|
||||
local mob_def = mob_library_worker_table[mob_index]
|
||||
if mob_def and mob_def.name and minetest.registered_entities[mob_def.name] then
|
||||
local spawn_in_group = minetest.registered_entities[mob_def.name].spawn_in_group or 4
|
||||
local spawn_in_group_min = minetest.registered_entities[mob_def.name].spawn_in_group_min or 1
|
||||
local mob_type = minetest.registered_entities[mob_def.name].type
|
||||
if spawn_check(spawning_position,mob_def) then
|
||||
|
||||
local mob_def_ent = minetest.registered_entities[mob_def.name]
|
||||
--local mob_type = mob_def_ent.type
|
||||
local mob_spawn_class = mob_def_ent.spawn_class
|
||||
|
||||
--mcl_log("mob_spawn_class: " .. mob_spawn_class)
|
||||
|
||||
local cap_space_wide, cap_space_close = mob_cap_space (spawning_position, mob_spawn_class, mob_counts_close, mob_counts_wide)
|
||||
|
||||
|
||||
if cap_space_close > 0 and cap_space_wide > 0 then
|
||||
--mcl_log("Cap space available")
|
||||
|
||||
-- Spawn caps for animals and water creatures fill up rapidly. Need to throttle this somewhat
|
||||
-- for performance and for early game challenge. We don't want to reduce hostiles though.
|
||||
local spawn_hostile = (mob_spawn_class == "hostile")
|
||||
local spawn_passive = (mob_spawn_class ~= "hostile") and math.random(100) < peaceful_percentage_spawned
|
||||
-- or not hostile
|
||||
--mcl_log("Spawn_passive: " .. tostring(spawn_passive))
|
||||
--mcl_log("Spawn_hostile: " .. tostring(spawn_hostile))
|
||||
|
||||
if (spawn_hostile or spawn_passive) and spawn_check(spawning_position,mob_def) then
|
||||
if mob_def.type_of_spawning == "water" then
|
||||
spawning_position = get_water_spawn(spawning_position)
|
||||
if not spawning_position then
|
||||
@ -698,25 +900,62 @@ if mobs_spawn then
|
||||
return
|
||||
end
|
||||
end
|
||||
if minetest.registered_entities[mob_def.name].can_spawn and not minetest.registered_entities[mob_def.name].can_spawn(spawning_position) then
|
||||
if mob_def_ent.can_spawn and not mob_def_ent.can_spawn(spawning_position) then
|
||||
minetest.log("warning","[mcl_mobs] mob "..mob_def.name.." refused to spawn at "..minetest.pos_to_string(vector.round(spawning_position)))
|
||||
return
|
||||
end
|
||||
--everything is correct, spawn mob
|
||||
local object
|
||||
if spawn_in_group and ( mob_type ~= "monster" or math.random(5) == 1 ) then
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_mobs] A group of mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1))
|
||||
end
|
||||
object = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name},spawn_in_group,spawn_in_group_min)
|
||||
|
||||
--everything is correct, spawn mob
|
||||
local spawn_in_group = mob_def_ent.spawn_in_group or 4
|
||||
|
||||
local spawn_group_hostile = (mob_spawn_class == "hostile") and (math.random(100) < hostile_group_percentage_spawned)
|
||||
local spawn_group_passive = (mob_spawn_class ~= "hostile") and (math.random(100) < peaceful_group_percentage_spawned)
|
||||
|
||||
mcl_log("spawn_group_hostile: " .. tostring(spawn_group_hostile))
|
||||
mcl_log("spawn_group_passive: " .. tostring(spawn_group_passive))
|
||||
|
||||
local spawned
|
||||
if spawn_in_group and (spawn_group_hostile or spawn_group_passive) then
|
||||
local group_min = mob_def_ent.spawn_in_group_min or 1
|
||||
if not group_min then group_min = 1 end
|
||||
|
||||
local amount_to_spawn = math.random(group_min,spawn_in_group)
|
||||
|
||||
if amount_to_spawn > cap_space_wide then
|
||||
mcl_log("Spawning quantity: " .. amount_to_spawn)
|
||||
mcl_log("Throttle amount to cap space: " .. cap_space_wide)
|
||||
amount_to_spawn = cap_space_wide
|
||||
end
|
||||
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_mobs] A group of " ..amount_to_spawn .. " " .. mob_def.name .. " mob spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at " .. minetest.pos_to_string(spawning_position, 1))
|
||||
end
|
||||
spawned = spawn_group(spawning_position,mob_def,{minetest.get_node(vector.offset(spawning_position,0,-1,0)).name}, amount_to_spawn)
|
||||
else
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns on " ..minetest.get_node(vector.offset(spawning_position,0,-1,0)).name .." at ".. minetest.pos_to_string(spawning_position, 1))
|
||||
end
|
||||
object = mcl_mobs.spawn(spawning_position, mob_def.name)
|
||||
spawned = mcl_mobs.spawn(spawning_position, mob_def.name)
|
||||
end
|
||||
|
||||
if spawned then
|
||||
--mcl_log("We have spawned")
|
||||
mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("type", pos)
|
||||
local new_spawning_position = find_spawning_position(pos, FIND_SPAWN_POS_RETRIES_SUCCESS_RESPIN)
|
||||
if new_spawning_position then
|
||||
mcl_log("Setting new spawning position")
|
||||
spawning_position = new_spawning_position
|
||||
else
|
||||
mcl_log("Cannot set new spawning position")
|
||||
end
|
||||
end
|
||||
else
|
||||
mcl_log("Spawn check failed")
|
||||
end
|
||||
else
|
||||
mcl_log("Cap space full")
|
||||
end
|
||||
|
||||
end
|
||||
current_summary_chance = current_summary_chance - mob_chance
|
||||
table_remove(mob_library_worker_table, mob_index)
|
||||
@ -728,22 +967,24 @@ if mobs_spawn then
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
||||
timer = timer + dtime
|
||||
if timer < 10 then return end
|
||||
if timer < WAIT_FOR_SPAWN_ATTEMPT then return end
|
||||
timer = 0
|
||||
|
||||
local players = get_connected_players()
|
||||
local total_mobs = count_mobs_total_cap()
|
||||
if total_mobs > mob_cap.total or total_mobs > #players * mob_cap.player then
|
||||
minetest.log("action","[mcl_mobs] global mob cap reached. no cycle spawning.")
|
||||
return
|
||||
end --mob cap per player
|
||||
|
||||
for _, player in pairs(players) do
|
||||
local pos = player:get_pos()
|
||||
local dimension = mcl_worlds.pos_to_dimension(pos)
|
||||
-- ignore void and unloaded area
|
||||
if dimension ~= "void" and dimension ~= "default" then
|
||||
local y_min, y_max = decypher_limits(pos.y)
|
||||
spawn_a_mob(pos, dimension, y_min, y_max)
|
||||
spawn_a_mob(pos)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@ -775,27 +1016,16 @@ function mob_class:check_despawn(pos, dtime)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
minetest.register_chatcommand("mobstats",{
|
||||
privs = { debug = true },
|
||||
func = function(n,param)
|
||||
minetest.chat_send_player(n,dump(dbg_spawn_counts))
|
||||
--minetest.chat_send_player(n,dump(dbg_spawn_counts))
|
||||
local pos = minetest.get_player_by_name(n):get_pos()
|
||||
minetest.chat_send_player(n,"mobs within 32 radius of player:"..count_mobs(pos,32))
|
||||
minetest.chat_send_player(n,"total mobs:"..count_mobs_total())
|
||||
minetest.chat_send_player(n,"spawning attempts since server start:"..dbg_spawn_attempts)
|
||||
minetest.chat_send_player(n,"successful spawns since server start:"..dbg_spawn_succ)
|
||||
|
||||
|
||||
local mob_counts, total_mobs = count_mobs_all()
|
||||
if (total_mobs) then
|
||||
minetest.log("action", "Total mobs found: " .. total_mobs)
|
||||
end
|
||||
if mob_counts then
|
||||
for k, v1 in pairs(mob_counts) do
|
||||
minetest.log("action", "k: " .. tostring(k))
|
||||
minetest.log("action", "v1: " .. tostring(v1))
|
||||
end
|
||||
end
|
||||
minetest.chat_send_player(n,"mobs: within 32 radius of player/total loaded :"..count_mobs(pos,MOB_CAP_INNER_RADIUS) .. "/" .. count_mobs_total())
|
||||
minetest.chat_send_player(n,"spawning attempts since server start:" .. dbg_spawn_succ .. "/" .. dbg_spawn_attempts)
|
||||
|
||||
local mob_counts_close, mob_counts_wide, total_mobs = count_mobs_all("name") -- Can use "type"
|
||||
output_mob_stats(mob_counts_wide, total_mobs, true)
|
||||
end
|
||||
})
|
||||
|
@ -40,8 +40,8 @@ local cod = {
|
||||
xp_max = 3,
|
||||
armor = 100,
|
||||
rotate = 180,
|
||||
spawn_in_group_min = 3,
|
||||
spawn_in_group = 8,
|
||||
spawn_in_group_min = 2, -- was 3
|
||||
spawn_in_group = 4, -- was 8 nerfed until we can cap them properly locally. this is a group size, not a per spawn attempt
|
||||
tilt_swim = true,
|
||||
collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3},
|
||||
visual = "mesh",
|
||||
|
@ -14,7 +14,7 @@ local cow_def = {
|
||||
xp_max = 3,
|
||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45},
|
||||
spawn_in_group = 4,
|
||||
spawn_in_group_min = 3,
|
||||
spawn_in_group_min = 2,
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_cow.b3d",
|
||||
textures = { {
|
||||
@ -93,8 +93,8 @@ mcl_mobs.register_mob("mobs_mc:cow", cow_def)
|
||||
-- Mooshroom
|
||||
local mooshroom_def = table.copy(cow_def)
|
||||
mooshroom_def.description = S("Mooshroom")
|
||||
mooshroom_def.spawn_in_group_min = 4
|
||||
mooshroom_def.spawn_in_group = 8
|
||||
mooshroom_def.spawn_in_group_min = 2
|
||||
mooshroom_def.spawn_in_group = 4
|
||||
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
||||
mooshroom_def.on_rightclick = function(self, clicker)
|
||||
if self:feed_tame(clicker, 1, true, false) then return end
|
||||
|
@ -42,8 +42,8 @@ local dolphin = {
|
||||
walk_chance = 100,
|
||||
breath_max = 120,
|
||||
rotate = 180,
|
||||
spawn_in_group_min = 3,
|
||||
spawn_in_group = 5,
|
||||
spawn_in_group_min = 2, -- was 3
|
||||
spawn_in_group = 4, -- was 4. nerfed until water has own cap, and it represents max pack size rather than per spawn attempt
|
||||
tilt_swim = true,
|
||||
collisionbox = {-0.3, 0.0, -0.3, 0.3, 0.79, 0.3},
|
||||
visual = "mesh",
|
||||
|
@ -125,7 +125,7 @@ local horse = {
|
||||
type = "animal",
|
||||
spawn_class = "passive",
|
||||
spawn_in_group_min = 2,
|
||||
spawn_in_group = 6,
|
||||
spawn_in_group = 4, -- was 6. nerfed until group size is a cap rather than per spawn cycle
|
||||
visual = "mesh",
|
||||
mesh = "mobs_mc_horse.b3d",
|
||||
visual_size = {x=3.0, y=3.0},
|
||||
|
@ -56,8 +56,8 @@ mcl_mobs.register_mob("mobs_mc:llama", {
|
||||
shoot_interval = 5.5,
|
||||
arrow = "mobs_mc:llamaspit",
|
||||
shoot_offset = 1, --3.5 *would* be a good value visually but it somehow messes with the projectiles trajectory
|
||||
spawn_in_group_min = 4,
|
||||
spawn_in_group = 6,
|
||||
spawn_in_group_min = 2, -- was 4
|
||||
spawn_in_group = 4, -- was 6 nerfed until we can cap them properly locally. this is a group size, not a per spawn attempt
|
||||
|
||||
head_swivel = "head.control",
|
||||
bone_eye_height = 11,
|
||||
|
@ -67,7 +67,7 @@ local tropical_fish = {
|
||||
xp_min = 1,
|
||||
xp_max = 3,
|
||||
armor = 100,
|
||||
spawn_in_group = 9,
|
||||
spawn_in_group = 4, -- was 9. nerfed until aquatics use own cap rather than animal, and it represents pack size, not per spawn attempt
|
||||
tilt_swim = true,
|
||||
collisionbox = {-0.2, 0.0, -0.2, 0.2, 0.1, 0.2},
|
||||
visual = "mesh",
|
||||
|
@ -617,6 +617,13 @@ local function set_textures(self)
|
||||
self.object:set_properties({textures=badge_textures})
|
||||
end
|
||||
|
||||
-- TODO Pass in self and if nitwit, go to bed later.
|
||||
local function is_night()
|
||||
local tod = minetest.get_timeofday()
|
||||
tod = ( tod * 24000 ) % 24000
|
||||
return tod > 17500 or tod < 6500
|
||||
end
|
||||
|
||||
function get_activity(tod)
|
||||
-- night hours = tod > 18541 or tod < 5458
|
||||
if not tod then
|
||||
@ -626,8 +633,8 @@ function get_activity(tod)
|
||||
|
||||
local lunch_start = 11000
|
||||
local lunch_end = 13500
|
||||
local work_start = 7000
|
||||
local work_end = 16500
|
||||
local work_start = 7500
|
||||
local work_end = 16000
|
||||
|
||||
local activity = nil
|
||||
if weather_mod and mcl_weather.get_weather() == "thunder" then
|
||||
@ -635,7 +642,7 @@ function get_activity(tod)
|
||||
activity = SLEEP
|
||||
elseif (tod > work_start and tod < lunch_start) or (tod > lunch_end and tod < work_end) then
|
||||
activity = WORK
|
||||
elseif mcl_beds.is_night() then
|
||||
elseif is_night() then
|
||||
activity = SLEEP
|
||||
elseif tod > lunch_start and tod < lunch_end then
|
||||
activity = GATHERING
|
||||
@ -829,7 +836,7 @@ local function go_home(entity, sleep)
|
||||
else
|
||||
--minetest.log("Need to walk to home")
|
||||
end
|
||||
end)
|
||||
end, true)
|
||||
end
|
||||
end
|
||||
|
||||
@ -1166,6 +1173,7 @@ local function do_work (self)
|
||||
self.order = nil
|
||||
return
|
||||
end
|
||||
|
||||
self:gopath(jobsite, function(self, jobsite)
|
||||
if not self then
|
||||
--mcl_log("missing self. not good")
|
||||
@ -1309,7 +1317,7 @@ local function do_activity (self)
|
||||
|
||||
local jobsite_valid = false
|
||||
|
||||
if not mcl_beds.is_night() then
|
||||
if not is_night() then
|
||||
if self.order == SLEEP then self.order = nil end
|
||||
|
||||
if not validate_jobsite(self) then
|
||||
|
@ -477,6 +477,19 @@ mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_black")
|
||||
mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_brown")
|
||||
mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_light_blue")
|
||||
mesecon.register_mvps_unsticky("mcl_colorblocks:glazed_terracotta_pink")
|
||||
-- Bamboo
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo")
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo_endcap")
|
||||
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo_1")
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo_2")
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo_3")
|
||||
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo_door")
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:bamboo_trapdoor")
|
||||
mesecon.register_mvps_unsticky("mcl_signs:wall_sign_bamboo")
|
||||
mesecon.register_mvps_unsticky("mcl_bamboo:scaffolding")
|
||||
|
||||
-- Beds
|
||||
mesecon.register_mvps_unsticky("mcl_beds:bed_black_top")
|
||||
mesecon.register_mvps_unsticky("mcl_beds:bed_black_bottom")
|
||||
|
@ -29,7 +29,7 @@ local bamboo_def = {
|
||||
tiles = {"mcl_bamboo_bamboo_bottom.png", "mcl_bamboo_bamboo_bottom.png", "mcl_bamboo_bamboo.png"},
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
groups = {handy = 1, axey = 1, choppy = 1, flammable = 3},
|
||||
groups = {handy = 1, axey = 1, choppy = 1, dig_by_piston = 1, plant = 1, non_mycelium_plant = 1, flammable = 3},
|
||||
sounds = node_sound,
|
||||
|
||||
drop = {
|
||||
@ -293,7 +293,6 @@ local bamboo_block_def = {
|
||||
|
||||
return minetest.item_place(itemstack, placer, pointed_thing, minetest.dir_to_facedir(vector.direction(pointed_thing.above, pointed_thing.under)))
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
minetest.register_node("mcl_bamboo:bamboo_block", bamboo_block_def)
|
||||
|
@ -279,7 +279,7 @@ minetest.register_node(SCAFFOLDING_NAME, {
|
||||
climbable = true,
|
||||
physical = true,
|
||||
node_placement_prediction = "",
|
||||
groups = {handy = 1, axey = 1, flammable = 3, building_block = 1, material_wood = 1, fire_encouragement = 5, fire_flammability = 20, falling_node = 1, stack_falling = 1},
|
||||
groups = { handy = 1, axey = 1, flammable = 3, building_block = 1, material_wood = 1, fire_encouragement = 5, fire_flammability = 20, dig_by_piston = 1, falling_node = 1, stack_falling = 1 },
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 0,
|
||||
_mcl_hardness = 0,
|
||||
|
@ -67,6 +67,32 @@ end
|
||||
|
||||
local BAMBOO_ENDCAP_NAME = "mcl_bamboo:bamboo_endcap"
|
||||
|
||||
-- For when I learn more about the pistons...
|
||||
function mcl_bamboo.break_orphaned(pos)
|
||||
mcl_bamboo.mcl_log("Break_Orphaned called.")
|
||||
local node_below = minetest.get_node(vector.offset(pos, 0, -1, 0))
|
||||
local node_name = node_below.name
|
||||
|
||||
-- short circuit checks.
|
||||
if mcl_bamboo.is_dirt(node_name) or mcl_bamboo.is_bamboo(node_name) or mcl_bamboo.is_bamboo(minetest.get_node(pos).name) == false then
|
||||
return
|
||||
end
|
||||
|
||||
-- dig the node.
|
||||
minetest.remove_node(pos) -- if that fails, remove the node
|
||||
local istack = ItemStack("mcl_bamboo:bamboo")
|
||||
local sound_params = {
|
||||
pos = pos,
|
||||
gain = 1.0, -- default
|
||||
max_hear_distance = 10, -- default, uses a Euclidean metric
|
||||
}
|
||||
|
||||
minetest.remove_node(pos)
|
||||
minetest.sound_play(mcl_sounds.node_sound_wood_defaults().dug, sound_params, true)
|
||||
minetest.add_item(pos, istack)
|
||||
end
|
||||
--]]
|
||||
|
||||
function mcl_bamboo.grow_bamboo(pos, bonemeal_applied)
|
||||
local node_above = minetest.get_node(vector.offset(pos, 0, 1, 0))
|
||||
mcl_bamboo.mcl_log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied))
|
||||
|
@ -26,6 +26,7 @@ dofile(minetest.get_modpath(modname) .. "/recipes.lua")
|
||||
|
||||
--ABMs
|
||||
minetest.register_abm({
|
||||
label = "Bamboo Grow",
|
||||
nodenames = mcl_bamboo.bamboo_index,
|
||||
interval = 10,
|
||||
chance = 20,
|
||||
@ -34,6 +35,38 @@ minetest.register_abm({
|
||||
end,
|
||||
})
|
||||
|
||||
--[[ TODO: Figure out how to make this work:
|
||||
local function dropper_call(node, pushdir, stack, stackid)
|
||||
mcl_bamboo.mcl_log("mvps_dropper call for bamboo:")
|
||||
-- mcl_bamboo.break_orphaned()
|
||||
|
||||
mcl_bamboo.mcl_log(dump(node))
|
||||
|
||||
end
|
||||
|
||||
if minetest.get_modpath("mesecons_mvps") then
|
||||
if mesecon then
|
||||
mcl_bamboo.mcl_log("registering mvps_dropper for bamboo:")
|
||||
for x = 1, #mcl_bamboo.bamboo_index do
|
||||
mesecon.register_mvps_dropper(mcl_bamboo.bamboo_index[x],dropper_call)
|
||||
mcl_bamboo.mcl_log("registering: " .. mcl_bamboo.bamboo_index[x])
|
||||
end
|
||||
end
|
||||
else
|
||||
end
|
||||
--]]
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Break Orphaned Bamboo",
|
||||
nodenames = mcl_bamboo.bamboo_index,
|
||||
interval = 1.5,
|
||||
chance = 1,
|
||||
action = function(pos, _)
|
||||
mcl_bamboo.break_orphaned(pos)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- Base Aliases.
|
||||
local SCAFFOLDING_NAME = "mcl_bamboo:scaffolding"
|
||||
minetest.register_alias("bamboo_block", "mcl_bamboo:bamboo_block")
|
||||
|
@ -1,4 +1,4 @@
|
||||
name = mcl_bamboo
|
||||
depends = mcl_core, mcl_sounds, mcl_tools
|
||||
optional_depends = mcl_flowerpots, mclx_stairs, mcl_doors, mcl_signs, mesecons_pressureplates, mcl_fences, mesecons_button
|
||||
optional_depends = mcl_flowerpots, mclx_stairs, mcl_doors, mcl_signs, mesecons_pressureplates, mcl_fences, mesecons_button, mesecons_mvps
|
||||
author = Michieal
|
@ -45,8 +45,8 @@ minetest.register_craft({
|
||||
minetest.register_craft({
|
||||
output = BAMBOO .. "_mosaic",
|
||||
recipe = {
|
||||
{"mcl_stair:slab_bamboo_plank"},
|
||||
{"mcl_stair:slab_bamboo_plank"},
|
||||
{"mcl_stairs:slab_bamboo_plank"},
|
||||
{"mcl_stairs:slab_bamboo_plank"},
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -274,7 +274,11 @@ function mcl_beds.sleep()
|
||||
end
|
||||
-- Always clear weather
|
||||
mcl_weather.change_weather("none")
|
||||
elseif mcl_beds.is_night() then
|
||||
elseif mcl_beds.is_night() and weather_mod then
|
||||
mcl_beds.skip_night()
|
||||
mcl_beds.kick_players()
|
||||
mcl_weather.change_weather("none")
|
||||
elseif mcl_beds.is_night() and not weather_mod then
|
||||
mcl_beds.skip_night()
|
||||
mcl_beds.kick_players()
|
||||
end
|
||||
|
@ -927,30 +927,19 @@ minetest.register_lbm({
|
||||
label = "Replace legacy dry grass",
|
||||
name = "mcl_core:replace_legacy_dry_grass_0_65_0",
|
||||
nodenames = {"mcl_core:dirt_with_dry_grass", "mcl_core:dirt_with_dry_grass_snow"},
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
local biome_data = minetest.get_biome_data(pos)
|
||||
if biome_data then
|
||||
local biome = biome_data.biome
|
||||
local biome_name = minetest.get_biome_name(biome)
|
||||
local reg_biome = minetest.registered_biomes[biome_name]
|
||||
if reg_biome then
|
||||
if node.name == "mcl_core:dirt_with_dry_grass_snow" then
|
||||
node.name = "mcl_core:dirt_with_grass_snow"
|
||||
else
|
||||
node.name = "mcl_core:dirt_with_grass"
|
||||
end
|
||||
node.param2 = reg_biome._mcl_grass_palette_index
|
||||
-- Fall back to savanna palette index
|
||||
-- use savanna palette index to simulate dry grass.
|
||||
if not node.param2 then
|
||||
node.param2 = SAVANNA_INDEX
|
||||
end
|
||||
minetest.set_node(pos, node)
|
||||
return
|
||||
end
|
||||
end
|
||||
node.param2 = SAVANNA_INDEX
|
||||
minetest.set_node(pos, node)
|
||||
return
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -66,7 +66,9 @@ local function spread_nether_plants(pos,node)
|
||||
end
|
||||
|
||||
minetest.register_node("mcl_crimson:warped_fungus", {
|
||||
description = S("Warped Fungus Mushroom"),
|
||||
description = S("Warped Fungus"),
|
||||
_tt_help = S("Warped fungus is a mushroom found in the nether's warped forest."),
|
||||
_doc_items_longdesc = S("Warped fungus is a mushroom found in the nether's warped forest."),
|
||||
drawtype = "plantlike",
|
||||
tiles = { "farming_warped_fungus.png" },
|
||||
inventory_image = "farming_warped_fungus.png",
|
||||
@ -95,7 +97,7 @@ minetest.register_node("mcl_crimson:warped_fungus", {
|
||||
|
||||
mcl_flowerpots.register_potted_flower("mcl_crimson:warped_fungus", {
|
||||
name = "warped fungus",
|
||||
desc = S("Warped Fungus Mushroom"),
|
||||
desc = S("Warped Fungus"),
|
||||
image = "farming_warped_fungus.png",
|
||||
})
|
||||
|
||||
@ -450,7 +452,9 @@ minetest.register_craft({
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_crimson:crimson_fungus", {
|
||||
description = S("Crimson Fungus Mushroom"),
|
||||
description = S("Crimson Fungus"),
|
||||
_tt_help = S("Crimson fungus is a mushroom found in the nether's crimson forest."),
|
||||
_doc_items_longdesc = S("Crimson fungus is a mushroom found in the nether's crimson forest."),
|
||||
drawtype = "plantlike",
|
||||
tiles = { "farming_crimson_fungus.png" },
|
||||
inventory_image = "farming_crimson_fungus.png",
|
||||
@ -483,7 +487,7 @@ minetest.register_node("mcl_crimson:crimson_fungus", {
|
||||
|
||||
mcl_flowerpots.register_potted_flower("mcl_crimson:crimson_fungus", {
|
||||
name = "crimson fungus",
|
||||
desc = S("Crimson Fungus Mushroom"),
|
||||
desc = S("Crimson Fungus"),
|
||||
image = "farming_crimson_fungus.png",
|
||||
})
|
||||
|
||||
|
@ -115,6 +115,15 @@ mobs_griefing (Mobs change blocks) bool true
|
||||
# If enabled, mobs won't damage particles when they got hurt.
|
||||
mobs_disable_blood (Disable mob damage particles) bool false
|
||||
|
||||
#Percentage of peaceful spawn attempts that succeed (default:35)
|
||||
mcl_mob_peaceful_percentage_spawned (Peaceful percentage success) int 35 0 100
|
||||
|
||||
#Percentage of peaceful spawn attempts that are group spawns (default:15)
|
||||
mcl_mob_peaceful_group_percentage_spawned (Peaceful group percentage) int 15 0 100
|
||||
|
||||
#Percentage of hostile spawn attempts that are group spawns (default:20)
|
||||
mcl_mob_hostile_group_percentage_spawned (Hostile group percentage) int 20 0 100
|
||||
|
||||
#Maximum amount mobs (default:500)
|
||||
mcl_mob_cap_total (Global mob cap) int 500 0 2048
|
||||
|
||||
@ -124,8 +133,11 @@ mcl_mob_cap_player (Mob cap per player) int 75 0 2048
|
||||
#Maximum amount of monsters that will spawn near a player (default:70)
|
||||
mcl_mob_cap_monster (Mob cap monsters) int 70 0 2048
|
||||
|
||||
#Maximum amount of animals that will spawn near a player (default:10)
|
||||
mcl_mob_cap_animal (Mob cap animals) int 10 0 1024
|
||||
#Maximum amount of animals that will spawn near a player (default:13)
|
||||
mcl_mob_cap_animal (Mob cap animals) int 13 0 1024
|
||||
|
||||
#Maximum amount of water mobs that will spawn near a player (default:8)
|
||||
mcl_mob_cap_water (Mob cap water) int 8 0 1024
|
||||
|
||||
#Maximum amount of ambient mobs that will spawn near a player (default:15)
|
||||
mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024
|
||||
|
Loading…
Reference in New Issue
Block a user