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

177
api.lua
View File

@ -19,7 +19,7 @@ end
mobs = {
mod = "redo",
version = "20241130",
version = "20241201",
spawning_mobs = {},
translate = S,
node_snow = has(minetest.registered_aliases["mapgen_snow"])
@ -263,27 +263,26 @@ end
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 prop = self.object:get_properties()
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
if object:is_player() then
pos2 = object:get_pos()
vec = {x = pos.x - pos2.x, z = pos.z - pos2.z}
force = width - vector.distance(
{x = pos.x, y = 0, z = pos.z}, {x = pos2.x, y = 0, z = pos2.z})
local pos2 = object:get_pos()
local vx, vz = pos.x - pos2.x, pos.z - pos2.z
local force = width - (vx * vx + vz * vz) ^ 0.5
x = x + (vec.x * force)
z = z + (vec.z * force)
if force > 0 then
force = force * 2 ; x = x + vx * force ; z = z + vz * force
end
end
end
return({x, z})
return x, z
end
-- 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
-- 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)
@ -634,9 +633,9 @@ function mob_class:update_tag(newname)
local text = ""
if self.horny == true then
if self.horny then
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)
elseif self._tame_countdown then
text = "\nTaming: " .. self._tame_countdown
@ -888,28 +887,23 @@ end
-- Returns true if node can deal damage to self
local function is_node_dangerous(mob_object, 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 function is_node_dangerous(self, 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
local damage = def.damage_per_second
for n = 1, #mob_object.immune_to do
if mob_object.immune_to[n][1] == nodename then
damage = mob_object.immune_to[n][2] or 0 ; break
if self.immune_to[n][1] == nodename then
damage = self.immune_to[n][2] or 0 ; break
end
end
@ -1080,14 +1074,14 @@ function mob_class:do_env_damage()
--- suffocation inside solid node
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.node_box == nil or nodef.node_box.type == "regular")
and (nodef.groups.disable_suffocation ~= 1) then
local damage
if type(self.suffocation) == "boolean" and self.suffocation == true then
if type(self.suffocation) == "boolean" and self.suffocation then
damage = 2
else
damage = self.suffocation
@ -1123,10 +1117,7 @@ function mob_class:do_jump()
local blocked = minetest.registered_nodes[self.looking_above].walkable
-- if mob can leap then remove blockages and let them try
if self.can_leap == true then
blocked = false
self.facing_fence = false
end
if self.can_leap then blocked = false ; self.facing_fence = false end
-- jump if possible
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()
-- child takes a long time before growing into adult
if self.child == true then
if self.child then
self.hornytimer = self.hornytimer + 1
@ -1274,7 +1265,7 @@ function mob_class:breed()
-- 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 < HORNY_TIME + HORNY_AGAIN_TIME then
if self.horny and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then
self.hornytimer = self.hornytimer + 1
@ -1287,7 +1278,7 @@ function mob_class:breed()
end
-- 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 prop = self.object:get_properties().collisionbox
@ -1323,8 +1314,8 @@ function mob_class:breed()
end
-- 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 <= HORNY_TIME then
if ent and ent.object ~= self.object and canmate
and ent.horny and ent.hornytimer <= HORNY_TIME then
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
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
end
@ -1450,7 +1441,7 @@ end
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
end
@ -1514,22 +1505,21 @@ function mob_class:smart_mobs(s, p, dist, dtime)
-- im stuck, search for path
if not has_lineofsight then
if los_switcher == true then
if los_switcher then
use_pathfind = true
los_switcher = false
end -- cannot see target!
else
if los_switcher == false then
if not los_switcher then
los_switcher = true
use_pathfind = false
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
end
if has_lineofsight then self.path.following = false end
end, self)
end -- can see target!
end
@ -1541,10 +1531,9 @@ function mob_class:smart_mobs(s, p, dist, dtime)
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
end
if has_lineofsight then self.path.following = false end
end, self)
end
@ -1555,16 +1544,15 @@ function mob_class:smart_mobs(s, p, dist, dtime)
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
end
if has_lineofsight then self.path.following = false end
end, self)
end
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
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)
-- determine node above ground (adjust height for player models)
if not ssight then
s.y = sground.y + 1
end
if not ssight then s.y = sground.y + 1 end
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
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_player = player
end
@ -1897,7 +1883,7 @@ function mob_class:do_runaway_from()
dist = get_distance(p, s)
-- 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_player = player
end
@ -2065,39 +2051,26 @@ function mob_class:do_states(dtime)
local yaw = self.object:get_yaw() ; if not yaw then return end
-- 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 grps = {}
if self.water_damage > 0 then table.insert(grps, "group:water") end
if self.fire_damage > 0 then table.insert(grps, "group:fire") end
if self.lava_damage > 0 then table.insert(grps, "group:lava") end
local lp = minetest.find_nodes_in_area_under_air(
{x = s.x - 7, y = s.y - 1.0, z = s.z - 7},
{x = s.x + 7, y = s.y + 1.0, z = s.z + 7},
{"group:cracky", "group:crumbly", "group:choppy", "group:solid"})
local lp = minetest.find_node_near(s, 1, grps)
-- did we find land ? if so face random block to climb onto
if #lp > 0 then
if lp then
yaw = self:yaw_to_pos( lp[random(#lp)] )
self.pause_timer = 3
self.following = nil
self:set_velocity(self.run_velocity)
self:set_animation("walk")
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"})
-- did we find land ? if so face random block to climb onto
if lp and #lp > 0 then
yaw = self:yaw_to_pos( lp[random(#lp)] )
end
self.pause_timer = 3
self.following = nil
self:set_velocity(self.run_velocity)
self:set_animation("walk")
return
end
return
end
end
@ -2156,8 +2129,7 @@ function mob_class:do_states(dtime)
end
-- stand for great fall in front
if self.facing_fence == true or self.at_cliff
or random(100) <= self.stand_chance then
if self.facing_fence or self.at_cliff or random(100) <= self.stand_chance then
-- don't stand if mob flies and keep_flying set
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
-- no custom attack or custom attack returns true to continue
if not self.custom_attack
or self:custom_attack(self, p) == true then
if not self.custom_attack or self:custom_attack(self, p) then
self:set_animation("punch")
@ -2453,7 +2424,7 @@ function mob_class:do_states(dtime)
p2.y = p2.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
self:mob_sound(self.sounds.attack)
@ -2846,7 +2817,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
end
-- 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()
@ -2861,7 +2832,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- attack puncher and call other mobs for help
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_invisible(self, hitter_name)
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
-- 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 (ent.name == self.name or ent.name == self.group_helper) then
ent:do_attack(hitter)
@ -3051,13 +3022,13 @@ function mob_class:mob_activate(staticdata, def, dtime)
local selbox = self.base_selbox
-- 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
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
if self.child == true then
if self.child then
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}
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
if minetest.registered_nodes[node_ok(pos2).name].walkable then
return nil
end
end
@ -3768,7 +3739,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end
-- 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
end
@ -3803,7 +3774,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
return
end
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)
return
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}
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)
return
end
@ -3894,7 +3865,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end
-- are we registering an abm or lbm?
if map_load == true then
if map_load then
minetest.register_lbm({
name = name .. "_spawning",
@ -4062,7 +4033,7 @@ function mobs:register_arrow(name, def)
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)
@ -4096,7 +4067,7 @@ function mobs:register_arrow(name, def)
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
pos.y = pos.y + 1
@ -4171,7 +4142,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
local grp = {spawn_egg = 1}
-- 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
@ -4518,7 +4489,7 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
self.object:set_hp(self.health)
-- make children grow quicker
if self.child == true then
if self.child then
-- deduct 10% of the time to adulthood
self.hornytimer = floor(self.hornytimer + (

View File

@ -22,35 +22,17 @@ local abs, cos, floor, sin, sqrt, pi =
-- 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)
if not entity.standing_on then return "other" end
if entity.standing_on == "air" then return "air" end
if minetest.get_item_group(entity.standing_on, "lava") ~= 0 then
return "lava"
end
local def = minetest.registered_nodes[entity.standing_on]
if minetest.get_item_group(entity.standing_on, "liquid") ~= 0 then
return "liquid"
end
if minetest.registered_nodes[entity.standing_on].walkable == true then
return "walkable"
end
if def.groups.lava then return "lava" end
if def.groups.liquid then return "liquid" end
if def.groups.walkable then return "walkable" end
return "other"
end
@ -236,6 +218,11 @@ function mobs.detach(player)
end)
end
-- vars
local GRAVITY = -9.8
local damage_counter = 0
-- ride mob like car or horse
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
local acce_y = 0
local acce_y = GRAVITY
local velo = entity.object:get_velocity() ; if not velo then return end
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
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 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
local ni = node_is(entity)
local v = entity.v
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