mirror of
https://codeberg.org/tenplus1/mobs_redo.git
synced 2025-07-19 16:50:25 +02:00
Compare commits
6 Commits
d12576f0c8
...
bf32a09e5e
Author | SHA1 | Date | |
---|---|---|---|
bf32a09e5e | |||
9489ff6965 | |||
1dfd7e1af1 | |||
4a6518eeba | |||
a4d2918383 | |||
bdea826b7c |
145
api.lua
145
api.lua
@ -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
16
api.txt
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user