1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2025-07-19 16:50:25 +02:00

Compare commits

...

6 Commits

4 changed files with 126 additions and 39 deletions

145
api.lua
View File

@ -8,7 +8,7 @@ local use_cmi = minetest.global_exists("cmi")
mobs = {
mod = "redo",
version = "20201029",
version = "20201206",
intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {}
}
@ -58,6 +58,7 @@ local mobs_drop_items = settings:get_bool("mobs_drop_items") ~= false
local mobs_griefing = settings:get_bool("mobs_griefing") ~= false
local spawn_protected = settings:get_bool("mobs_spawn_protected") ~= false
local remove_far = settings:get_bool("remove_far_mobs") ~= false
local mob_area_spawn = settings:get_bool("mob_area_spawn")
local difficulty = tonumber(settings:get("mob_difficulty")) or 1.0
local show_health = settings:get_bool("mob_show_health") ~= false
local max_per_block = tonumber(settings:get("max_objects_per_block") or 99)
@ -111,6 +112,7 @@ local mob_class = {
light_damage_max = 15,
water_damage = 0,
lava_damage = 0,
air_damage = 0,
suffocation = 2,
fall_damage = 1,
fall_speed = -10, -- must be lower than -2 (default: -10)
@ -276,10 +278,10 @@ function mob_class:set_velocity(v)
c_x, c_y = unpack(self:collision())
end
local yaw = (self.object:get_yaw() or 0) + self.rotate
local yaw = (self.object:get_yaw() or 0) + (self.rotate or 0)
-- nil check for velocity
v = v or 0
v = v or 0.01
-- check if standing in liquid with max viscosity of 7
local visc = min(minetest.registered_nodes[self.standing_in].liquid_viscosity, 7)
@ -291,8 +293,8 @@ function mob_class:set_velocity(v)
v = v / (visc + 1)
end
-- set velocity with hard limit of 10
local vel = self.object:get_velocity()
-- set velocity
local vel = self.object:get_velocity() or 0
local new_vel = {
x = (sin(yaw) * -v) + c_x,
@ -828,6 +830,11 @@ end
-- check if mob is dead or only hurt
function mob_class:check_for_death(cmi_cause)
-- We dead already
if self.state == "die" then
return true
end
-- has health actually changed?
if self.health == self.old_health and self.health > 0 then
return false
@ -877,7 +884,7 @@ function mob_class:check_for_death(cmi_cause)
local pos = self.object:get_pos()
-- execute custom death function
if self.on_die then
if pos and self.on_die then
self:on_die(pos)
@ -897,7 +904,8 @@ function mob_class:check_for_death(cmi_cause)
local frames = self.animation.die_end - self.animation.die_start
local speed = self.animation.die_speed or 15
local length = max(frames / speed, 0)
local length = max((frames / speed), 0)
local rot = self.animation.die_rotate and 5
self.attack = nil
self.v_start = false
@ -905,28 +913,37 @@ function mob_class:check_for_death(cmi_cause)
self.blinktimer = 0
self.passive = true
self.state = "die"
self.object:set_properties({
pointable = false, collide_with_objects = false,
automatic_rotate = rot,
})
self:set_velocity(0)
self:set_animation("die")
minetest.after(length, function(self)
if use_cmi and self.object:get_luaentity() then
cmi.notify_die(self.object, cmi_cause)
if self.object:get_luaentity() then
if use_cmi then
cmi.notify_die(self.object, cmi_cause)
end
remove_mob(self, true)
end
remove_mob(self, true)
end, self)
else
return true
elseif pos then -- otherwise remove mod and show particle effect
if use_cmi then
cmi.notify_die(self.object, cmi_cause)
end
remove_mob(self, true)
end
effect(pos, 20, "tnt_smoke.png")
effect(pos, 20, "tnt_smoke.png")
end
return true
end
@ -1084,6 +1101,19 @@ function mob_class:do_env_damage()
end
end
-- air damage
if self.air_damage ~= 0 and self.standing_in == "air" then
self.health = self.health - self.air_damage
effect(pos, 3, "bubble.png", 1, 1, 1, 0.2)
if self:check_for_death({type = "environment",
pos = pos, node = self.standing_in}) then
return true
end
end
-- is mob light sensative, or scared of the dark :P
if self.light_damage ~= 0 then
@ -1290,16 +1320,20 @@ function mob_class:follow_holding(clicker)
return false
end
-- Thanks Wuzzy for the following editable settings
local HORNY_TIME = 30
local HORNY_AGAIN_TIME = 300
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- find two animals of same type and breed if nearby and horny
function mob_class:breed()
-- child takes 240 seconds before growing into adult
-- child takes a long time before growing into adult
if self.child == true then
self.hornytimer = self.hornytimer + 1
if self.hornytimer > 240 then
if self.hornytimer > CHILD_GROW_TIME then
self.child = false
self.hornytimer = 0
@ -1328,14 +1362,14 @@ function mob_class:breed()
return
end
-- horny animal can mate for 40 seconds,
-- afterwards horny animal cannot mate again for 200 seconds
-- horny animal can mate for HORNY_TIME seconds,
-- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds
if self.horny == true
and self.hornytimer < 240 then
and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then
self.hornytimer = self.hornytimer + 1
if self.hornytimer >= 240 then
if self.hornytimer >= HORNY_TIME + HORNY_AGAIN_TIME then
self.hornytimer = 0
self.horny = false
end
@ -1343,7 +1377,7 @@ function mob_class:breed()
-- find another same animal who is also horny and mate if nearby
if self.horny == true
and self.hornytimer <= 40 then
and self.hornytimer <= HORNY_TIME then
local pos = self.object:get_pos()
@ -1351,7 +1385,6 @@ function mob_class:breed()
"heart.png", 3, 4, 1, 0.1)
local objs = minetest.get_objects_inside_radius(pos, 3)
local num = 0
local ent
for n = 1, #objs do
@ -1380,18 +1413,20 @@ function mob_class:breed()
end
end
if ent
-- found another similar horny animal that isn't self?
if ent and ent.object ~= self.object
and canmate == true
and ent.horny == true
and ent.hornytimer <= 40 then
num = num + 1
end
and ent.hornytimer <= HORNY_TIME then
-- found your mate? then have a baby
if num > 1 then
local pos2 = ent.object:get_pos()
self.hornytimer = 41
ent.hornytimer = 41
-- Have mobs face one another
yaw_to_pos(self, pos2)
yaw_to_pos(ent, self.object:get_pos())
self.hornytimer = HORNY_TIME + 1
ent.hornytimer = HORNY_TIME + 1
-- have we reached active mob limit
if active_limit > 0 and active_mobs >= active_limit then
@ -1459,8 +1494,6 @@ function mob_class:breed()
ent2.owner = self.owner
end, self, ent)
num = 0
break
end
end
@ -2005,10 +2038,11 @@ function mob_class:follow_flop()
self.following = nil
end
else
-- stop following player if not holding specific item
-- stop following player if not holding specific item or mob is horny
if self.following
and self.following:is_player()
and self:follow_holding(self.following) == false then
and (self:follow_holding(self.following) == false
or self.horny) then
self.following = nil
end
@ -2064,6 +2098,15 @@ function mob_class:follow_flop()
if not self:attempt_flight_correction() then
self.state = "flop"
-- do we have a custom on_flop function?
if self.on_flop then
if self:on_flop(self) then
return
end
end
self.object:set_velocity({x = 0, y = -5, z = 0})
self:set_animation("stand")
@ -3462,6 +3505,7 @@ minetest.register_entity(name, setmetatable({
owner = def.owner,
order = def.order,
on_die = def.on_die,
on_flop = def.on_flop,
do_custom = def.do_custom,
jump_height = def.jump_height,
drawtype = def.drawtype, -- DEPRECATED, use rotate instead
@ -3485,6 +3529,7 @@ minetest.register_entity(name, setmetatable({
light_damage_max = def.light_damage_max,
water_damage = def.water_damage,
lava_damage = def.lava_damage,
air_damage = def.air_damage,
suffocation = def.suffocation,
fall_damage = def.fall_damage,
fall_speed = def.fall_speed,
@ -3903,8 +3948,27 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end
end
-- returns position if we have enough space to spawn mob
pos = can_spawn(pos, name)
-- should we check mob area for obstructions ?
if mob_area_spawn ~= true then
-- do we have enough height clearance to spawn mob?
local ent = minetest.registered_entities[name]
local height = max(1, math.ceil(
(ent.collisionbox[5] or 0.25) - (ent.collisionbox[2] or -0.25) - 1))
for n = 0, height do
local pos2 = {x = pos.x, y = pos.y + n, z = pos.z}
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
--print ("--- inside block", name, node_ok(pos2).name)
return
end
end
else
-- returns position if we have enough space to spawn mob
pos = can_spawn(pos, name)
end
if pos then
@ -4547,8 +4611,11 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
-- make children grow quicker
if self.child == true then
self.hornytimer = self.hornytimer + 20
-- self.hornytimer = self.hornytimer + 20
-- deduct 10% of the time to adulthood
self.hornytimer = self.hornytimer + (
(CHILD_GROW_TIME - self.hornytimer) * 0.1)
print ("====", self.hornytimer)
return true
end

16
api.txt
View File

@ -64,6 +64,7 @@ functions needed for the mob to work properly which contains the following:
'fall_damage' when true causes falling to inflict damage.
'water_damage' holds the damage per second infliced to mobs when standing in
water.
'air_damage' holds damage per second inflicted to mob when standing in air.
'lava_damage' holds the damage per second inflicted to mobs when standing
in lava or fire or an ignition source.
'light_damage' holds the damage per second inflicted to mobs when light
@ -226,6 +227,7 @@ functions needed for the mob to work properly which contains the following:
'die_end'
'die_speed'
'die_loop' when set to false stops the animation looping.
'die_rotate' if true mob spins during death animation.
Using '_loop = false' setting will stop any of the above animations from
looping.
@ -298,6 +300,9 @@ enhance mob functionality and have them do many interesting things:
is returned normal attack function continued.
'on_die' a function that is called when mob is killed (self, pos), also
has access to self.cause_of_death table.
'on_flop' function called when flying or swimmimng mob is no longer in
air/water, (self) paramater and return true to skip the built
in api flop feature.
'do_custom' a custom function that is called every tick while mob is
active and which has access to all of the self.* variables
e.g. (self.health for health or self.standing_in for node
@ -329,6 +334,14 @@ for each mob.
'self.order' set to "follow" or "stand" so that npc will follow owner
or stand it's ground
'self.nametag' contains the name of the mob which it can show above
'self.state' Current mob state.
"stand": no movement (except turning around)
"walk": walk or move around aimlessly
"attack": chase and attack enemy
"runaway": flee from target
"flop": bounce around aimlessly
(for swimming mobs that have stranded)
"die": during death
Adding Mobs in World
@ -697,6 +710,9 @@ External Settings for "minetest.conf"
function.
'mob_nospawn_range' Minimum range a mob can spawn near player (def: 12)
'mob_active_limit' Number of active mobs in game, 0 for unlimited
'mob_area_spawn' When true will check surrounding area the size of the
mob for obstructions before spawning, otherwise it
defaults to checking the height of the mob only.
Players can override the spawn chance for each mob registered by adding a line
to their minetest.conf file with a new value, the lower the value the more each

View File

@ -23,6 +23,7 @@ Lucky Blocks: 9
Changelog:
- 1.54 - Simplified animal breeding function, added editable settings (thanks Wuzzy), Child mobs now take 20 mins to grow up, reverted to simple mob spawning with setting to use area checks, on_flop added, air_damage added.
- 1.53 - Added 'on_map_load' settings to mobs:spawn so that mobs will only spawn when new areas of map are loaded.
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game,
(default is 0 for unlimited), removed {immortal} from mob armor, fluid viscocity slows mobs

View File

@ -33,3 +33,6 @@ mob_nospawn_range (Mob no-spawn range) float 12.0
# Sets maximum number of active mobs in game (0 for unlimited)
mob_active_limit (Mob Active Limit) float 0
# Enables area check when spawning mobs
mob_area_spawn (Mob Area Spawn) bool false