mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-12-22 16:09:33 +01:00
Update mobs mod
This commit is contained in:
parent
084c299a3c
commit
b25254e516
4 changed files with 84 additions and 135 deletions
|
@ -1,9 +1,9 @@
|
|||
|
||||
-- Mobs Api (4th July 2017)
|
||||
-- Mobs Api (14th July 2017)
|
||||
|
||||
mobs = {}
|
||||
mobs.mod = "redo"
|
||||
mobs.version = "20170704"
|
||||
mobs.version = "20170714"
|
||||
|
||||
|
||||
-- Intllib
|
||||
|
@ -48,7 +48,7 @@ local damage_enabled = minetest.setting_getbool("enable_damage")
|
|||
local peaceful_only = minetest.setting_getbool("only_peaceful_mobs")
|
||||
local disable_blood = minetest.setting_getbool("mobs_disable_blood")
|
||||
local creative = minetest.setting_getbool("creative_mode")
|
||||
local spawn_protected = tonumber(minetest.setting_get("mobs_spawn_protected")) or 1
|
||||
local spawn_protected = minetest.setting_getbool("mobs_spawn_protected") ~= false
|
||||
local remove_far = minetest.setting_getbool("remove_far_mobs")
|
||||
local difficulty = tonumber(minetest.setting_get("mob_difficulty")) or 1.0
|
||||
local show_health = false
|
||||
|
@ -64,6 +64,13 @@ local enable_pathfinding = true
|
|||
local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching
|
||||
local stuck_path_timeout = 10 -- how long will mob follow path before giving up
|
||||
|
||||
-- default nodes
|
||||
local node_fire = "mcl_fire:fire"
|
||||
local node_permanent_flame = "mcl_fire:eternal_fire"
|
||||
local node_ice = "mcl_core:ice"
|
||||
local node_snowblock = "mcl_core:snowblock"
|
||||
local node_snow = "mcl_core:snow"
|
||||
mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt"
|
||||
|
||||
-- play sound
|
||||
local mob_sound = function(self, sound)
|
||||
|
@ -242,9 +249,10 @@ end
|
|||
local flight_check = function(self, pos_w)
|
||||
|
||||
local nod = self.standing_in
|
||||
local def = minetest.registered_nodes[nod]
|
||||
|
||||
if type(self.fly_in) == "string"
|
||||
and (nod == self.fly_in or nod == self.fly_in:gsub("_source", "_flowing")) then
|
||||
and (nod == self.fly_in or def.liquid_alternative_flowing ~= "") then
|
||||
|
||||
return true
|
||||
|
||||
|
@ -252,7 +260,7 @@ local flight_check = function(self, pos_w)
|
|||
|
||||
for _,fly_in in pairs(self.fly_in) do
|
||||
|
||||
if nod == fly_in or nod == fly_in:gsub("_source", "_flowing") then
|
||||
if nod == fly_in or def.liquid_alternative_flowing ~= "" then
|
||||
|
||||
return true
|
||||
end
|
||||
|
@ -507,7 +515,7 @@ end
|
|||
-- get node but use fallback for nil or unknown
|
||||
local node_ok = function(pos, fallback)
|
||||
|
||||
fallback = fallback or "mcl_core:dirt"
|
||||
fallback = fallback or mobs.fallback_node
|
||||
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
|
||||
|
@ -598,8 +606,8 @@ local do_env_damage = function(self)
|
|||
-- lava or fire
|
||||
elseif self.lava_damage
|
||||
and (nodef.groups.lava
|
||||
or self.standing_in == "mcl_fire:fire"
|
||||
or self.standing_in == "mcl_fire:eternal_fire") then
|
||||
or self.standing_in == node_fire
|
||||
or self.standing_in == node_permanent_flame) then
|
||||
|
||||
if self.lava_damage ~= 0 then
|
||||
|
||||
|
@ -681,7 +689,7 @@ local do_jump = function(self)
|
|||
})
|
||||
|
||||
-- thin blocks that do not need to be jumped
|
||||
if nod.name == "mcl_core:snow" then
|
||||
if nod.name == node_snow then
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -1049,7 +1057,7 @@ local smart_mobs = function(self, s, p, dist, dtime)
|
|||
|
||||
if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then
|
||||
|
||||
minetest.set_node(s, {name = "mcl_core:dirt"})
|
||||
minetest.set_node(s, {name = mobs.fallback_node})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1511,7 +1519,7 @@ local do_states = function(self, dtime)
|
|||
and minetest.registered_nodes[self.standing_in].groups.water) then
|
||||
|
||||
lp = minetest.find_node_near(s, 5, {"group:soil", "group:stone",
|
||||
"group:sand", "mcl_core:ice", "mcl_core:snowblock"})
|
||||
"group:sand", node_ice, node_snowblock})
|
||||
|
||||
-- did we find land?
|
||||
if lp then
|
||||
|
@ -1675,30 +1683,36 @@ local do_states = function(self, dtime)
|
|||
|
||||
local pos = self.object:getpos()
|
||||
local radius = self.explosion_radius or 1
|
||||
local damage_radius = radius
|
||||
|
||||
-- dont damage anything if area protected or next to water
|
||||
if minetest.find_node_near(pos, 1, {"group:water"})
|
||||
or minetest.is_protected(pos, "") then
|
||||
|
||||
mob_sound(self, self.sounds.explode)
|
||||
|
||||
self.object:remove()
|
||||
|
||||
effect(pos, 15, "tnt_smoke.png")
|
||||
|
||||
-- hurt player/mobs caught in blast area
|
||||
entity_physics(pos, radius)
|
||||
|
||||
return
|
||||
damage_radius = 0
|
||||
end
|
||||
|
||||
pos.y = pos.y - 1
|
||||
|
||||
mobs:explosion(pos, radius, 0, 1, self.sounds.explode)
|
||||
|
||||
self.object:remove()
|
||||
|
||||
entity_physics(pos, radius)
|
||||
if minetest.get_modpath("tnt") and tnt and tnt.boom
|
||||
and not minetest.is_protected(pos, "") then
|
||||
|
||||
tnt.boom(pos, {
|
||||
radius = radius,
|
||||
damage_radius = damage_radius,
|
||||
sound = self.sounds.explode,
|
||||
})
|
||||
else
|
||||
|
||||
minetest.sound_play(self.sounds.explode, {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = self.sounds.distance or 32
|
||||
})
|
||||
|
||||
entity_physics(pos, damage_radius)
|
||||
effect(pos, 32, "tnt_smoke.png", radius * 3, radius * 5, radius, 1, 0)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
@ -2764,7 +2778,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
|||
end
|
||||
|
||||
-- mobs cannot spawn in protected areas when enabled
|
||||
if spawn_protected == 1
|
||||
if not spawn_protected
|
||||
and minetest.is_protected(pos, "") then
|
||||
--print ("--- inside protected area", name)
|
||||
return
|
||||
|
@ -2850,96 +2864,6 @@ function mobs:spawn(def)
|
|||
end
|
||||
|
||||
|
||||
-- set content id's
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_ignore = minetest.get_content_id("ignore")
|
||||
local c_obsidian = minetest.get_content_id("mcl_core:obsidian")
|
||||
local c_fire = minetest.get_content_id("mcl_fire:fire")
|
||||
|
||||
-- explosion (cannot break protected or unbreakable nodes)
|
||||
function mobs:explosion(pos, radius, fire, smoke, sound)
|
||||
|
||||
radius = radius or 0
|
||||
fire = fire or 0
|
||||
smoke = smoke or 0
|
||||
|
||||
-- if area protected or near map limits then no blast damage
|
||||
if minetest.is_protected(pos, "")
|
||||
or not within_limits(pos, radius) then
|
||||
return
|
||||
end
|
||||
|
||||
-- explosion sound
|
||||
if sound
|
||||
and sound ~= "" then
|
||||
|
||||
minetest.sound_play(sound, {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = 16
|
||||
})
|
||||
end
|
||||
|
||||
pos = vector.round(pos) -- voxelmanip doesn't work properly unless pos is rounded ?!?!
|
||||
|
||||
local vm = VoxelManip()
|
||||
local minp, maxp = vm:read_from_map(vector.subtract(pos, radius), vector.add(pos, radius))
|
||||
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
|
||||
local data = vm:get_data()
|
||||
local p = {}
|
||||
local pr = PseudoRandom(os.time())
|
||||
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
|
||||
for x = -radius, radius do
|
||||
|
||||
p.x = pos.x + x
|
||||
p.y = pos.y + y
|
||||
p.z = pos.z + z
|
||||
|
||||
if (x * x) + (y * y) + (z * z) <= (radius * radius) + pr:next(-radius, radius)
|
||||
and data[vi] ~= c_air
|
||||
and data[vi] ~= c_ignore
|
||||
and data[vi] ~= c_obsidian
|
||||
and data[vi] ~= c_fire then
|
||||
|
||||
local n = node_ok(p).name
|
||||
local on_blast = minetest.registered_nodes[n].on_blast
|
||||
|
||||
if on_blast then
|
||||
|
||||
return on_blast(p)
|
||||
|
||||
elseif minetest.registered_nodes[n].groups.unbreakable == 1 then
|
||||
|
||||
-- do nothing
|
||||
else
|
||||
|
||||
-- after effects
|
||||
if fire > 0
|
||||
and (minetest.registered_nodes[n].groups.flammable
|
||||
or random(1, 100) <= 30) then
|
||||
|
||||
minetest.set_node(p, {name = "mcl_fire:fire"})
|
||||
else
|
||||
minetest.set_node(p, {name = "air"})
|
||||
|
||||
if smoke > 0 then
|
||||
effect(p, 2, "tnt_smoke.png", 3*radius, 5*radius, radius, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vi = vi + 1
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- register arrow for shoot attack
|
||||
function mobs:register_arrow(name, def)
|
||||
|
||||
|
@ -3034,16 +2958,12 @@ function mobs:register_arrow(name, def)
|
|||
end
|
||||
|
||||
local entity = player:get_luaentity()
|
||||
and player:get_luaentity().name or ""
|
||||
|
||||
if self.hit_mob
|
||||
if entity
|
||||
and self.hit_mob
|
||||
and entity._cmi_is_mob == true
|
||||
and tostring(player) ~= self.owner_id
|
||||
and entity ~= self.object:get_luaentity().name
|
||||
and entity ~= "__builtin:item"
|
||||
and entity ~= "__builtin:falling_node"
|
||||
and entity ~= "gauges:hp_bar"
|
||||
and entity ~= "mcl_signs:text"
|
||||
and entity ~= "itemframes:item" then
|
||||
and entity.name ~= self.object:get_luaentity().name then
|
||||
|
||||
self.hit_mob(self, player)
|
||||
|
||||
|
@ -3060,6 +2980,38 @@ function mobs:register_arrow(name, def)
|
|||
end
|
||||
|
||||
|
||||
-- compatibility function
|
||||
function mobs:explosion(pos, radius)
|
||||
local self = {sounds = {}}
|
||||
self.sounds.explode = "tnt_explode"
|
||||
mobs:boom(self, pos, radius)
|
||||
end
|
||||
|
||||
|
||||
-- make explosion with protection and tnt mod check
|
||||
function mobs:boom(self, pos, radius)
|
||||
|
||||
if minetest.get_modpath("tnt") and tnt and tnt.boom
|
||||
and not minetest.is_protected(pos, "") then
|
||||
|
||||
tnt.boom(pos, {
|
||||
radius = radius,
|
||||
damage_radius = radius,
|
||||
sound = self.sounds.explode,
|
||||
})
|
||||
else
|
||||
minetest.sound_play(self.sounds.explode, {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = self.sounds.distance or 32
|
||||
})
|
||||
|
||||
entity_physics(pos, radius)
|
||||
effect(pos, 32, "tnt_smoke.png", radius * 3, radius * 5, radius, 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Register spawn eggs
|
||||
|
||||
-- Note: This also introduces the “spawn_egg” group:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
MOB API (4th July 2017)
|
||||
MOB API (13th July 2017)
|
||||
|
||||
The mob api is a function that can be called on by other mods to add new animals or monsters into minetest.
|
||||
|
||||
|
@ -8,7 +8,7 @@ The mob api is a function that can be called on by other mods to add new animals
|
|||
'enable_damage' if true monsters will attack players (default is true)
|
||||
'only_peaceful_mobs' if true only animals will spawn in game (default is false)
|
||||
'mobs_disable_blood' if false blood effects appear when mob is hit (default is false)
|
||||
'mobs_spawn_protected' if set to 1 then mobs will not spawn in protected areas (default is 0)
|
||||
'mobs_spawn_protected' if set to false then mobs will not spawn in protected areas (default is true)
|
||||
'remove_far_mobs' if true then mobs that are outside players visual range will be removed (default is false)
|
||||
'mobname' can change specific mob chance rate (0 to disable) and spawn number e.g. mobs_animal:cow = 1000,5
|
||||
'mob_difficulty' sets difficulty level (health and hit damage multiplied by this number), defaults to 1.0.
|
||||
|
@ -229,15 +229,14 @@ This function registers a spawn egg which can be used by admin to properly spawn
|
|||
'no_creative' when set to true this stops spawn egg appearing in creative mode for destructive mobs like Dungeon Masters
|
||||
|
||||
|
||||
mobs:explosion(pos, radius, fire, smoke)
|
||||
mobs:explosion(pos, radius) -- DEPRECATED!!! use mobs:boom() instead
|
||||
|
||||
This function generates an explosion which removes nodes in a specific radius and replace them with fire or air. Protection nodes, obsidian and locked chests will not be destroyed although a normal chest will drop it's contents.
|
||||
mobs:boom(self, pos, radius)
|
||||
This function generates an explosion which removes nodes in a specific radius and damages any entity caught inside the blast radius. Protection will limit node destruction but not entity damage.
|
||||
|
||||
'self' mob entity
|
||||
'pos' centre position of explosion
|
||||
'radius' radius of explosion (typically set to 3)
|
||||
'fire' should fire appear in explosion (1=yes, 0=no)
|
||||
'smoke' should smoke appear in explosion (1=yes, 0=no)
|
||||
'sound' sound played when mob explodes
|
||||
|
||||
|
||||
mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
mcl_core
|
||||
mcl_hunger
|
||||
mcl_sounds
|
||||
invisibility?
|
||||
intllib?
|
||||
lucky_block?
|
||||
|
|
|
@ -12,7 +12,7 @@ local crash_threshold = 6.5 -- ignored if enable_crash=false
|
|||
|
||||
local node_ok = function(pos, fallback)
|
||||
|
||||
fallback = fallback or "mcl_core:dirt"
|
||||
fallback = fallback or mobs.fallback_node
|
||||
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
|
||||
|
|
Loading…
Reference in a new issue