1
0
mirror of https://codeberg.org/tenplus1/mobs_redo.git synced 2025-01-23 16:00:16 +01:00

tweak/tidy, check env damage when riding mob

This commit is contained in:
tenplus1 2024-12-01 12:18:44 +00:00
parent cc60499637
commit 03ce8ada6b
2 changed files with 114 additions and 128 deletions

155
api.lua
View File

@ -19,7 +19,7 @@ end
mobs = { mobs = {
mod = "redo", mod = "redo",
version = "20241130", version = "20241201",
spawning_mobs = {}, spawning_mobs = {},
translate = S, translate = S,
node_snow = has(minetest.registered_aliases["mapgen_snow"]) node_snow = has(minetest.registered_aliases["mapgen_snow"])
@ -263,27 +263,26 @@ end
function mob_class:collision() function mob_class:collision()
local pos = self.object:get_pos() ; if not pos then return {0, 0} end local pos = self.object:get_pos() ; if not pos then return 0, 0 end
local x, z = 0, 0 local x, z = 0, 0
local prop = self.object:get_properties() local prop = self.object:get_properties()
local width = -prop.collisionbox[1] + prop.collisionbox[4] + 0.5 local width = -prop.collisionbox[1] + prop.collisionbox[4] + 0.5
local pos2, vec, force
for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
if object:is_player() then if object:is_player() then
pos2 = object:get_pos() local pos2 = object:get_pos()
vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} local vx, vz = pos.x - pos2.x, pos.z - pos2.z
force = width - vector.distance( local force = width - (vx * vx + vz * vz) ^ 0.5
{x = pos.x, y = 0, z = pos.z}, {x = pos2.x, y = 0, z = pos2.z})
x = x + (vec.x * force) if force > 0 then
z = z + (vec.z * force) force = force * 2 ; x = x + vx * force ; z = z + vz * force
end
end end
end end
return({x, z}) return x, z
end end
-- check if string exists in another string or table -- check if string exists in another string or table
@ -325,7 +324,7 @@ function mob_class:set_velocity(v)
local c_x, c_y = 0, 0 local c_x, c_y = 0, 0
-- can mob be pushed, if so calculate direction -- can mob be pushed, if so calculate direction
if self.pushable then c_x, c_y = unpack(self:collision()) end if self.pushable then c_x, c_y = self:collision() end
local yaw = (self.object:get_yaw() or 0) + (self.rotate or 0) local yaw = (self.object:get_yaw() or 0) + (self.rotate or 0)
@ -634,9 +633,9 @@ function mob_class:update_tag(newname)
local text = "" local text = ""
if self.horny == true then if self.horny then
text = "\nLoving: " .. (self.hornytimer - (HORNY_TIME + HORNY_AGAIN_TIME)) text = "\nLoving: " .. (self.hornytimer - (HORNY_TIME + HORNY_AGAIN_TIME))
elseif self.child == true then elseif self.child then
text = "\nGrowing: " .. (self.hornytimer - CHILD_GROW_TIME) text = "\nGrowing: " .. (self.hornytimer - CHILD_GROW_TIME)
elseif self._tame_countdown then elseif self._tame_countdown then
text = "\nTaming: " .. self._tame_countdown text = "\nTaming: " .. self._tame_countdown
@ -888,28 +887,23 @@ end
-- Returns true if node can deal damage to self -- Returns true if node can deal damage to self
local function is_node_dangerous(mob_object, nodename) local function is_node_dangerous(self, nodename)
if mob_object.water_damage > 0
and minetest.get_item_group(nodename, "water") ~= 0 then return true end
if mob_object.lava_damage > 0
and minetest.get_item_group(nodename, "lava") ~= 0 then return true end
if mob_object.fire_damage > 0
and minetest.get_item_group(nodename, "fire") ~= 0 then return true end
local def = minetest.registered_nodes[nodename] local def = minetest.registered_nodes[nodename]
if mob_object.node_damage and def.damage_per_second > 0 then if (self.water_damage and def.groups.water)
or (self.lava_damage and def.groups.lava)
or (self.fire_damage and def.groups.fire) then return true end
if self.node_damage and def.damage_per_second > 0 then
-- check for node immunity or special damage -- check for node immunity or special damage
local damage = def.damage_per_second local damage = def.damage_per_second
for n = 1, #mob_object.immune_to do for n = 1, #mob_object.immune_to do
if mob_object.immune_to[n][1] == nodename then if self.immune_to[n][1] == nodename then
damage = mob_object.immune_to[n][2] or 0 ; break damage = self.immune_to[n][2] or 0 ; break
end end
end end
@ -1080,14 +1074,14 @@ function mob_class:do_env_damage()
--- suffocation inside solid node --- suffocation inside solid node
if (self.suffocation and self.suffocation ~= 0) if (self.suffocation and self.suffocation ~= 0)
and (nodef.walkable == nil or nodef.walkable == true) and (nodef.walkable == nil or nodef.walkable)
and (nodef.collision_box == nil or nodef.collision_box.type == "regular") and (nodef.collision_box == nil or nodef.collision_box.type == "regular")
and (nodef.node_box == nil or nodef.node_box.type == "regular") and (nodef.node_box == nil or nodef.node_box.type == "regular")
and (nodef.groups.disable_suffocation ~= 1) then and (nodef.groups.disable_suffocation ~= 1) then
local damage local damage
if type(self.suffocation) == "boolean" and self.suffocation == true then if type(self.suffocation) == "boolean" and self.suffocation then
damage = 2 damage = 2
else else
damage = self.suffocation damage = self.suffocation
@ -1123,10 +1117,7 @@ function mob_class:do_jump()
local blocked = minetest.registered_nodes[self.looking_above].walkable local blocked = minetest.registered_nodes[self.looking_above].walkable
-- if mob can leap then remove blockages and let them try -- if mob can leap then remove blockages and let them try
if self.can_leap == true then if self.can_leap then blocked = false ; self.facing_fence = false end
blocked = false
self.facing_fence = false
end
-- jump if possible -- jump if possible
if self.jump and self.jump_height > 0 and not self.fly and not self.child if self.jump and self.jump_height > 0 and not self.fly and not self.child
@ -1231,7 +1222,7 @@ end
function mob_class:breed() function mob_class:breed()
-- child takes a long time before growing into adult -- child takes a long time before growing into adult
if self.child == true then if self.child then
self.hornytimer = self.hornytimer + 1 self.hornytimer = self.hornytimer + 1
@ -1274,7 +1265,7 @@ function mob_class:breed()
-- horny animal can mate for HORNY_TIME seconds, -- horny animal can mate for HORNY_TIME seconds,
-- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds -- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds
if self.horny == true and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then if self.horny and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then
self.hornytimer = self.hornytimer + 1 self.hornytimer = self.hornytimer + 1
@ -1287,7 +1278,7 @@ function mob_class:breed()
end end
-- find another same animal who is also horny and mate if nearby -- find another same animal who is also horny and mate if nearby
if self.horny == true and self.hornytimer <= HORNY_TIME then if self.horny and self.hornytimer <= HORNY_TIME then
local pos = self.object:get_pos() local pos = self.object:get_pos()
local prop = self.object:get_properties().collisionbox local prop = self.object:get_properties().collisionbox
@ -1323,8 +1314,8 @@ function mob_class:breed()
end end
-- found another similar horny animal that isn't self? -- found another similar horny animal that isn't self?
if ent and ent.object ~= self.object and canmate == true if ent and ent.object ~= self.object and canmate
and ent.horny == true and ent.hornytimer <= HORNY_TIME then and ent.horny and ent.hornytimer <= HORNY_TIME then
local pos2 = ent.object:get_pos() local pos2 = ent.object:get_pos()
@ -1394,7 +1385,7 @@ function mob_class:replace(pos)
local vel = self.object:get_velocity() ; if not vel then return end local vel = self.object:get_velocity() ; if not vel then return end
if not mobs_griefing or not self.replace_rate or not self.replace_what if not mobs_griefing or not self.replace_rate or not self.replace_what
or self.child == true or vel.y ~= 0 or random(self.replace_rate) > 1 then or self.child or vel.y ~= 0 or random(self.replace_rate) > 1 then
return return
end end
@ -1450,7 +1441,7 @@ end
function mob_class:day_docile() function mob_class:day_docile()
if self.docile_by_day == true if self.docile_by_day
and self.time_of_day > 0.2 and self.time_of_day < 0.8 then return true end and self.time_of_day > 0.2 and self.time_of_day < 0.8 then return true end
end end
@ -1514,22 +1505,21 @@ function mob_class:smart_mobs(s, p, dist, dtime)
-- im stuck, search for path -- im stuck, search for path
if not has_lineofsight then if not has_lineofsight then
if los_switcher == true then if los_switcher then
use_pathfind = true use_pathfind = true
los_switcher = false los_switcher = false
end -- cannot see target! end -- cannot see target!
else else
if los_switcher == false then if not los_switcher then
los_switcher = true los_switcher = true
use_pathfind = false use_pathfind = false
minetest.after(1, function(self) minetest.after(1, function(self)
if self.object:get_luaentity() then if not self.object:get_luaentity() then return end
if has_lineofsight then self.path.following = false end if has_lineofsight then self.path.following = false end
end
end, self) end, self)
end -- can see target! end -- can see target!
end end
@ -1541,10 +1531,9 @@ function mob_class:smart_mobs(s, p, dist, dtime)
minetest.after(1, function(self) minetest.after(1, function(self)
if self.object:get_luaentity() then if not self.object:get_luaentity() then return end
if has_lineofsight then self.path.following = false end if has_lineofsight then self.path.following = false end
end
end, self) end, self)
end end
@ -1555,16 +1544,15 @@ function mob_class:smart_mobs(s, p, dist, dtime)
minetest.after(1, function(self) minetest.after(1, function(self)
if self.object:get_luaentity() then if not self.object:get_luaentity() then return end
if has_lineofsight then self.path.following = false end if has_lineofsight then self.path.following = false end
end
end, self) end, self)
end end
local prop = self.object:get_properties() local prop = self.object:get_properties()
if abs(vsubtract(s, target_pos).y) > prop.stepheight then if abs(s.y - target_pos.y) > prop.stepheight then
if height_switcher then use_pathfind = true ; height_switcher = false end if height_switcher then use_pathfind = true ; height_switcher = false end
else else
@ -1583,9 +1571,7 @@ function mob_class:smart_mobs(s, p, dist, dtime)
{x = s.x, y = s.y - 4, z = s.z}, 1) {x = s.x, y = s.y - 4, z = s.z}, 1)
-- determine node above ground (adjust height for player models) -- determine node above ground (adjust height for player models)
if not ssight then if not ssight then s.y = sground.y + 1 end
s.y = sground.y + 1
end
local p1 = self.attack and self.attack:get_pos() local p1 = self.attack and self.attack:get_pos()
@ -1837,7 +1823,7 @@ function mob_class:general_attack()
-- choose closest player to attack that isnt self -- choose closest player to attack that isnt self
if dist ~= 0 and dist < min_dist if dist ~= 0 and dist < min_dist
and self:line_of_sight(sp, p) == true and not is_peaceful_player(player) then and self:line_of_sight(sp, p) and not is_peaceful_player(player) then
min_dist = dist min_dist = dist
min_player = player min_player = player
end end
@ -1897,7 +1883,7 @@ function mob_class:do_runaway_from()
dist = get_distance(p, s) dist = get_distance(p, s)
-- choose closest player/mob to runaway from -- choose closest player/mob to runaway from
if dist < min_dist and self:line_of_sight(sp, p) == true then if dist < min_dist and self:line_of_sight(sp, p) then
min_dist = dist min_dist = dist
min_player = player min_player = player
end end
@ -2065,41 +2051,28 @@ function mob_class:do_states(dtime)
local yaw = self.object:get_yaw() ; if not yaw then return end local yaw = self.object:get_yaw() ; if not yaw then return end
-- are we standing in something that hurts ? Try to get out -- are we standing in something that hurts ? Try to get out
if is_node_dangerous(self, self.standing_in) then if is_node_dangerous(self, self.standing_in) then -- and self.pause_timer <= 0 then
local s = self.object:get_pos() local s = self.object:get_pos()
local grps = {}
if self.water_damage > 0 then table.insert(grps, "group:water") end local lp = minetest.find_nodes_in_area_under_air(
if self.fire_damage > 0 then table.insert(grps, "group:fire") end {x = s.x - 7, y = s.y - 1.0, z = s.z - 7},
if self.lava_damage > 0 then table.insert(grps, "group:lava") end {x = s.x + 7, y = s.y + 1.0, z = s.z + 7},
local lp = minetest.find_node_near(s, 1, grps)
if lp then
if self.pause_timer <= 0 then
lp = minetest.find_nodes_in_area_under_air(
{x = s.x - 5, y = s.y , z = s.z - 5},
{x = s.x + 5, y = s.y + 2, z = s.z + 5},
{"group:cracky", "group:crumbly", "group:choppy", "group:solid"}) {"group:cracky", "group:crumbly", "group:choppy", "group:solid"})
-- did we find land ? if so face random block to climb onto -- did we find land ? if so face random block to climb onto
if lp and #lp > 0 then if #lp > 0 then
yaw = self:yaw_to_pos( lp[random(#lp)] ) yaw = self:yaw_to_pos( lp[random(#lp)] )
end
self.pause_timer = 3 self.pause_timer = 3
self.following = nil self.following = nil
self:set_velocity(self.run_velocity) self:set_velocity(self.run_velocity)
self:set_animation("walk") self:set_animation("walk")
return return
end end
end end
end
if self.state == "stand" then if self.state == "stand" then
@ -2156,8 +2129,7 @@ function mob_class:do_states(dtime)
end end
-- stand for great fall in front -- stand for great fall in front
if self.facing_fence == true or self.at_cliff if self.facing_fence or self.at_cliff or random(100) <= self.stand_chance then
or random(100) <= self.stand_chance then
-- don't stand if mob flies and keep_flying set -- don't stand if mob flies and keep_flying set
if (self.fly and not self.keep_flying) or not self.fly then if (self.fly and not self.keep_flying) or not self.fly then
@ -2443,8 +2415,7 @@ function mob_class:do_states(dtime)
self.timer = 0 self.timer = 0
-- no custom attack or custom attack returns true to continue -- no custom attack or custom attack returns true to continue
if not self.custom_attack if not self.custom_attack or self:custom_attack(self, p) then
or self:custom_attack(self, p) == true then
self:set_animation("punch") self:set_animation("punch")
@ -2453,7 +2424,7 @@ function mob_class:do_states(dtime)
p2.y = p2.y + .5 p2.y = p2.y + .5
s2.y = s2.y + .5 s2.y = s2.y + .5
if self:line_of_sight(p2, s2) == true then if self:line_of_sight(p2, s2) then
-- play attack sound -- play attack sound
self:mob_sound(self.sounds.attack) self:mob_sound(self.sounds.attack)
@ -2846,7 +2817,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
end end
-- if skittish then run away -- if skittish then run away
if self.runaway == true and self.order ~= "stand" then if self.runaway and self.order ~= "stand" then
local lp = hitter:get_pos() local lp = hitter:get_pos()
@ -2861,7 +2832,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- attack puncher and call other mobs for help -- attack puncher and call other mobs for help
if self.passive == false and self.state ~= "flop" if self.passive == false and self.state ~= "flop"
and self.child == false and self.attack_players == true and not self.child and self.attack_players
and not (is_player(hitter) and hitter_name == self.owner) and not (is_player(hitter) and hitter_name == self.owner)
and not is_invisible(self, hitter_name) and not is_invisible(self, hitter_name)
and self.object ~= hitter then and self.object ~= hitter then
@ -2881,7 +2852,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
if ent and ent._cmi_is_mob then if ent and ent._cmi_is_mob then
-- only alert members of same mob and assigned helper -- only alert members of same mob and assigned helper
if ent.group_attack == true and ent.state ~= "attack" if ent.group_attack and ent.state ~= "attack"
and not (is_player(hitter) and ent.owner == hitter_name) and not (is_player(hitter) and ent.owner == hitter_name)
and (ent.name == self.name or ent.name == self.group_helper) then and (ent.name == self.name or ent.name == self.group_helper) then
ent:do_attack(hitter) ent:do_attack(hitter)
@ -3051,13 +3022,13 @@ function mob_class:mob_activate(staticdata, def, dtime)
local selbox = self.base_selbox local selbox = self.base_selbox
-- is there a specific texture if gotten -- is there a specific texture if gotten
if self.gotten == true and def.gotten_texture then textures = def.gotten_texture end if self.gotten and def.gotten_texture then textures = def.gotten_texture end
-- specific mesh if gotten -- specific mesh if gotten
if self.gotten == true and def.gotten_mesh then mesh = def.gotten_mesh end if self.gotten and def.gotten_mesh then mesh = def.gotten_mesh end
-- set child objects to half size -- set child objects to half size
if self.child == true then if self.child then
vis_size = {x = self.base_size.x * .5, y = self.base_size.y * .5} vis_size = {x = self.base_size.x * .5, y = self.base_size.y * .5}
@ -3573,7 +3544,7 @@ local function can_spawn(pos, name)
pos2 = {x = pos.x + x, y = pos.y + y, z = pos.z + z} pos2 = {x = pos.x + x, y = pos.y + y, z = pos.z + z}
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then if minetest.registered_nodes[node_ok(pos2).name].walkable then
return nil return nil
end end
end end
@ -3768,7 +3739,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
-- additional custom checks for spawning mob -- additional custom checks for spawning mob
if mobs:spawn_abm_check(pos, node, name) == true then if mobs:spawn_abm_check(pos, node, name) then
return return
end end
@ -3803,7 +3774,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
return return
end end
else else
if day_toggle == true then -- night time but mob wants day if day_toggle then -- night time but mob wants day
--print("--- mob needs day", name) --print("--- mob needs day", name)
return return
end end
@ -3860,7 +3831,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
local pos2 = {x = pos.x, y = pos.y + n, z = pos.z} local pos2 = {x = pos.x, y = pos.y + n, z = pos.z}
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then if minetest.registered_nodes[node_ok(pos2).name].walkable then
--print ("--- inside block", name, node_ok(pos2).name) --print ("--- inside block", name, node_ok(pos2).name)
return return
end end
@ -3894,7 +3865,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
-- are we registering an abm or lbm? -- are we registering an abm or lbm?
if map_load == true then if map_load then
minetest.register_lbm({ minetest.register_lbm({
name = name .. "_spawning", name = name .. "_spawning",
@ -4062,7 +4033,7 @@ function mobs:register_arrow(name, def)
local entity = thing.ref:get_luaentity() local entity = thing.ref:get_luaentity()
if entity and self.hit_mob and entity._cmi_is_mob == true then if entity and self.hit_mob and entity._cmi_is_mob then
self:hit_mob(thing.ref) self:hit_mob(thing.ref)
@ -4096,7 +4067,7 @@ function mobs:register_arrow(name, def)
self:hit_node(pos, node) self:hit_node(pos, node)
if (type(self.drop) == "boolean" and self.drop == true) if (type(self.drop) == "boolean" and self.drop)
or (type(self.drop) == "number" and random(self.drop) == 1) then or (type(self.drop) == "number" and random(self.drop) == 1) then
pos.y = pos.y + 1 pos.y = pos.y + 1
@ -4171,7 +4142,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
local grp = {spawn_egg = 1} local grp = {spawn_egg = 1}
-- do NOT add this egg to creative inventory (e.g. dungeon master) -- do NOT add this egg to creative inventory (e.g. dungeon master)
if no_creative == true then grp.not_in_creative_inventory = 1 end if no_creative then grp.not_in_creative_inventory = 1 end
local invimg = background local invimg = background
@ -4518,7 +4489,7 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
self.object:set_hp(self.health) self.object:set_hp(self.health)
-- make children grow quicker -- make children grow quicker
if self.child == true then if self.child then
-- deduct 10% of the time to adulthood -- deduct 10% of the time to adulthood
self.hornytimer = floor(self.hornytimer + ( self.hornytimer = floor(self.hornytimer + (

View File

@ -22,35 +22,17 @@ local abs, cos, floor, sin, sqrt, pi =
-- helper functions -- helper functions
local function node_ok(pos, fallback)
fallback = fallback or mobs.fallback_node
local node = minetest.get_node_or_nil(pos)
if node and minetest.registered_nodes[node.name] then return node end
return {name = fallback}
end
local function node_is(entity) local function node_is(entity)
if not entity.standing_on then return "other" end if not entity.standing_on then return "other" end
if entity.standing_on == "air" then return "air" end if entity.standing_on == "air" then return "air" end
if minetest.get_item_group(entity.standing_on, "lava") ~= 0 then local def = minetest.registered_nodes[entity.standing_on]
return "lava"
end
if minetest.get_item_group(entity.standing_on, "liquid") ~= 0 then if def.groups.lava then return "lava" end
return "liquid" if def.groups.liquid then return "liquid" end
end if def.groups.walkable then return "walkable" end
if minetest.registered_nodes[entity.standing_on].walkable == true then
return "walkable"
end
return "other" return "other"
end end
@ -236,6 +218,11 @@ function mobs.detach(player)
end) end)
end end
-- vars
local GRAVITY = -9.8
local damage_counter = 0
-- ride mob like car or horse -- ride mob like car or horse
function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
@ -245,7 +232,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
if entity.player_rotation.y == 90 then rot_view = pi / 2 end if entity.player_rotation.y == 90 then rot_view = pi / 2 end
local acce_y = 0 local acce_y = GRAVITY
local velo = entity.object:get_velocity() ; if not velo then return end local velo = entity.object:get_velocity() ; if not velo then return end
entity.v = get_v(velo) * get_sign(entity.v) entity.v = get_v(velo) * get_sign(entity.v)
@ -321,6 +308,35 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
end end
end end
local ni = node_is(entity)
-- env damage
if ni == "liquid" or ni == "lava" then
damage_counter = damage_counter + dtime
if damage_counter > 1 then
local damage = 0
if entity.lava_damage > 0 and ni == "lava" then
damage = entity.lava_damage
elseif entity.water_damage > 0 and ni == "liquid" then
damage = entity.water_damage
end
if damage >= 1 then
entity.object:punch(entity.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = damage}
}, nil)
end
damage_counter = 0
end
end
-- if not moving then set animation and return -- if not moving then set animation and return
if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
@ -361,12 +377,11 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
p.y = p.y - 0.5 p.y = p.y - 0.5
local ni = node_is(entity)
local v = entity.v local v = entity.v
if ni == "air" then if ni == "air" then
if can_fly == true then new_acce.y = 0 end if can_fly then new_acce.y = 0 ; acce_y = 0 end
elseif ni == "liquid" or ni == "lava" then elseif ni == "liquid" or ni == "lava" then