forked from MineClone5/MineClone5
159 lines
4.0 KiB
Lua
159 lines
4.0 KiB
Lua
local minetest_add_item = minetest.add_item
|
|
--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
|
|
|
|
|
|
-- 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
|
|
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)
|
|
|
|
--stop crashing game when object is nil
|
|
if not self or not self.object or not self.object:get_luaentity() then
|
|
return
|
|
end
|
|
|
|
self.death_animation_timer = self.death_animation_timer + dtime
|
|
|
|
--get all attached entities and sort through them
|
|
local attached_entities = self.object:get_children()
|
|
if #attached_entities > 0 then
|
|
for _,entity in pairs(attached_entities) do
|
|
--kick the player off
|
|
if entity:is_player() then
|
|
mobs.detach(entity)
|
|
--kick mobs off
|
|
--if there is scaling issues, this needs an additional check
|
|
else
|
|
entity:set_detach()
|
|
end
|
|
end
|
|
end
|
|
|
|
--stop mob from getting in the way of other mobs you're fighting
|
|
if self.object:get_properties().pointable then
|
|
self.object:set_properties({pointable = false})
|
|
end
|
|
|
|
--the final POOF of a mob despawning
|
|
if self.death_animation_timer >= 1.25 then
|
|
item_drop(self,false,1)
|
|
mobs.death_effect(self)
|
|
mcl_experience.throw_xp(self.object:get_pos(), math_random(self.xp_min, self.xp_max))
|
|
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
|