mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-17 16:41:06 +01:00
effects -> separate file + metatable
This commit is contained in:
parent
67fd8c8b40
commit
d62dbcb852
3 changed files with 367 additions and 360 deletions
|
@ -72,9 +72,6 @@ if minetest.settings:get_bool("only_peaceful_mobs", false) then
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local active_particlespawners = {}
|
|
||||||
|
|
||||||
|
|
||||||
local function dir_to_pitch(dir)
|
local function dir_to_pitch(dir)
|
||||||
--local dir2 = vector.normalize(dir)
|
--local dir2 = vector.normalize(dir)
|
||||||
local xz = math.abs(dir.x) + math.abs(dir.z)
|
local xz = math.abs(dir.x) + math.abs(dir.z)
|
||||||
|
@ -111,48 +108,6 @@ minetest.register_chatcommand("clearmobs",{
|
||||||
end
|
end
|
||||||
end})
|
end})
|
||||||
|
|
||||||
local function remove_particlespawners(pn,self)
|
|
||||||
if not active_particlespawners[pn] then return end
|
|
||||||
if not active_particlespawners[pn][self.object] then return end
|
|
||||||
for k,v in pairs(active_particlespawners[pn][self.object]) do
|
|
||||||
minetest.delete_particlespawner(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function add_particlespawners(pn,self)
|
|
||||||
if not active_particlespawners[pn] then active_particlespawners[pn] = {} end
|
|
||||||
if not active_particlespawners[pn][self.object] then active_particlespawners[pn][self.object] = {} end
|
|
||||||
for _,ps in pairs(self.particlespawners) do
|
|
||||||
ps.attached = self.object
|
|
||||||
ps.playername = pn
|
|
||||||
table.insert(active_particlespawners[pn][self.object],minetest.add_particlespawner(ps))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function particlespawner_check(self,dtime)
|
|
||||||
if not self.particlespawners then return end
|
|
||||||
--minetest.log(dump(active_particlespawners))
|
|
||||||
if self._particle_timer and self._particle_timer >= 1 then
|
|
||||||
self._particle_timer = 0
|
|
||||||
local players = {}
|
|
||||||
for _,player in pairs(minetest.get_connected_players()) do
|
|
||||||
local pn = player:get_player_name()
|
|
||||||
table.insert(players,pn)
|
|
||||||
if not active_particlespawners[pn] then
|
|
||||||
active_particlespawners[pn] = {} end
|
|
||||||
|
|
||||||
local dst = vector.distance(player:get_pos(),self.object:get_pos())
|
|
||||||
if dst < player_transfer_distance and not active_particlespawners[pn][self.object] then
|
|
||||||
add_particlespawners(pn,self)
|
|
||||||
elseif dst >= player_transfer_distance and active_particlespawners[pn][self.object] then
|
|
||||||
remove_particlespawners(pn,self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif not self._particle_timer then
|
|
||||||
self._particle_timer = 0
|
|
||||||
end
|
|
||||||
self._particle_timer = self._particle_timer + dtime
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
minetest.register_on_leaveplayer(function(player)
|
||||||
local pn = player:get_player_name()
|
local pn = player:get_player_name()
|
||||||
|
@ -240,85 +195,6 @@ local do_attack = function(self, player)
|
||||||
--self:mob_sound("war_cry", true)
|
--self:mob_sound("war_cry", true)
|
||||||
--end
|
--end
|
||||||
end
|
end
|
||||||
|
|
||||||
local add_texture_mod = function(self, mod)
|
|
||||||
local full_mod = ""
|
|
||||||
local already_added = false
|
|
||||||
for i=1, #self.texture_mods do
|
|
||||||
if mod == self.texture_mods[i] then
|
|
||||||
already_added = true
|
|
||||||
end
|
|
||||||
full_mod = full_mod .. self.texture_mods[i]
|
|
||||||
end
|
|
||||||
if not already_added then
|
|
||||||
full_mod = full_mod .. mod
|
|
||||||
table.insert(self.texture_mods, mod)
|
|
||||||
end
|
|
||||||
self.object:set_texture_mod(full_mod)
|
|
||||||
end
|
|
||||||
local remove_texture_mod = function(self, mod)
|
|
||||||
local full_mod = ""
|
|
||||||
local remove = {}
|
|
||||||
for i=1, #self.texture_mods do
|
|
||||||
if self.texture_mods[i] ~= mod then
|
|
||||||
full_mod = full_mod .. self.texture_mods[i]
|
|
||||||
else
|
|
||||||
table.insert(remove, i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i=#remove, 1 do
|
|
||||||
table.remove(self.texture_mods, remove[i])
|
|
||||||
end
|
|
||||||
self.object:set_texture_mod(full_mod)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set defined animation
|
|
||||||
local set_animation = function(self, anim, fixed_frame)
|
|
||||||
if not self.animation or not anim then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if self.state == "die" and anim ~= "die" and anim ~= "stand" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.jockey then
|
|
||||||
anim = "jockey"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
if self:flight_check() and self.fly and anim == "walk" then anim = "fly" end
|
|
||||||
|
|
||||||
self._current_animation = self._current_animation or ""
|
|
||||||
|
|
||||||
if (anim == self._current_animation
|
|
||||||
or not self.animation[anim .. "_start"]
|
|
||||||
or not self.animation[anim .. "_end"]) and self.state ~= "die" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self._current_animation = anim
|
|
||||||
|
|
||||||
local a_start = self.animation[anim .. "_start"]
|
|
||||||
local a_end
|
|
||||||
if fixed_frame then
|
|
||||||
a_end = a_start
|
|
||||||
else
|
|
||||||
a_end = self.animation[anim .. "_end"]
|
|
||||||
end
|
|
||||||
if a_start and a_end then
|
|
||||||
self.object:set_animation({
|
|
||||||
x = a_start,
|
|
||||||
y = a_end},
|
|
||||||
self.animation[anim .. "_speed"] or self.animation.speed_normal or 15,
|
|
||||||
0, self.animation[anim .. "_loop"] ~= false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- above function exported for mount.lua
|
|
||||||
function mcl_mobs:set_animation(self, anim)
|
|
||||||
set_animation(self, anim)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Returns true is node can deal damage to self
|
-- Returns true is node can deal damage to self
|
||||||
local is_node_dangerous = function(self, nodename)
|
local is_node_dangerous = function(self, nodename)
|
||||||
local nn = nodename
|
local nn = nodename
|
||||||
|
@ -429,184 +305,6 @@ local line_of_sight = function(self, pos1, pos2, stepsize)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- custom particle effects
|
|
||||||
local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down)
|
|
||||||
|
|
||||||
radius = radius or 2
|
|
||||||
min_size = min_size or 0.5
|
|
||||||
max_size = max_size or 1
|
|
||||||
gravity = gravity or DEFAULT_FALL_SPEED
|
|
||||||
glow = glow or 0
|
|
||||||
go_down = go_down or false
|
|
||||||
|
|
||||||
local ym
|
|
||||||
if go_down then
|
|
||||||
ym = 0
|
|
||||||
else
|
|
||||||
ym = -radius
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.add_particlespawner({
|
|
||||||
amount = amount,
|
|
||||||
time = 0.25,
|
|
||||||
minpos = pos,
|
|
||||||
maxpos = pos,
|
|
||||||
minvel = {x = -radius, y = ym, z = -radius},
|
|
||||||
maxvel = {x = radius, y = radius, z = radius},
|
|
||||||
minacc = {x = 0, y = gravity, z = 0},
|
|
||||||
maxacc = {x = 0, y = gravity, z = 0},
|
|
||||||
minexptime = 0.1,
|
|
||||||
maxexptime = 1,
|
|
||||||
minsize = min_size,
|
|
||||||
maxsize = max_size,
|
|
||||||
texture = texture,
|
|
||||||
glow = glow,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local damage_effect = function(self, damage)
|
|
||||||
-- damage particles
|
|
||||||
if (not disable_blood) and damage > 0 then
|
|
||||||
|
|
||||||
local amount_large = floor(damage / 2)
|
|
||||||
local amount_small = damage % 2
|
|
||||||
|
|
||||||
local pos = self.object:get_pos()
|
|
||||||
|
|
||||||
pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5
|
|
||||||
|
|
||||||
local texture = "mobs_blood.png"
|
|
||||||
-- full heart damage (one particle for each 2 HP damage)
|
|
||||||
if amount_large > 0 then
|
|
||||||
effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true)
|
|
||||||
end
|
|
||||||
-- half heart damage (one additional particle if damage is an odd number)
|
|
||||||
if amount_small > 0 then
|
|
||||||
-- TODO: Use "half heart"
|
|
||||||
effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
mcl_mobs.death_effect = function(pos, yaw, collisionbox, rotate)
|
|
||||||
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]}
|
|
||||||
else
|
|
||||||
min = { x = -0.5, y = 0, z = -0.5 }
|
|
||||||
max = { x = 0.5, y = 0.5, z = 0.5 }
|
|
||||||
end
|
|
||||||
if rotate then
|
|
||||||
min = vector.rotate(min, {x=0, y=yaw, z=pi/2})
|
|
||||||
max = vector.rotate(max, {x=0, y=yaw, z=pi/2})
|
|
||||||
min, max = vector.sort(min, max)
|
|
||||||
min = vector.multiply(min, 0.5)
|
|
||||||
max = vector.multiply(max, 0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.add_particlespawner({
|
|
||||||
amount = 50,
|
|
||||||
time = 0.001,
|
|
||||||
minpos = vector.add(pos, min),
|
|
||||||
maxpos = vector.add(pos, max),
|
|
||||||
minvel = vector.new(-5,-5,-5),
|
|
||||||
maxvel = vector.new(5,5,5),
|
|
||||||
minexptime = 1.1,
|
|
||||||
maxexptime = 1.5,
|
|
||||||
minsize = 1,
|
|
||||||
maxsize = 2,
|
|
||||||
collisiondetection = false,
|
|
||||||
vertical = false,
|
|
||||||
texture = "mcl_particles_mob_death.png^[colorize:#000000:255",
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.sound_play("mcl_mobs_mob_poof", {
|
|
||||||
pos = pos,
|
|
||||||
gain = 1.0,
|
|
||||||
max_hear_distance = 8,
|
|
||||||
}, true)
|
|
||||||
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 random() < chance then
|
|
||||||
num = 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 + floor(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 = random(-10, 10) / 9,
|
|
||||||
y = 6,
|
|
||||||
z = random(-10, 10) / 9,
|
|
||||||
})
|
|
||||||
elseif obj then
|
|
||||||
obj:remove() -- item does not exist
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.drops = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check if within physical map limits (-30911 to 30927)
|
-- check if within physical map limits (-30911 to 30927)
|
||||||
local function within_limits(pos, radius)
|
local function within_limits(pos, radius)
|
||||||
local wmin, wmax = -30912, 30928
|
local wmin, wmax = -30912, 30928
|
||||||
|
@ -854,7 +552,7 @@ local do_jump = function(self)
|
||||||
v=vector.multiply(v, vector.new(2.8,1,2.8))
|
v=vector.multiply(v, vector.new(2.8,1,2.8))
|
||||||
end
|
end
|
||||||
|
|
||||||
set_animation(self, "jump") -- only when defined
|
self:set_animation( "jump") -- only when defined
|
||||||
|
|
||||||
self.object:set_velocity(v)
|
self.object:set_velocity(v)
|
||||||
|
|
||||||
|
@ -969,7 +667,7 @@ local breed = function(self)
|
||||||
self.animation = nil
|
self.animation = nil
|
||||||
local anim = self._current_animation
|
local anim = self._current_animation
|
||||||
self._current_animation = nil -- Mobs Redo does nothing otherwise
|
self._current_animation = nil -- Mobs Redo does nothing otherwise
|
||||||
mcl_mobs.set_animation(self, anim)
|
mcl_mobs.self:set_animation( anim)
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -996,7 +694,7 @@ local breed = function(self)
|
||||||
|
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
|
|
||||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1)
|
mcl_mobs.effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1)
|
||||||
|
|
||||||
local objs = minetest.get_objects_inside_radius(pos, 3)
|
local objs = minetest.get_objects_inside_radius(pos, 3)
|
||||||
local num = 0
|
local num = 0
|
||||||
|
@ -1741,11 +1439,11 @@ local follow_flop = function(self)
|
||||||
self:set_velocity(self.follow_velocity)
|
self:set_velocity(self.follow_velocity)
|
||||||
|
|
||||||
if self.walk_chance ~= 0 then
|
if self.walk_chance ~= 0 then
|
||||||
set_animation(self, "run")
|
self:set_animation( "run")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -1775,7 +1473,7 @@ local follow_flop = function(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
set_animation(self, "stand", true)
|
self:set_animation( "stand", true)
|
||||||
|
|
||||||
return
|
return
|
||||||
elseif self.state == "flop" then
|
elseif self.state == "flop" then
|
||||||
|
@ -2031,10 +1729,10 @@ local do_states = function(self, dtime)
|
||||||
yaw = self:set_yaw( yaw, 8)
|
yaw = self:set_yaw( yaw, 8)
|
||||||
end
|
end
|
||||||
if self.order == "sit" then
|
if self.order == "sit" then
|
||||||
set_animation(self, "sit")
|
self:set_animation( "sit")
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
else
|
else
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2049,7 +1747,7 @@ local do_states = function(self, dtime)
|
||||||
|
|
||||||
self:set_velocity(self.walk_velocity)
|
self:set_velocity(self.walk_velocity)
|
||||||
self.state = "walk"
|
self.state = "walk"
|
||||||
set_animation(self, "walk")
|
self:set_animation( "walk")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2148,7 +1846,7 @@ local do_states = function(self, dtime)
|
||||||
|
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
self.state = "stand"
|
self.state = "stand"
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
local yaw = self.object:get_yaw() or 0
|
local yaw = self.object:get_yaw() or 0
|
||||||
yaw = self:set_yaw( yaw + 0.78, 8)
|
yaw = self:set_yaw( yaw + 0.78, 8)
|
||||||
else
|
else
|
||||||
|
@ -2159,9 +1857,9 @@ local do_states = function(self, dtime)
|
||||||
and self.animation
|
and self.animation
|
||||||
and self.animation.fly_start
|
and self.animation.fly_start
|
||||||
and self.animation.fly_end then
|
and self.animation.fly_end then
|
||||||
set_animation(self, "fly")
|
self:set_animation( "fly")
|
||||||
else
|
else
|
||||||
set_animation(self, "walk")
|
self:set_animation( "walk")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2176,12 +1874,12 @@ local do_states = function(self, dtime)
|
||||||
self.runaway_timer = 0
|
self.runaway_timer = 0
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
self.state = "stand"
|
self.state = "stand"
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
local yaw = self.object:get_yaw() or 0
|
local yaw = self.object:get_yaw() or 0
|
||||||
yaw = self:set_yaw( yaw + 0.78, 8)
|
yaw = self:set_yaw( yaw + 0.78, 8)
|
||||||
else
|
else
|
||||||
self:set_velocity( self.run_velocity)
|
self:set_velocity( self.run_velocity)
|
||||||
set_animation(self, "run")
|
self:set_animation( "run")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- attack routines (explode, dogfight, shoot, dogshoot)
|
-- attack routines (explode, dogfight, shoot, dogshoot)
|
||||||
|
@ -2199,7 +1897,7 @@ local do_states = function(self, dtime)
|
||||||
|
|
||||||
self.state = "stand"
|
self.state = "stand"
|
||||||
self:set_velocity( 0)
|
self:set_velocity( 0)
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
self.attack = nil
|
self.attack = nil
|
||||||
self.v_start = false
|
self.v_start = false
|
||||||
self.timer = 0
|
self.timer = 0
|
||||||
|
@ -2248,7 +1946,7 @@ local do_states = function(self, dtime)
|
||||||
self.timer = 0
|
self.timer = 0
|
||||||
self.blinktimer = 0
|
self.blinktimer = 0
|
||||||
self.blinkstatus = false
|
self.blinkstatus = false
|
||||||
remove_texture_mod(self, "^[brighten")
|
self:remove_texture_mod("^[brighten")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- walk right up to player unless the timer is active
|
-- walk right up to player unless the timer is active
|
||||||
|
@ -2259,9 +1957,9 @@ local do_states = function(self, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.animation and self.animation.run_start then
|
if self.animation and self.animation.run_start then
|
||||||
set_animation(self, "run")
|
self:set_animation( "run")
|
||||||
else
|
else
|
||||||
set_animation(self, "walk")
|
self:set_animation( "walk")
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.v_start then
|
if self.v_start then
|
||||||
|
@ -2274,9 +1972,9 @@ local do_states = function(self, dtime)
|
||||||
self.blinktimer = 0
|
self.blinktimer = 0
|
||||||
|
|
||||||
if self.blinkstatus then
|
if self.blinkstatus then
|
||||||
remove_texture_mod(self, "^[brighten")
|
self:remove_texture_mod("^[brighten")
|
||||||
else
|
else
|
||||||
add_texture_mod(self, "^[brighten")
|
self:add_texture_mod("^[brighten")
|
||||||
end
|
end
|
||||||
|
|
||||||
self.blinkstatus = not self.blinkstatus
|
self.blinkstatus = not self.blinkstatus
|
||||||
|
@ -2296,7 +1994,7 @@ local do_states = function(self, dtime)
|
||||||
}, true)
|
}, true)
|
||||||
|
|
||||||
entity_physics(pos, entity_damage_radius)
|
entity_physics(pos, entity_damage_radius)
|
||||||
effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0)
|
mcl_mobs.effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0)
|
||||||
end
|
end
|
||||||
mcl_burning.extinguish(self.object)
|
mcl_burning.extinguish(self.object)
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
|
@ -2409,7 +2107,7 @@ local do_states = function(self, dtime)
|
||||||
if is_at_cliff_or_danger(self) then
|
if is_at_cliff_or_danger(self) then
|
||||||
|
|
||||||
self:set_velocity( 0)
|
self:set_velocity( 0)
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
local yaw = self.object:get_yaw() or 0
|
local yaw = self.object:get_yaw() or 0
|
||||||
yaw = self:set_yaw( yaw + 0.78, 8)
|
yaw = self:set_yaw( yaw + 0.78, 8)
|
||||||
else
|
else
|
||||||
|
@ -2421,9 +2119,9 @@ local do_states = function(self, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.animation and self.animation.run_start then
|
if self.animation and self.animation.run_start then
|
||||||
set_animation(self, "run")
|
self:set_animation( "run")
|
||||||
else
|
else
|
||||||
set_animation(self, "walk")
|
self:set_animation( "walk")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2443,9 +2141,9 @@ local do_states = function(self, dtime)
|
||||||
|
|
||||||
if self.double_melee_attack
|
if self.double_melee_attack
|
||||||
and random(1, 2) == 1 then
|
and random(1, 2) == 1 then
|
||||||
set_animation(self, "punch2")
|
self:set_animation( "punch2")
|
||||||
else
|
else
|
||||||
set_animation(self, "punch")
|
self:set_animation( "punch")
|
||||||
end
|
end
|
||||||
|
|
||||||
local p2 = p
|
local p2 = p
|
||||||
|
@ -2507,7 +2205,7 @@ local do_states = function(self, dtime)
|
||||||
|
|
||||||
--stay away from player so as to shoot them
|
--stay away from player so as to shoot them
|
||||||
if dist < self.avoid_distance and self.shooter_avoid_enemy then
|
if dist < self.avoid_distance and self.shooter_avoid_enemy then
|
||||||
set_animation(self, "shoot")
|
self:set_animation( "shoot")
|
||||||
stay_away_from_player=vector.multiply(vector.direction(p, s), 0.33)
|
stay_away_from_player=vector.multiply(vector.direction(p, s), 0.33)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2532,7 +2230,7 @@ local do_states = function(self, dtime)
|
||||||
and random(1, 100) <= 60 then
|
and random(1, 100) <= 60 then
|
||||||
|
|
||||||
self.timer = 0
|
self.timer = 0
|
||||||
set_animation(self, "shoot")
|
self:set_animation( "shoot")
|
||||||
|
|
||||||
-- play shoot attack sound
|
-- play shoot attack sound
|
||||||
self:mob_sound("shoot_attack")
|
self:mob_sound("shoot_attack")
|
||||||
|
@ -3060,7 +2758,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
||||||
}, true)
|
}, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
damage_effect(self, damage)
|
self:damage_effect(damage)
|
||||||
|
|
||||||
-- do damage
|
-- do damage
|
||||||
self.health = self.health - damage
|
self.health = self.health - damage
|
||||||
|
@ -3115,9 +2813,9 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
|
||||||
self._turn_to=self.object:get_yaw()-1.57
|
self._turn_to=self.object:get_yaw()-1.57
|
||||||
self.frame_speed_multiplier=2.3
|
self.frame_speed_multiplier=2.3
|
||||||
if self.animation.run_end then
|
if self.animation.run_end then
|
||||||
set_animation(self, "run")
|
self:set_animation( "run")
|
||||||
elseif self.animation.walk_end then
|
elseif self.animation.walk_end then
|
||||||
set_animation(self, "walk")
|
self:set_animation( "walk")
|
||||||
end
|
end
|
||||||
minetest.after(0.2, function()
|
minetest.after(0.2, function()
|
||||||
if self and self.object then
|
if self and self.object then
|
||||||
|
@ -3217,7 +2915,7 @@ end
|
||||||
local mob_staticdata = function(self)
|
local mob_staticdata = function(self)
|
||||||
|
|
||||||
for _,p in pairs(minetest.get_connected_players()) do
|
for _,p in pairs(minetest.get_connected_players()) do
|
||||||
remove_particlespawners(p:get_player_name(),self)
|
self:remove_particlespawners(p:get_player_name())
|
||||||
end
|
end
|
||||||
-- remove mob when out of range unless tamed
|
-- remove mob when out of range unless tamed
|
||||||
if remove_far
|
if remove_far
|
||||||
|
@ -3419,7 +3117,7 @@ local mob_activate = function(self, staticdata, def, dtime)
|
||||||
self:set_yaw( (random(0, 360) - 180) / 180 * pi, 6)
|
self:set_yaw( (random(0, 360) - 180) / 180 * pi, 6)
|
||||||
self:update_tag()
|
self:update_tag()
|
||||||
self._current_animation = nil
|
self._current_animation = nil
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
|
|
||||||
-- run on_spawn function if found
|
-- run on_spawn function if found
|
||||||
if self.on_spawn and not self.on_spawn_run then
|
if self.on_spawn and not self.on_spawn_run then
|
||||||
|
@ -3497,7 +3195,7 @@ local mob_step = function(self, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:player_in_active_range() then
|
if not self:player_in_active_range() then
|
||||||
set_animation(self, "stand", true)
|
self:set_animation( "stand", true)
|
||||||
local node_under = node_ok(vector.offset(pos,0,-1,0)).name
|
local node_under = node_ok(vector.offset(pos,0,-1,0)).name
|
||||||
local acc = self.object:get_acceleration()
|
local acc = self.object:get_acceleration()
|
||||||
if acc.y > 0 or node_under ~= "air" then
|
if acc.y > 0 or node_under ~= "air" then
|
||||||
|
@ -3517,7 +3215,7 @@ local mob_step = function(self, dtime)
|
||||||
|
|
||||||
check_item_pickup(self)
|
check_item_pickup(self)
|
||||||
check_aggro(self,dtime)
|
check_aggro(self,dtime)
|
||||||
particlespawner_check(self,dtime)
|
self:check_particlespawners(dtime)
|
||||||
if not self.fire_resistant then
|
if not self.fire_resistant then
|
||||||
mcl_burning.tick(self.object, dtime, self)
|
mcl_burning.tick(self.object, dtime, self)
|
||||||
-- mcl_burning.tick may remove object immediately
|
-- mcl_burning.tick may remove object immediately
|
||||||
|
@ -3767,7 +3465,7 @@ local mob_step = function(self, dtime)
|
||||||
if random(1, 10) <= 6 then
|
if random(1, 10) <= 6 then
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
self.state = "stand"
|
self.state = "stand"
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
yaw = yaw + random(-0.5, 0.5)
|
yaw = yaw + random(-0.5, 0.5)
|
||||||
yaw = self:set_yaw( yaw, 8)
|
yaw = self:set_yaw( yaw, 8)
|
||||||
end
|
end
|
||||||
|
@ -3818,7 +3516,7 @@ local mob_step = function(self, dtime)
|
||||||
if is_at_cliff_or_danger(self) then
|
if is_at_cliff_or_danger(self) then
|
||||||
self:set_velocity(0)
|
self:set_velocity(0)
|
||||||
self.state = "stand"
|
self.state = "stand"
|
||||||
set_animation(self, "stand")
|
self:set_animation( "stand")
|
||||||
local yaw = self.object:get_yaw() or 0
|
local yaw = self.object:get_yaw() or 0
|
||||||
yaw = self:set_yaw( yaw + 0.78, 8)
|
yaw = self:set_yaw( yaw + 0.78, 8)
|
||||||
end
|
end
|
||||||
|
@ -4241,7 +3939,7 @@ function mcl_mobs:safe_boom(self, pos, strength)
|
||||||
}, true)
|
}, true)
|
||||||
local radius = strength
|
local radius = strength
|
||||||
entity_physics(pos, radius)
|
entity_physics(pos, radius)
|
||||||
effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0)
|
mcl_mobs.effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -4467,7 +4165,7 @@ function mcl_mobs:spawn_child(pos, mob_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ent = child:get_luaentity()
|
local ent = child:get_luaentity()
|
||||||
effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5)
|
mcl_mobs.effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5)
|
||||||
|
|
||||||
ent.child = true
|
ent.child = true
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
|
local math, vector, minetest, mcl_mobs = math, vector, minetest, mcl_mobs
|
||||||
local mob_class = mcl_mobs.mob_class
|
local mob_class = mcl_mobs.mob_class
|
||||||
|
local active_particlespawners = {}
|
||||||
|
local DEFAULT_FALL_SPEED = -9.81*1.5
|
||||||
-- play sound
|
-- play sound
|
||||||
function mob_class:mob_sound(soundname, is_opinion, fixed_pitch)
|
function mob_class:mob_sound(soundname, is_opinion, fixed_pitch)
|
||||||
|
|
||||||
|
@ -41,3 +43,226 @@ function mob_class:mob_sound(soundname, is_opinion, fixed_pitch)
|
||||||
self.opinion_sound_cooloff = 1
|
self.opinion_sound_cooloff = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mob_class:add_texture_mod(mod)
|
||||||
|
local full_mod = ""
|
||||||
|
local already_added = false
|
||||||
|
for i=1, #self.texture_mods do
|
||||||
|
if mod == self.texture_mods[i] then
|
||||||
|
already_added = true
|
||||||
|
end
|
||||||
|
full_mod = full_mod .. self.texture_mods[i]
|
||||||
|
end
|
||||||
|
if not already_added then
|
||||||
|
full_mod = full_mod .. mod
|
||||||
|
table.insert(self.texture_mods, mod)
|
||||||
|
end
|
||||||
|
self.object:set_texture_mod(full_mod)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mob_class:remove_texture_mod(mod)
|
||||||
|
local full_mod = ""
|
||||||
|
local remove = {}
|
||||||
|
for i=1, #self.texture_mods do
|
||||||
|
if self.texture_mods[i] ~= mod then
|
||||||
|
full_mod = full_mod .. self.texture_mods[i]
|
||||||
|
else
|
||||||
|
table.insert(remove, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i=#remove, 1 do
|
||||||
|
table.remove(self.texture_mods, remove[i])
|
||||||
|
end
|
||||||
|
self.object:set_texture_mod(full_mod)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- custom particle effects
|
||||||
|
function mcl_mobs.effect(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down)
|
||||||
|
|
||||||
|
radius = radius or 2
|
||||||
|
min_size = min_size or 0.5
|
||||||
|
max_size = max_size or 1
|
||||||
|
gravity = gravity or DEFAULT_FALL_SPEED
|
||||||
|
glow = glow or 0
|
||||||
|
go_down = go_down or false
|
||||||
|
|
||||||
|
local ym
|
||||||
|
if go_down then
|
||||||
|
ym = 0
|
||||||
|
else
|
||||||
|
ym = -radius
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = amount,
|
||||||
|
time = 0.25,
|
||||||
|
minpos = pos,
|
||||||
|
maxpos = pos,
|
||||||
|
minvel = {x = -radius, y = ym, z = -radius},
|
||||||
|
maxvel = {x = radius, y = radius, z = radius},
|
||||||
|
minacc = {x = 0, y = gravity, z = 0},
|
||||||
|
maxacc = {x = 0, y = gravity, z = 0},
|
||||||
|
minexptime = 0.1,
|
||||||
|
maxexptime = 1,
|
||||||
|
minsize = min_size,
|
||||||
|
maxsize = max_size,
|
||||||
|
texture = texture,
|
||||||
|
glow = glow,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function mob_class:damage_effect(damage)
|
||||||
|
-- damage particles
|
||||||
|
if (not disable_blood) and damage > 0 then
|
||||||
|
|
||||||
|
local amount_large = math.floor(damage / 2)
|
||||||
|
local amount_small = damage % 2
|
||||||
|
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
|
||||||
|
pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5
|
||||||
|
|
||||||
|
local texture = "mobs_blood.png"
|
||||||
|
-- full heart damage (one particle for each 2 HP damage)
|
||||||
|
if amount_large > 0 then
|
||||||
|
mcl_mobs.effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true)
|
||||||
|
end
|
||||||
|
-- half heart damage (one additional particle if damage is an odd number)
|
||||||
|
if amount_small > 0 then
|
||||||
|
-- TODO: Use "half heart"
|
||||||
|
mcl_mobs.effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mcl_mobs.death_effect = function(pos, yaw, collisionbox, rotate)
|
||||||
|
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]}
|
||||||
|
else
|
||||||
|
min = { x = -0.5, y = 0, z = -0.5 }
|
||||||
|
max = { x = 0.5, y = 0.5, z = 0.5 }
|
||||||
|
end
|
||||||
|
if rotate then
|
||||||
|
min = vector.rotate(min, {x=0, y=yaw, z=math.pi/2})
|
||||||
|
max = vector.rotate(max, {x=0, y=yaw, z=math.pi/2})
|
||||||
|
min, max = vector.sort(min, max)
|
||||||
|
min = vector.multiply(min, 0.5)
|
||||||
|
max = vector.multiply(max, 0.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 50,
|
||||||
|
time = 0.001,
|
||||||
|
minpos = vector.add(pos, min),
|
||||||
|
maxpos = vector.add(pos, max),
|
||||||
|
minvel = vector.new(-5,-5,-5),
|
||||||
|
maxvel = vector.new(5,5,5),
|
||||||
|
minexptime = 1.1,
|
||||||
|
maxexptime = 1.5,
|
||||||
|
minsize = 1,
|
||||||
|
maxsize = 2,
|
||||||
|
collisiondetection = false,
|
||||||
|
vertical = false,
|
||||||
|
texture = "mcl_particles_mob_death.png^[colorize:#000000:255",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.sound_play("mcl_mobs_mob_poof", {
|
||||||
|
pos = pos,
|
||||||
|
gain = 1.0,
|
||||||
|
max_hear_distance = 8,
|
||||||
|
}, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function mob_class:remove_particlespawners(pn)
|
||||||
|
if not active_particlespawners[pn] then return end
|
||||||
|
if not active_particlespawners[pn][self.object] then return end
|
||||||
|
for k,v in pairs(active_particlespawners[pn][self.object]) do
|
||||||
|
minetest.delete_particlespawner(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mob_class:add_particlespawners(pn)
|
||||||
|
if not active_particlespawners[pn] then active_particlespawners[pn] = {} end
|
||||||
|
if not active_particlespawners[pn][self.object] then active_particlespawners[pn][self.object] = {} end
|
||||||
|
for _,ps in pairs(self.particlespawners) do
|
||||||
|
ps.attached = self.object
|
||||||
|
ps.playername = pn
|
||||||
|
table.insert(active_particlespawners[pn][self.object],minetest.add_particlespawner(ps))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mob_class:check_particlespawners(dtime)
|
||||||
|
if not self.particlespawners then return end
|
||||||
|
--minetest.log(dump(active_particlespawners))
|
||||||
|
if self._particle_timer and self._particle_timer >= 1 then
|
||||||
|
self._particle_timer = 0
|
||||||
|
local players = {}
|
||||||
|
for _,player in pairs(minetest.get_connected_players()) do
|
||||||
|
local pn = player:get_player_name()
|
||||||
|
table.insert(players,pn)
|
||||||
|
if not active_particlespawners[pn] then
|
||||||
|
active_particlespawners[pn] = {} end
|
||||||
|
|
||||||
|
local dst = vector.distance(player:get_pos(),self.object:get_pos())
|
||||||
|
if dst < player_transfer_distance and not active_particlespawners[pn][self.object] then
|
||||||
|
self:add_particlespawners(pn)
|
||||||
|
elseif dst >= player_transfer_distance and active_particlespawners[pn][self.object] then
|
||||||
|
self:remove_particlespawners(pn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif not self._particle_timer then
|
||||||
|
self._particle_timer = 0
|
||||||
|
end
|
||||||
|
self._particle_timer = self._particle_timer + dtime
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- set defined animation
|
||||||
|
function mob_class:set_animation(anim, fixed_frame)
|
||||||
|
if not self.animation or not anim then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.state == "die" and anim ~= "die" and anim ~= "stand" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.jockey then
|
||||||
|
anim = "jockey"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if self:flight_check() and self.fly and anim == "walk" then anim = "fly" end
|
||||||
|
|
||||||
|
self._current_animation = self._current_animation or ""
|
||||||
|
|
||||||
|
if (anim == self._current_animation
|
||||||
|
or not self.animation[anim .. "_start"]
|
||||||
|
or not self.animation[anim .. "_end"]) and self.state ~= "die" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self._current_animation = anim
|
||||||
|
|
||||||
|
local a_start = self.animation[anim .. "_start"]
|
||||||
|
local a_end
|
||||||
|
if fixed_frame then
|
||||||
|
a_end = a_start
|
||||||
|
else
|
||||||
|
a_end = self.animation[anim .. "_end"]
|
||||||
|
end
|
||||||
|
if a_start and a_end then
|
||||||
|
self.object:set_animation({
|
||||||
|
x = a_start,
|
||||||
|
y = a_end},
|
||||||
|
self.animation[anim .. "_speed"] or self.animation.speed_normal or 15,
|
||||||
|
0, self.animation[anim .. "_loop"] ~= false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- above function exported for mount.lua
|
||||||
|
function mcl_mobs:set_animation(self, anim)
|
||||||
|
set_animation(self, anim)
|
||||||
|
end
|
||||||
|
|
|
@ -3,7 +3,12 @@ local mob_class = mcl_mobs.mob_class
|
||||||
|
|
||||||
local ENTITY_CRAMMING_MAX = 24
|
local ENTITY_CRAMMING_MAX = 24
|
||||||
local CRAMMING_DAMAGE = 3
|
local CRAMMING_DAMAGE = 3
|
||||||
|
local DEATH_DELAY = 0.5
|
||||||
local DEFAULT_FALL_SPEED = -9.81*1.5
|
local DEFAULT_FALL_SPEED = -9.81*1.5
|
||||||
|
local FLOP_HEIGHT = 6
|
||||||
|
local FLOP_HOR_SPEED = 1.5
|
||||||
|
local PATHFINDING = "gowp"
|
||||||
|
local mobs_debug = minetest.settings:get_bool("mobs_debug", false)
|
||||||
|
|
||||||
|
|
||||||
-- get node but use fallback for nil or unknown
|
-- get node but use fallback for nil or unknown
|
||||||
|
@ -38,6 +43,85 @@ local function within_limits(pos, radius)
|
||||||
return true
|
return true
|
||||||
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 random() < chance then
|
||||||
|
num = 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 + floor(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 = random(-10, 10) / 9,
|
||||||
|
y = 6,
|
||||||
|
z = random(-10, 10) / 9,
|
||||||
|
})
|
||||||
|
elseif obj then
|
||||||
|
obj:remove() -- item does not exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.drops = {}
|
||||||
|
end
|
||||||
|
|
||||||
-- collision function borrowed amended from jordan4ibanez open_ai mod
|
-- collision function borrowed amended from jordan4ibanez open_ai mod
|
||||||
function mob_class:collision()
|
function mob_class:collision()
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
|
@ -240,7 +324,7 @@ function mob_class:set_yaw(yaw, delay, dtime)
|
||||||
|
|
||||||
if delay == 0 then
|
if delay == 0 then
|
||||||
if self.shaking and dtime then
|
if self.shaking and dtime then
|
||||||
yaw = yaw + (random() * 2 - 1) * 5 * dtime
|
yaw = yaw + (math.random() * 2 - 1) * 5 * dtime
|
||||||
end
|
end
|
||||||
self:update_roll()
|
self:update_roll()
|
||||||
return yaw
|
return yaw
|
||||||
|
@ -308,10 +392,10 @@ function mob_class:check_for_death(cause, cmi_cause)
|
||||||
|
|
||||||
-- play damage sound if health was reduced and make mob flash red.
|
-- play damage sound if health was reduced and make mob flash red.
|
||||||
if damaged then
|
if damaged then
|
||||||
add_texture_mod(self, "^[colorize:#d42222:175")
|
self:add_texture_mod("^[colorize:#d42222:175")
|
||||||
minetest.after(1, function(self)
|
minetest.after(1, function(self)
|
||||||
if self and self.object then
|
if self and self.object then
|
||||||
remove_texture_mod(self, "^[colorize:#d42222:175")
|
self:remove_texture_mod("^[colorize:#d42222:175")
|
||||||
end
|
end
|
||||||
end, self)
|
end, self)
|
||||||
self:mob_sound("damage")
|
self:mob_sound("damage")
|
||||||
|
@ -352,8 +436,8 @@ function mob_class:check_for_death(cause, cmi_cause)
|
||||||
local looting = mcl_enchanting.get_enchantment(wielditem, "looting")
|
local looting = mcl_enchanting.get_enchantment(wielditem, "looting")
|
||||||
item_drop(self, cooked, looting)
|
item_drop(self, cooked, looting)
|
||||||
|
|
||||||
if ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then
|
if ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= math.huge) then
|
||||||
mcl_experience.throw_xp(self.object:get_pos(), random(self.xp_min, self.xp_max))
|
mcl_experience.throw_xp(self.object:get_pos(), math.random(self.xp_min, self.xp_max))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -386,8 +470,8 @@ function mob_class:check_for_death(cause, cmi_cause)
|
||||||
self.fall_speed = DEFAULT_FALL_SPEED
|
self.fall_speed = DEFAULT_FALL_SPEED
|
||||||
self.timer = 0
|
self.timer = 0
|
||||||
self.blinktimer = 0
|
self.blinktimer = 0
|
||||||
remove_texture_mod(self, "^[colorize:#FF000040")
|
self:remove_texture_mod("^[colorize:#FF000040")
|
||||||
remove_texture_mod(self, "^[brighten")
|
self:remove_texture_mod("^[brighten")
|
||||||
self.passive = true
|
self.passive = true
|
||||||
|
|
||||||
self.object:set_properties({
|
self.object:set_properties({
|
||||||
|
@ -395,7 +479,7 @@ function mob_class:check_for_death(cause, cmi_cause)
|
||||||
collide_with_objects = false,
|
collide_with_objects = false,
|
||||||
})
|
})
|
||||||
|
|
||||||
set_velocity(self, 0)
|
self:set_velocity(0)
|
||||||
local acc = self.object:get_acceleration()
|
local acc = self.object:get_acceleration()
|
||||||
acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0
|
acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0
|
||||||
self.object:set_acceleration(acc)
|
self.object:set_acceleration(acc)
|
||||||
|
@ -411,10 +495,10 @@ function mob_class:check_for_death(cause, cmi_cause)
|
||||||
local frames = self.animation.die_end - self.animation.die_start
|
local frames = self.animation.die_end - self.animation.die_start
|
||||||
local speed = self.animation.die_speed or 15
|
local speed = self.animation.die_speed or 15
|
||||||
length = math.max(frames / speed, 0) + DEATH_DELAY
|
length = math.max(frames / speed, 0) + DEATH_DELAY
|
||||||
set_animation(self, "die")
|
self:set_animation( "die")
|
||||||
else
|
else
|
||||||
length = 1 + DEATH_DELAY
|
length = 1 + DEATH_DELAY
|
||||||
set_animation(self, "stand", true)
|
self:set_animation( "stand", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -474,7 +558,7 @@ function mob_class:do_env_damage()
|
||||||
if not ((mcl_weather.rain.raining or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos)) then
|
if not ((mcl_weather.rain.raining or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos)) then
|
||||||
self.health = self.health - damage
|
self.health = self.health - damage
|
||||||
|
|
||||||
effect(pos, 5, "mcl_particles_smoke.png")
|
mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png")
|
||||||
|
|
||||||
if self:check_for_death("light", {type = "light"}) then
|
if self:check_for_death("light", {type = "light"}) then
|
||||||
return true
|
return true
|
||||||
|
@ -547,7 +631,7 @@ function mob_class:do_env_damage()
|
||||||
|
|
||||||
self.health = self.health - self.water_damage
|
self.health = self.health - self.water_damage
|
||||||
|
|
||||||
effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil)
|
mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil)
|
||||||
|
|
||||||
if self:check_for_death("water", {type = "environment",
|
if self:check_for_death("water", {type = "environment",
|
||||||
pos = pos, node = self.standing_in}) then
|
pos = pos, node = self.standing_in}) then
|
||||||
|
@ -563,7 +647,7 @@ function mob_class:do_env_damage()
|
||||||
|
|
||||||
self.health = self.health - self.lava_damage
|
self.health = self.health - self.lava_damage
|
||||||
|
|
||||||
effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil)
|
mcl_mobs.effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil)
|
||||||
mcl_burning.set_on_fire(self.object, 10)
|
mcl_burning.set_on_fire(self.object, 10)
|
||||||
|
|
||||||
if self:check_for_death("lava", {type = "environment",
|
if self:check_for_death("lava", {type = "environment",
|
||||||
|
@ -580,7 +664,7 @@ function mob_class:do_env_damage()
|
||||||
|
|
||||||
self.health = self.health - self.fire_damage
|
self.health = self.health - self.fire_damage
|
||||||
|
|
||||||
effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil)
|
mcl_mobs.effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil)
|
||||||
mcl_burning.set_on_fire(self.object, 5)
|
mcl_burning.set_on_fire(self.object, 5)
|
||||||
|
|
||||||
if self:check_for_death("fire", {type = "environment",
|
if self:check_for_death("fire", {type = "environment",
|
||||||
|
@ -594,7 +678,7 @@ function mob_class:do_env_damage()
|
||||||
|
|
||||||
self.health = self.health - nodef.damage_per_second
|
self.health = self.health - nodef.damage_per_second
|
||||||
|
|
||||||
effect(pos, 5, "mcl_particles_smoke.png")
|
mcl_mobs.effect(pos, 5, "mcl_particles_smoke.png")
|
||||||
|
|
||||||
if self:check_for_death("dps", {type = "environment",
|
if self:check_for_death("dps", {type = "environment",
|
||||||
pos = pos, node = self.standing_in}) then
|
pos = pos, node = self.standing_in}) then
|
||||||
|
@ -616,7 +700,7 @@ function mob_class:do_env_damage()
|
||||||
|
|
||||||
self.breath = math.max(0, self.breath - 1)
|
self.breath = math.max(0, self.breath - 1)
|
||||||
|
|
||||||
effect(pos, 2, "bubble.png", nil, nil, 1, nil)
|
mcl_mobs.effect(pos, 2, "bubble.png", nil, nil, 1, nil)
|
||||||
if self.breath <= 0 then
|
if self.breath <= 0 then
|
||||||
local dmg
|
local dmg
|
||||||
if nodef.drowning > 0 then
|
if nodef.drowning > 0 then
|
||||||
|
@ -624,7 +708,7 @@ function mob_class:do_env_damage()
|
||||||
else
|
else
|
||||||
dmg = 4
|
dmg = 4
|
||||||
end
|
end
|
||||||
damage_effect(self, dmg)
|
self:damage_effect(dmg)
|
||||||
self.health = self.health - dmg
|
self.health = self.health - dmg
|
||||||
end
|
end
|
||||||
if self:check_for_death("drowning", {type = "environment",
|
if self:check_for_death("drowning", {type = "environment",
|
||||||
|
@ -671,11 +755,11 @@ end
|
||||||
|
|
||||||
function mob_class:damage_mob(reason,damage)
|
function mob_class:damage_mob(reason,damage)
|
||||||
if not self.health then return end
|
if not self.health then return end
|
||||||
damage = floor(damage)
|
damage = math.floor(damage)
|
||||||
if damage > 0 then
|
if damage > 0 then
|
||||||
self.health = self.health - damage
|
self.health = self.health - damage
|
||||||
|
|
||||||
effect(self.object:get_pos(), 5, "mcl_particles_smoke.png", 1, 2, 2, nil)
|
mcl_mobs.effect(self.object:get_pos(), 5, "mcl_particles_smoke.png", 1, 2, 2, nil)
|
||||||
|
|
||||||
if self:check_for_death(reason, {type = reason}) then
|
if self:check_for_death(reason, {type = reason}) then
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in a new issue