forked from VoxeLibre/VoxeLibre
Merge pull request 'Next bunch of mob fixes' (#2637) from mob_fixes into master
Reviewed-on: MineClone2/MineClone2#2637
This commit is contained in:
commit
630c2fbcef
|
@ -1,4 +1,3 @@
|
|||
|
||||
-- API for Mobs Redo: MineClone 2 Edition (MRM)
|
||||
|
||||
mcl_mobs = {}
|
||||
|
@ -14,12 +13,6 @@ local FLOP_HOR_SPEED = 1.5
|
|||
local ENTITY_CRAMMING_MAX = 24
|
||||
local CRAMMING_DAMAGE = 3
|
||||
|
||||
local MOB_CAP = {}
|
||||
MOB_CAP.hostile = 70
|
||||
MOB_CAP.passive = 10
|
||||
MOB_CAP.ambient = 15
|
||||
MOB_CAP.water = 15
|
||||
|
||||
-- Localize
|
||||
local S = minetest.get_translator("mcl_mobs")
|
||||
|
||||
|
@ -36,6 +29,7 @@ local max = math.max
|
|||
local atann = math.atan
|
||||
local random = math.random
|
||||
local floor = math.floor
|
||||
local ceil = math.ceil
|
||||
|
||||
local atan = function(x)
|
||||
if not x or x ~= x then
|
||||
|
@ -45,7 +39,6 @@ local atan = function(x)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- Load settings
|
||||
local damage_enabled = minetest.settings:get_bool("enable_damage")
|
||||
local disable_blood = minetest.settings:get_bool("mobs_disable_blood")
|
||||
|
@ -55,11 +48,10 @@ local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= fa
|
|||
local remove_far = true
|
||||
local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0
|
||||
local show_health = false
|
||||
local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 64)
|
||||
local mobs_spawn_chance = tonumber(minetest.settings:get("mobs_spawn_chance") or 2.5)
|
||||
|
||||
-- Shows helpful debug info above each mob
|
||||
local mobs_debug = minetest.settings:get_bool("mobs_debug", false)
|
||||
local spawn_logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true)
|
||||
|
||||
-- Peaceful mode message so players will know there are no monsters
|
||||
if minetest.settings:get_bool("only_peaceful_mobs", false) then
|
||||
|
@ -155,7 +147,7 @@ local mob_sound = function(self, soundname, is_opinion, fixed_pitch)
|
|||
pitch = base_pitch
|
||||
end
|
||||
-- randomize the pitch a bit
|
||||
pitch = pitch + math.random(-10, 10) * 0.005
|
||||
pitch = pitch + random(-10, 10) * 0.005
|
||||
end
|
||||
minetest.sound_play(sound, {
|
||||
object = self.object,
|
||||
|
@ -288,7 +280,7 @@ local function update_roll(self)
|
|||
local cbox = table.copy(self.collisionbox)
|
||||
local acbox = self.object:get_properties().collisionbox
|
||||
|
||||
if math.abs(cbox[2] - acbox[2]) > 0.1 then
|
||||
if abs(cbox[2] - acbox[2]) > 0.1 then
|
||||
was_Fleckenstein = true
|
||||
end
|
||||
|
||||
|
@ -311,7 +303,10 @@ end
|
|||
|
||||
-- set and return valid yaw
|
||||
local set_yaw = function(self, yaw, delay, dtime)
|
||||
|
||||
if true then
|
||||
self.object:set_yaw(yaw)
|
||||
return yaw
|
||||
end
|
||||
if not yaw or yaw ~= yaw then
|
||||
yaw = 0
|
||||
end
|
||||
|
@ -320,7 +315,7 @@ local set_yaw = function(self, yaw, delay, dtime)
|
|||
|
||||
if delay == 0 then
|
||||
if self.shaking and dtime then
|
||||
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
|
||||
yaw = yaw + (random() * 2 - 1) * 5 * dtime
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
update_roll(self)
|
||||
|
@ -589,7 +584,7 @@ local damage_effect = function(self, damage)
|
|||
-- damage particles
|
||||
if (not disable_blood) and damage > 0 then
|
||||
|
||||
local amount_large = math.floor(damage / 2)
|
||||
local amount_large = floor(damage / 2)
|
||||
local amount_small = damage % 2
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
|
@ -715,7 +710,7 @@ local item_drop = function(self, cooked, looting_level)
|
|||
end
|
||||
|
||||
if do_common_looting then
|
||||
num = num + math.floor(math.random(0, looting_level) + 0.5)
|
||||
num = num + floor(random(0, looting_level) + 0.5)
|
||||
end
|
||||
|
||||
if num > 0 then
|
||||
|
@ -824,7 +819,7 @@ local check_for_death = function(self, cause, cmi_cause)
|
|||
item_drop(self, cooked, looting)
|
||||
|
||||
if ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then
|
||||
mcl_experience.throw_xp(self.object:get_pos(), math.random(self.xp_min, self.xp_max))
|
||||
mcl_experience.throw_xp(self.object:get_pos(), random(self.xp_min, self.xp_max))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1205,7 +1200,7 @@ local do_env_damage = function(self)
|
|||
end
|
||||
if drowning then
|
||||
|
||||
self.breath = math.max(0, self.breath - 1)
|
||||
self.breath = max(0, self.breath - 1)
|
||||
|
||||
effect(pos, 2, "bubble.png", nil, nil, 1, nil)
|
||||
if self.breath <= 0 then
|
||||
|
@ -1223,7 +1218,7 @@ local do_env_damage = function(self)
|
|||
return true
|
||||
end
|
||||
else
|
||||
self.breath = math.min(self.breath_max, self.breath + 1)
|
||||
self.breath = min(self.breath_max, self.breath + 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1549,7 +1544,7 @@ local breed = function(self)
|
|||
return
|
||||
end
|
||||
|
||||
mcl_experience.throw_xp(pos, math.random(1, 7))
|
||||
mcl_experience.throw_xp(pos, random(1, 7))
|
||||
|
||||
-- custom breed function
|
||||
if parent1.on_breed then
|
||||
|
@ -1565,7 +1560,7 @@ local breed = function(self)
|
|||
|
||||
|
||||
-- Use texture of one of the parents
|
||||
local p = math.random(1, 2)
|
||||
local p = random(1, 2)
|
||||
if p == 1 then
|
||||
ent_c.base_texture = parent1.base_texture
|
||||
else
|
||||
|
@ -1727,7 +1722,7 @@ local smart_mobs = function(self, s, p, dist, dtime)
|
|||
end, self)
|
||||
end
|
||||
|
||||
if math.abs(vector.subtract(s,target_pos).y) > self.stepheight then
|
||||
if abs(vector.subtract(s,target_pos).y) > self.stepheight then
|
||||
|
||||
if height_switcher then
|
||||
use_pathfind = true
|
||||
|
@ -1768,7 +1763,7 @@ local smart_mobs = function(self, s, p, dist, dtime)
|
|||
if self.fear_height ~= 0 then dropheight = self.fear_height end
|
||||
local jumpheight = 0
|
||||
if self.jump and self.jump_height >= 4 then
|
||||
jumpheight = math.min(math.ceil(self.jump_height / 4), 4)
|
||||
jumpheight = min(ceil(self.jump_height / 4), 4)
|
||||
elseif self.stepheight > 0.5 then
|
||||
jumpheight = 1
|
||||
end
|
||||
|
@ -1799,7 +1794,7 @@ local smart_mobs = function(self, s, p, dist, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
local sheight = math.ceil(self.collisionbox[5]) + 1
|
||||
local sheight = ceil(self.collisionbox[5]) + 1
|
||||
|
||||
-- assume mob is 2 blocks high so it digs above its head
|
||||
s.y = s.y + sheight
|
||||
|
@ -1946,7 +1941,7 @@ local monster_attack = function(self)
|
|||
|
||||
-- find specific mob to attack, failing that attack player/npc/animal
|
||||
if specific_attack(self.specific_attack, name)
|
||||
and (type == "player" or type == "npc"
|
||||
and (type == "player" or ( type == "npc" and self.attack_npcs )
|
||||
or (type == "animal" and self.attack_animals == true)) then
|
||||
|
||||
p = player:get_pos()
|
||||
|
@ -2237,9 +2232,9 @@ local follow_flop = function(self)
|
|||
if sdef and sdef.walkable then
|
||||
mob_sound(self, "flop")
|
||||
self.object:set_velocity({
|
||||
x = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED),
|
||||
x = random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED),
|
||||
y = FLOP_HEIGHT,
|
||||
z = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED),
|
||||
z = random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED),
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -2294,8 +2289,8 @@ local function go_to_pos(entity,b)
|
|||
return true
|
||||
end
|
||||
local v = { x = b.x - s.x, z = b.z - s.z }
|
||||
local yaw = (math.atan(v.z / v.x) + math.pi / 2) - entity.rotate
|
||||
if b.x > s.x then yaw = yaw + math.pi end
|
||||
local yaw = (atann(v.z / v.x) + pi / 2) - entity.rotate
|
||||
if b.x > s.x then yaw = yaw + pi end
|
||||
entity.object:set_yaw(yaw)
|
||||
set_velocity(entity,entity.follow_velocity)
|
||||
mcl_mobs:set_animation(entity, "walk")
|
||||
|
@ -3403,21 +3398,22 @@ end
|
|||
-- get entity staticdata
|
||||
local mob_staticdata = function(self)
|
||||
|
||||
--[[
|
||||
|
||||
-- remove mob when out of range unless tamed
|
||||
if remove_far
|
||||
and self.can_despawn
|
||||
and self.remove_ok
|
||||
and ((not self.nametag) or (self.nametag == ""))
|
||||
and self.lifetimer <= 20 then
|
||||
|
||||
minetest.log("action", "Mob "..name.." despawns in mob_staticdata at "..minetest.pos_to_string(self.object.get_pos(), 1))
|
||||
if spawn_logging then
|
||||
minetest.log("action", "[mcl_mobs] Mob "..tostring(self.name).." despawns in mob_staticdata at "..minetest.pos_to_string(self.object:get_pos()))
|
||||
end
|
||||
mcl_burning.extinguish(self.object)
|
||||
self.object:remove()
|
||||
|
||||
return ""-- nil
|
||||
return "remove"-- nil
|
||||
end
|
||||
--]]
|
||||
|
||||
self.remove_ok = true
|
||||
self.attack = nil
|
||||
self.following = nil
|
||||
|
@ -3453,6 +3449,11 @@ local mob_activate = function(self, staticdata, def, dtime)
|
|||
return
|
||||
end
|
||||
|
||||
if staticdata == "remove" then
|
||||
mcl_burning.extinguish(self.object)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
-- load entity variables
|
||||
local tmp = minetest.deserialize(staticdata)
|
||||
|
||||
|
@ -3473,7 +3474,7 @@ local mob_activate = function(self, staticdata, def, dtime)
|
|||
local c = 1
|
||||
if #def.textures > c then c = #def.textures end
|
||||
|
||||
self.base_texture = def.textures[math.random(c)]
|
||||
self.base_texture = def.textures[random(c)]
|
||||
self.base_mesh = def.mesh
|
||||
self.base_size = self.visual_size
|
||||
self.base_colbox = self.collisionbox
|
||||
|
@ -3620,6 +3621,7 @@ end
|
|||
|
||||
-- main mob function
|
||||
local mob_step = function(self, dtime)
|
||||
self.lifetimer = self.lifetimer - dtime
|
||||
check_item_pickup(self)
|
||||
check_aggro(self,dtime)
|
||||
if not self.fire_resistant then
|
||||
|
@ -3686,7 +3688,7 @@ local mob_step = function(self, dtime)
|
|||
|
||||
self.delay = self.delay - 1
|
||||
if self.shaking then
|
||||
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
|
||||
yaw = yaw + (random() * 2 - 1) * 5 * dtime
|
||||
end
|
||||
self.object:set_yaw(yaw)
|
||||
update_roll(self)
|
||||
|
@ -3833,14 +3835,15 @@ local mob_step = function(self, dtime)
|
|||
and ((not self.nametag) or (self.nametag == ""))
|
||||
and self.state ~= "attack"
|
||||
and self.following == nil then
|
||||
|
||||
self.lifetimer = self.lifetimer - dtime
|
||||
if self.despawn_immediately or self.lifetimer <= 0 then
|
||||
minetest.log("action", "Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1))
|
||||
if spawn_logging then
|
||||
minetest.log("action", "[mcl_mobs] Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1))
|
||||
end
|
||||
mcl_burning.extinguish(self.object)
|
||||
self.object:remove()
|
||||
return
|
||||
elseif self.lifetimer <= 10 then
|
||||
if math.random(10) < 4 then
|
||||
if random(10) < 4 then
|
||||
self.despawn_immediately = true
|
||||
else
|
||||
self.lifetimer = 20
|
||||
|
@ -4030,6 +4033,7 @@ minetest.register_entity(name, {
|
|||
dogshoot_count_max = def.dogshoot_count_max or 5,
|
||||
dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5),
|
||||
attack_animals = def.attack_animals or false,
|
||||
attack_npcs = def.attack_npcs or false,
|
||||
specific_attack = def.specific_attack,
|
||||
runaway_from = def.runaway_from,
|
||||
owner_loyal = def.owner_loyal,
|
||||
|
@ -4512,7 +4516,7 @@ minetest.register_globalstep(function(dtime)
|
|||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 47)) do
|
||||
local lua = obj:get_luaentity()
|
||||
if lua and lua.is_mob then
|
||||
lua.lifetimer = math.max(20, lua.lifetimer)
|
||||
lua.lifetimer = max(20, lua.lifetimer)
|
||||
lua.despawn_immediately = false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,16 +29,17 @@ local dbg_spawn_succ = 0
|
|||
local aoc_range = 136
|
||||
|
||||
local mob_cap = {
|
||||
monster = 70,
|
||||
animal =10,
|
||||
ambient =15,
|
||||
water = 5, --currently unused
|
||||
water_ambient = 20, --currently unused
|
||||
monster = minetest.settings:get_bool("mcl_mob_cap_monster") or 70,
|
||||
animal = minetest.settings:get_bool("mcl_mob_cap_animal") or 10,
|
||||
ambient = minetest.settings:get_bool("mcl_mob_cap_ambient") or 15,
|
||||
water = minetest.settings:get_bool("mcl_mob_cap_water") or 5, --currently unused
|
||||
water_ambient = minetest.settings:get_bool("mcl_mob_cap_water_ambient") or 20, --currently unused
|
||||
}
|
||||
|
||||
--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
|
||||
local logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true)
|
||||
|
||||
local noise_params = {
|
||||
offset = 0,
|
||||
|
@ -456,6 +457,7 @@ local function spawn_check(pos,spawn_def)
|
|||
and (spawn_def.check_position and spawn_def.check_position(pos) or true)
|
||||
and (not is_farm_animal(spawn_def.name) or is_grass)
|
||||
and (spawn_def.type_of_spawning ~= "water" or is_water)
|
||||
and ( not spawn_protected or not minetest.is_protected(s, "") )
|
||||
and not is_bedrock then
|
||||
--only need to poll for node light if everything else worked
|
||||
local gotten_light = get_node_light(pos)
|
||||
|
@ -466,6 +468,15 @@ local function spawn_check(pos,spawn_def)
|
|||
return false
|
||||
end
|
||||
|
||||
function mcl_mobs.spawn(pos,id)
|
||||
local def = minetest.registered_entities[id] or minetest.registered_entities["mobs_mc:"..id] or minetest.registered_entities["extra_mobs:"..id]
|
||||
if not def or (def.can_spawn and not def.can_spawn(pos)) or not def.is_mob then
|
||||
return false
|
||||
end
|
||||
return minetest.add_entity(pos, def.name)
|
||||
end
|
||||
|
||||
|
||||
local function spawn_group(p,mob,spawn_on,group_max,group_min)
|
||||
if not group_min then group_min = 1 end
|
||||
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
|
||||
|
@ -481,13 +492,27 @@ local function spawn_group(p,mob,spawn_on,group_max,group_min)
|
|||
if mob.type_of_spawning == "water" then
|
||||
sp = get_water_spawn(sp)
|
||||
end
|
||||
o = minetest.add_entity(sp,mob.name)
|
||||
o = mcl_mobs.spawn(sp,mob.name)
|
||||
if o then dbg_spawn_succ = dbg_spawn_succ + 1 end
|
||||
end
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
mcl_mobs.spawn_group = spawn_group
|
||||
|
||||
minetest.register_chatcommand("spawn_mob",{
|
||||
privs = { debug = true },
|
||||
func = function(n,param)
|
||||
local pos = minetest.get_player_by_name(n):get_pos()
|
||||
if mcl_mobs.spawn(pos,param) then
|
||||
return true, param.." spawned at "..minetest.pos_to_string(pos),
|
||||
minetest.log("action", n.." spawned "..param.." at "..minetest.pos_to_string(pos))
|
||||
end
|
||||
return false, "Couldn't spawn "..param
|
||||
end
|
||||
})
|
||||
|
||||
if mobs_spawn then
|
||||
|
||||
local perlin_noise
|
||||
|
@ -538,11 +563,16 @@ if mobs_spawn then
|
|||
--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 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)
|
||||
minetest.log("action", "A group of mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1))
|
||||
|
||||
else
|
||||
object = minetest.add_entity(spawning_position, mob_def.name)
|
||||
minetest.log("action", "Mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1))
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_mobs] Mob " .. mob_def.name .. " spawns at " .. minetest.pos_to_string(spawning_position, 1))
|
||||
end
|
||||
object = mcl_mobs.spawn(spawning_position, mob_def.name)
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ pillager = {
|
|||
fear_height = 4,
|
||||
arrow = "mcl_bows:arrow_entity",
|
||||
attack_type = "dogshoot", -- Alternate punching/shooting
|
||||
attack_npcs = true,
|
||||
reach = 0, -- Punching max distance
|
||||
damage = 0, -- Punching damage
|
||||
dogshoot_switch = 1, -- Start of shooting
|
||||
|
|
|
@ -38,6 +38,7 @@ mcl_mobs:register_mob("mobs_mc:vindicator", {
|
|||
walk_velocity = 1.2,
|
||||
run_velocity = 2.4,
|
||||
attack_type = "dogfight",
|
||||
attack_npcs = true,
|
||||
drops = {
|
||||
{name = "mcl_core:emerald",
|
||||
chance = 1,
|
||||
|
|
|
@ -133,6 +133,7 @@ mcl_mobs:register_mob("mobs_mc:villager_zombie", {
|
|||
view_range = 16,
|
||||
fear_height = 4,
|
||||
harmed_by_heal = true,
|
||||
attack_npcs = true,
|
||||
})
|
||||
|
||||
mcl_mobs:spawn_specific(
|
||||
|
|
|
@ -101,6 +101,7 @@ local zombie = {
|
|||
self.object:set_properties({visual_size = self.visual_size})
|
||||
self.base_size = self.visual_size
|
||||
end,
|
||||
attack_npcs = true,
|
||||
}
|
||||
|
||||
mcl_mobs:register_mob("mobs_mc:zombie", zombie)
|
||||
|
|
|
@ -76,10 +76,6 @@ mcl_enable_skin_customization (Enable player skin customization) bool true
|
|||
# This setting is only read at startup.
|
||||
mobs_spawn (Spawn mobs naturally) bool true
|
||||
|
||||
# Controls the overall amount of mobs that spawn. The higher the number,
|
||||
# the less often mobs will spawn. This does not affect mob spawners.
|
||||
mobs_spawn_chance (Mob spawn chance) float 2.5 0.0
|
||||
|
||||
# If enabled, only peaceful mobs will appear naturally. This does not
|
||||
# affect mob spawners.
|
||||
# This setting is only read at startup.
|
||||
|
@ -103,6 +99,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
|
||||
|
||||
#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 ambient mobs that will spawn near a player (default:15)
|
||||
mcl_mob_cap_ambient (Mob cap ambient mobs) int 15 0 1024
|
||||
|
||||
[Audio]
|
||||
# Enable flame sound.
|
||||
flame_sound (Flame sound) bool true
|
||||
|
@ -186,3 +191,6 @@ mcl_enable_fapples (Enable swiftness on enchanted golden apples) bool true
|
|||
[Debugging]
|
||||
# If enabled, this will show the itemstring of an item in the description.
|
||||
mcl_item_id_debug (Item ID Debug) bool false
|
||||
|
||||
#Log mob spawning and despawning events
|
||||
mcl_logging_mobs_spawn (Log Mob Spawning) bool true
|
||||
|
|
Loading…
Reference in New Issue