mobs: update and cleanup
This commit is contained in:
parent
ff9169e053
commit
a24c7757a0
@ -12,6 +12,6 @@ local name = {
|
||||
"kitten", "pig", "sheep"
|
||||
}
|
||||
|
||||
for _, name in pairs(name) do
|
||||
dofile(path .. "/" .. name .. ".lua")
|
||||
for _, mob in pairs(name) do
|
||||
dofile(path .. "/" .. mob .. ".lua")
|
||||
end
|
||||
|
@ -58,7 +58,7 @@ mobs:register_mob("mobs_npc:npc_man", {
|
||||
punch_start = 189, punch_end = 198
|
||||
},
|
||||
|
||||
do_punch = function(self, hitter)
|
||||
do_punch = function(_, hitter)
|
||||
if not hitter or not hitter:is_player() then
|
||||
return true
|
||||
end
|
||||
@ -151,7 +151,7 @@ mobs:register_mob("mobs_npc:npc_woman", {
|
||||
punch_start = 189, punch_end = 198
|
||||
},
|
||||
|
||||
do_punch = function(self, hitter)
|
||||
do_punch = function(_, hitter)
|
||||
if not hitter or not hitter:is_player() then
|
||||
return true
|
||||
end
|
||||
|
@ -35,11 +35,11 @@ mobs:register_mob("mobs_npc:trader", {
|
||||
},
|
||||
|
||||
on_punch = function(self, clicker)
|
||||
mobs_trader(self, clicker, mobs.human)
|
||||
mobs.trader_show_goods(self, clicker, mobs.human)
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
mobs_trader(self, clicker, mobs.human)
|
||||
mobs.trader_show_goods(self, clicker, mobs.human)
|
||||
end,
|
||||
|
||||
on_spawn = function(self)
|
||||
@ -133,7 +133,7 @@ mobs.human = {
|
||||
|
||||
local random = math.random
|
||||
|
||||
function mobs.add_goods(self, race)
|
||||
function mobs.trader_add_goods(self, race)
|
||||
local trade_index = 1
|
||||
local trades_already_added = {}
|
||||
local trader_pool_size = 6
|
||||
@ -177,7 +177,7 @@ function mobs.add_goods(self, race)
|
||||
self.version = 2
|
||||
end
|
||||
|
||||
function mobs_trader(self, clicker, race)
|
||||
function mobs.trader_show_goods(self, clicker, race)
|
||||
if not self.id then
|
||||
self.id = (random(1000) * random(10000))
|
||||
.. self.name .. (random(1000) ^ 2)
|
||||
@ -195,7 +195,7 @@ function mobs_trader(self, clicker, race)
|
||||
local version = self.version
|
||||
|
||||
if self.trades == nil or not version or version < 2 then
|
||||
mobs.add_goods(self, race)
|
||||
mobs.trader_add_goods(self, race)
|
||||
end
|
||||
|
||||
local player = clicker:get_player_name()
|
||||
|
@ -1,7 +1,7 @@
|
||||
-- Mobs API
|
||||
mobs = {
|
||||
mod = "redo",
|
||||
version = "20200312",
|
||||
version = "20200427",
|
||||
invis = minetest.global_exists("invisibility") and invisibility or {}
|
||||
}
|
||||
|
||||
@ -226,6 +226,8 @@ end
|
||||
-- calculate mob velocity
|
||||
function mob_class:get_velocity()
|
||||
local v = self.object:get_velocity()
|
||||
if not v then return 0 end
|
||||
|
||||
return (v.x * v.x + v.z * v.z) ^ 0.5
|
||||
end
|
||||
|
||||
@ -416,10 +418,10 @@ local ray_line_of_sight = function(self, pos1, pos2)
|
||||
local thing = ray:next()
|
||||
|
||||
while thing do
|
||||
if thing.type == "object"
|
||||
and thing.ref ~= self.object
|
||||
and not thing.ref:is_player() then return false
|
||||
end
|
||||
-- if thing.type == "object"
|
||||
-- and thing.ref ~= self.object
|
||||
-- and not thing.ref:is_player() then return false
|
||||
-- end
|
||||
|
||||
if thing.type == "node" then
|
||||
local name = minetest.get_node(thing.under).name
|
||||
@ -545,14 +547,14 @@ end
|
||||
|
||||
-- custom particle effects
|
||||
local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow)
|
||||
if not minetest.is_valid_pos(pos) then return end
|
||||
|
||||
radius = radius or 2
|
||||
min_size = min_size or 0.5
|
||||
min_size = min_size or 1
|
||||
max_size = max_size or 1
|
||||
gravity = gravity or -9.81
|
||||
glow = glow or 0
|
||||
|
||||
if not minetest.is_valid_pos(pos) then return end
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = amount,
|
||||
time = 0.25,
|
||||
@ -562,7 +564,7 @@ local effect = function(pos, amount, texture, min_size, max_size, radius, gravit
|
||||
maxvel = {x = radius, y = radius, z = radius},
|
||||
minacc = {x = 0, y = gravity, z = 0},
|
||||
maxacc = {x = 0, y = gravity, z = 0},
|
||||
minexptime = 0.1,
|
||||
minexptime = 0.25,
|
||||
maxexptime = 1,
|
||||
minsize = min_size,
|
||||
maxsize = max_size,
|
||||
@ -732,6 +734,39 @@ function mob_class:check_for_death(cmi_cause)
|
||||
end
|
||||
|
||||
|
||||
-- get node but use fallback for nil or unknown
|
||||
local node_ok = function(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 minetest.registered_nodes[fallback]
|
||||
end
|
||||
|
||||
|
||||
-- Returns true is node can deal damage to self
|
||||
local is_node_dangerous = function(self, nodename)
|
||||
if self.water_damage > 0
|
||||
and minetest.get_item_group(nodename, "water") ~= 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
if self.lava_damage > 0
|
||||
and minetest.get_item_group(nodename, "igniter") ~= 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
if minetest.registered_nodes[nodename].damage_per_second > 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- is mob facing a cliff
|
||||
function mob_class:is_at_cliff()
|
||||
if self.fear_height == 0 then -- 0 for no falling protection!
|
||||
@ -749,28 +784,29 @@ function mob_class:is_at_cliff()
|
||||
local pos = self.object:get_pos()
|
||||
local ypos = pos.y + self.collisionbox[2] -- just above floor
|
||||
|
||||
if minetest.line_of_sight(
|
||||
local free_fall, blocker = minetest.line_of_sight(
|
||||
{x = pos.x + dir_x, y = ypos, z = pos.z + dir_z},
|
||||
{x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}, 1) then
|
||||
{x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z})
|
||||
|
||||
-- check for straight drop, drop onto danger or walkable node
|
||||
if free_fall then
|
||||
return true
|
||||
else
|
||||
local bnode = node_ok(blocker)
|
||||
|
||||
if is_node_dangerous(self, bnode.name) then
|
||||
return true
|
||||
else
|
||||
local def = minetest.registered_nodes[bnode.name]
|
||||
|
||||
return (not def and def.walkable)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- get node but use fallback for nil or unknown
|
||||
local node_ok = function(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 minetest.registered_nodes[fallback]
|
||||
end
|
||||
|
||||
|
||||
-- environmental damage (water, lava, fire, light etc.)
|
||||
function mob_class:do_env_damage()
|
||||
-- feed/tame text timer (so mob 'full' messages dont spam chat)
|
||||
@ -801,7 +837,7 @@ function mob_class:do_env_damage()
|
||||
if light >= self.light_damage_min
|
||||
and light <= self.light_damage_max then
|
||||
self.health = self.health - self.light_damage
|
||||
effect(pos, 5, "heart.png")
|
||||
effect(pos, 3, "fire_basic_flame.png", 4, 4, 2, nil, 5)
|
||||
if show_health then
|
||||
self.nametag = S("Health:") .. " " .. self.health .. " / " .. self.hp_max
|
||||
self:update_tag()
|
||||
@ -891,6 +927,9 @@ function mob_class:do_jump()
|
||||
local pos = self.object:get_pos()
|
||||
local yaw = self.object:get_yaw()
|
||||
|
||||
-- sanity check
|
||||
if not yaw then return false end
|
||||
|
||||
-- what is mob standing on?
|
||||
pos.y = pos.y + self.collisionbox[2] - 0.2
|
||||
local nod = node_ok(pos)
|
||||
@ -910,6 +949,18 @@ function mob_class:do_jump()
|
||||
z = pos.z + dir_z
|
||||
})
|
||||
|
||||
-- what is above and in front?
|
||||
local nodt = node_ok({
|
||||
x = pos.x + dir_x,
|
||||
y = pos.y + 1.5,
|
||||
z = pos.z + dir_z
|
||||
})
|
||||
|
||||
-- is there space to jump up?
|
||||
if minetest.registered_nodes[nodt.name].walkable == true then
|
||||
return false
|
||||
end
|
||||
|
||||
-- thin blocks that do not need to be jumped
|
||||
if nod.name == node_snow then
|
||||
return false
|
||||
@ -919,7 +970,9 @@ function mob_class:do_jump()
|
||||
|
||||
if self.walk_chance == 0
|
||||
or minetest.registered_items[nod.name].walkable then
|
||||
if not nod.name:find("fence") and not nod.name:find("gate") then
|
||||
if not nod.name:find("fence")
|
||||
and not nod.name:find("gate")
|
||||
and not nod.name:find("wall") then
|
||||
local v = self.object:get_velocity()
|
||||
v.y = self.jump_height
|
||||
|
||||
@ -942,6 +995,8 @@ function mob_class:do_jump()
|
||||
end
|
||||
else
|
||||
self.facing_fence = true
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- if we jumped against a block/wall 4 times then turn
|
||||
@ -1124,9 +1179,13 @@ function mob_class:breed()
|
||||
if self.child_texture then
|
||||
textures = self.child_texture[1]
|
||||
end
|
||||
|
||||
local infotext = Sl("Owned by @1", Sl(self.owner))
|
||||
|
||||
|
||||
local infotext = ""
|
||||
local owner = (self.owner ~= nil and self.owner) or ""
|
||||
if owner and owner ~= "" then
|
||||
infotext = Sl("Owned by @1", Sl(owner and owner or ""))
|
||||
end
|
||||
|
||||
-- and resize to half height
|
||||
mob:set_properties({
|
||||
textures = textures,
|
||||
@ -1485,6 +1544,7 @@ end
|
||||
function mob_class:general_attack()
|
||||
-- return if already attacking, passive or docile during day
|
||||
if self.passive
|
||||
or self.state == "runaway"
|
||||
or self.state == "attack"
|
||||
or self:day_docile() then
|
||||
return
|
||||
@ -1833,19 +1893,16 @@ function mob_class:do_states(dtime)
|
||||
-- is there something I need to avoid?
|
||||
if self.water_damage > 0
|
||||
and self.lava_damage > 0 then
|
||||
lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"})
|
||||
lp = minetest.find_node_near(s, 1, {"group:water", "group:igniter"})
|
||||
elseif self.water_damage > 0 then
|
||||
lp = minetest.find_node_near(s, 1, {"group:water"})
|
||||
elseif self.lava_damage > 0 then
|
||||
lp = minetest.find_node_near(s, 1, {"group:lava"})
|
||||
lp = minetest.find_node_near(s, 1, {"group:igniter"})
|
||||
end
|
||||
|
||||
if lp then
|
||||
-- if mob in water or lava then look for land
|
||||
if (self.lava_damage
|
||||
and minetest.registered_nodes[self.standing_in].groups.lava)
|
||||
or (self.water_damage
|
||||
and minetest.registered_nodes[self.standing_in].groups.water) then
|
||||
-- if mob in dangerous node then look for land
|
||||
if is_node_dangerous(self, self.standing_in) then
|
||||
lp = minetest.find_node_near(s, 5, {
|
||||
"group:soil", "group:stone",
|
||||
"group:sand", node_ice, node_snowblock
|
||||
@ -2248,6 +2305,9 @@ function mob_class:falling(pos)
|
||||
-- floating in water (or falling)
|
||||
local v = self.object:get_velocity()
|
||||
|
||||
-- sanity check
|
||||
if not v then return end
|
||||
|
||||
if v.y > 0 then
|
||||
-- apply gravity when moving up
|
||||
self.object:set_acceleration({
|
||||
@ -2287,7 +2347,7 @@ function mob_class:falling(pos)
|
||||
self.health = self.health - floor(d - 5)
|
||||
-- effect(pos, 5, "item_smoke.png", 1, 2, 2, nil)
|
||||
if self:check_for_death({type = "fall"}) then
|
||||
return
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
@ -2435,6 +2495,10 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir)
|
||||
-- knock back effect (only on full punch)
|
||||
if self.knock_back and tflp >= punch_interval then
|
||||
local v = self.object:get_velocity()
|
||||
|
||||
-- sanity check
|
||||
if not v then return end
|
||||
|
||||
local kb = damage or 1
|
||||
local up = 2
|
||||
|
||||
@ -2728,7 +2792,10 @@ end
|
||||
-- main mob function
|
||||
function mob_class:on_step(dtime)
|
||||
local pos = self.object:get_pos()
|
||||
local yaw = 0
|
||||
local yaw = self.object:get_yaw()
|
||||
|
||||
-- early warning check, if no yaw then no entity, skip rest of function
|
||||
if not yaw then return end
|
||||
|
||||
-- get node at foot level every quarter second
|
||||
self.node_timer = (self.node_timer or 0) + dtime
|
||||
@ -2769,14 +2836,13 @@ function mob_class:on_step(dtime)
|
||||
self:mob_expire(pos, 0.25)
|
||||
end
|
||||
|
||||
-- check if falling, flying, floating
|
||||
self:falling(pos)
|
||||
-- check if falling, flying, floating and return if player died
|
||||
if self:falling(pos) then
|
||||
return
|
||||
end
|
||||
|
||||
-- smooth rotation by ThomasMonroe314
|
||||
|
||||
if self.delay and self.delay > 0 then
|
||||
local yaw = self.object:get_yaw()
|
||||
|
||||
if self.delay == 1 then
|
||||
yaw = self.target_yaw
|
||||
else
|
||||
@ -2805,7 +2871,6 @@ function mob_class:on_step(dtime)
|
||||
self.delay = self.delay - 1
|
||||
self.object:set_yaw(yaw)
|
||||
end
|
||||
|
||||
-- end rotation
|
||||
|
||||
-- knockback timer
|
||||
@ -3327,7 +3392,7 @@ local function spawn_mob(pos, mob, data, placer)
|
||||
local pn = placer:get_player_name()
|
||||
ent.owner = pn
|
||||
ent.tamed = true
|
||||
local infotext = Sl("Owned by @1", Sl(pn))
|
||||
local infotext = Sl("Owned by @1", Sl(pn))
|
||||
ent.infotext = infotext
|
||||
obj:set_properties({
|
||||
infotext = infotext
|
||||
|
@ -104,22 +104,22 @@ minetest.register_craft({
|
||||
})
|
||||
|
||||
-- chicken egg
|
||||
local function mobs_shoot_egg(itemstack, thrower)
|
||||
local function chicken_egg_shoot(itemstack, thrower)
|
||||
local playerpos = thrower:get_pos()
|
||||
if not minetest.is_valid_pos(playerpos) then
|
||||
return
|
||||
end
|
||||
local obj = minetest.item_throw("mobs:chicken_egg", thrower, 19, -3, egg_impact)
|
||||
local obj = minetest.item_throw("mobs:chicken_egg", thrower, 19, -3, mobs_animal and mobs_animal.egg_impact)
|
||||
if obj then
|
||||
obj:set_properties({
|
||||
visual = "sprite",
|
||||
visual_size = {x = 0.5, y = 0.5},
|
||||
textures = {"mobs_chicken_egg.png"},
|
||||
textures = {"mobs_chicken_egg.png"}
|
||||
})
|
||||
minetest.sound_play("throwing_sound", {
|
||||
pos = playerpos,
|
||||
gain = 0.7,
|
||||
max_hear_distance = 10,
|
||||
max_hear_distance = 10
|
||||
})
|
||||
if not mobs.is_creative(thrower) or
|
||||
not minetest.is_singleplayer() then
|
||||
@ -133,8 +133,8 @@ minetest.register_craftitem("mobs:chicken_egg", {
|
||||
description = "Egg",
|
||||
inventory_image = "mobs_chicken_egg.png",
|
||||
visual_scale = 0.7,
|
||||
on_use = mobs_shoot_egg,
|
||||
groups = {food = 1}
|
||||
groups = {food = 1},
|
||||
on_use = chicken_egg_shoot
|
||||
})
|
||||
|
||||
minetest.register_alias("mobs:egg", "air")
|
||||
|
Loading…
x
Reference in New Issue
Block a user