Add in mob death

This commit is contained in:
jordan4ibanez 2021-04-22 21:36:42 -04:00
parent ebf27866ca
commit 8142f7e512
4 changed files with 181 additions and 78 deletions

View file

@ -327,6 +327,7 @@ function mobs:register_mob(name, def)
visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1}, visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1},
punch_timer_cooloff = def.punch_timer_cooloff or 0.5, punch_timer_cooloff = def.punch_timer_cooloff or 0.5,
projectile_cooldown = def.projectile_cooldown or 2, projectile_cooldown = def.projectile_cooldown or 2,
death_animation_timer = 0,
--end j4i stuff --end j4i stuff
-- MCL2 extensions -- MCL2 extensions

View file

@ -610,8 +610,22 @@ mobs.mob_step = function(self, dtime)
return false return false
end end
--do death logic (animation, poof, explosion, etc)
if self.health <= 0 then if self.health <= 0 then
mobs.death_logic(self, dtime)
--this is here because the mob must continue to move
--while stunned before coming to a complete halt even during
--the death tilt
if self.pause_timer > 0 then
self.pause_timer = self.pause_timer - dtime
--perfectly reset pause_timer
if self.pause_timer < 0 then
self.pause_timer = 0
end
end
return return
end end

View file

@ -971,84 +971,7 @@ local update_tag = function(self)
update_roll(self) update_roll(self)
end end
-- drop items
local item_drop = function(self, cooked, looting_level)
-- no drops if disabled by setting
if not mobs_drop_items then return end
looting_level = looting_level or 0
-- no drops for child mobs (except monster)
if (self.child and self.type ~= "monster") then
return
end
local obj, item, num
local pos = self.object:get_pos()
self.drops = self.drops or {} -- nil check
for n = 1, #self.drops do
local dropdef = self.drops[n]
local chance = 1 / dropdef.chance
local looting_type = dropdef.looting
if looting_level > 0 then
local chance_function = dropdef.looting_chance_function
if chance_function then
chance = chance_function(looting_level)
elseif looting_type == "rare" then
chance = chance + (dropdef.looting_factor or 0.01) * looting_level
end
end
local num = 0
local do_common_looting = (looting_level > 0 and looting_type == "common")
if math_random() < chance then
num = math_random(dropdef.min or 1, dropdef.max or 1)
elseif not dropdef.looting_ignore_chance then
do_common_looting = false
end
if do_common_looting then
num = num + math_floor(math_random(0, looting_level) + 0.5)
end
if num > 0 then
item = dropdef.name
-- cook items when true
if cooked then
local output = minetest_get_craft_result({
method = "cooking", width = 1, items = {item}})
if output and output.item and not output.item:is_empty() then
item = output.item:get_name()
end
end
-- add item if it exists
for x = 1, num do
obj = minetest_add_item(pos, ItemStack(item .. " " .. 1))
end
if obj and obj:get_luaentity() then
obj:set_velocity({
x = math_random(-10, 10) / 9,
y = 6,
z = math_random(-10, 10) / 9,
})
elseif obj then
obj:remove() -- item does not exist
end
end
end
self.drops = {}
end
-- check if mob is dead or only hurt -- check if mob is dead or only hurt

View file

@ -0,0 +1,165 @@
local minetest_add_item = minetest.add_item
local minetest_add_particlespawner = minetest.add_particlespawner
local minetest_sound_play = minetest.sound_play
local math_pi = math.pi
local math_random = math.random
local math_floor = math.floor
local HALF_PI = math_pi / 2
local vector_new = vector.new
local death_effect = function(self)
local pos = self.object:get_pos()
local yaw = self.object:get_yaw()
local collisionbox = self.object:get_properties().collisionbox
local min, max
if collisionbox then
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
end
minetest_add_particlespawner({
amount = 50,
time = 0.001,
minpos = vector.add(pos, min),
maxpos = vector.add(pos, max),
minvel = vector.new(-0.5,0.5,-0.5),
maxvel = vector.new(0.5,1,0.5),
minexptime = 1.1,
maxexptime = 1.5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "mcl_particles_mob_death.png", -- this particle looks strange
})
end
-- drop items
local item_drop = function(self, cooked, looting_level)
looting_level = looting_level or 0
-- no drops for child mobs (except monster)
if (self.child and self.type ~= "monster") then
return
end
local obj, item, num
local pos = self.object:get_pos()
self.drops = self.drops or {} -- nil check
for n = 1, #self.drops do
local dropdef = self.drops[n]
local chance = 1 / dropdef.chance
local looting_type = dropdef.looting
if looting_level > 0 then
local chance_function = dropdef.looting_chance_function
if chance_function then
chance = chance_function(looting_level)
elseif looting_type == "rare" then
chance = chance + (dropdef.looting_factor or 0.01) * looting_level
end
end
local num = 0
local do_common_looting = (looting_level > 0 and looting_type == "common")
if math_random() < chance then
num = math_random(dropdef.min or 1, dropdef.max or 1)
elseif not dropdef.looting_ignore_chance then
do_common_looting = false
end
if do_common_looting then
num = num + math_floor(math_random(0, looting_level) + 0.5)
end
if num > 0 then
item = dropdef.name
-- cook items when true
if cooked then
local output = minetest_get_craft_result({
method = "cooking", width = 1, items = {item}})
if output and output.item and not output.item:is_empty() then
item = output.item:get_name()
end
end
-- add item if it exists
for x = 1, num do
obj = minetest_add_item(pos, ItemStack(item .. " " .. 1))
end
if obj and obj:get_luaentity() then
obj:set_velocity({
x = math_random(-10, 10) / 9,
y = 6,
z = math_random(-10, 10) / 9,
})
elseif obj then
obj:remove() -- item does not exist
end
end
end
self.drops = {}
end
mobs.death_logic = function(self, dtime)
self.death_animation_timer = self.death_animation_timer + dtime
--the final POOF of a mob despawning
if self.death_animation_timer >= 1.25 then
item_drop(self,false,1)
death_effect(self)
self.object:remove()
return
end
--I'm sure there's a more efficient way to do this
--but this is the easiest, easier to work with 1 variable synced
--this is also not smooth
local death_animation_roll = self.death_animation_timer * 2 -- * 2 to make it faster
if death_animation_roll > 1 then
death_animation_roll = 1
end
local rot = self.object:get_rotation() --(no pun intended)
rot.z = death_animation_roll * HALF_PI
self.object:set_rotation(rot)
mobs.set_mob_animation(self,"stand", true)
--flying and swimming mobs just fall down
if self.fly or self.swim then
if self.object:get_acceleration().y ~= -self.gravity then
self.object:set_acceleration(vector_new(0,-self.gravity,0))
end
end
--when landing allow mob to slow down and just fall if in air
if self.pause_timer <= 0 then
mobs.set_velocity(self,0)
end
end