351 lines
9.4 KiB
Lua
351 lines
9.4 KiB
Lua
local vector_direction = vector.direction
|
|
local minetest_dir_to_yaw = minetest.dir_to_yaw
|
|
local vector_distance = vector.distance
|
|
local vector_multiply = vector.multiply
|
|
local math_random = math.random
|
|
|
|
--[[
|
|
_ _ _ _
|
|
| | | | | | | |
|
|
| | | | __ _ _ __ __| | | |
|
|
| | | | / _` | '_ \ / _` | | |
|
|
|_| | |___| (_| | | | | (_| | |_|
|
|
(_) \_____/\__,_|_| |_|\__,_| (_)
|
|
]]--
|
|
|
|
|
|
|
|
--[[
|
|
_____ _ _
|
|
| ___| | | | |
|
|
| |____ ___ __ | | ___ __| | ___
|
|
| __\ \/ / '_ \| |/ _ \ / _` |/ _ \
|
|
| |___> <| |_) | | (_) | (_| | __/
|
|
\____/_/\_\ .__/|_|\___/ \__,_|\___|
|
|
| |
|
|
|_|
|
|
]]--
|
|
|
|
mobs.explode_attack_walk = function(self,dtime)
|
|
|
|
--this needs an exception
|
|
if self.attacking == nil or not self.attacking:is_player() then
|
|
self.attacking = nil
|
|
return
|
|
end
|
|
|
|
mobs.set_yaw_while_attacking(self)
|
|
|
|
local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos())
|
|
|
|
--make mob walk up to player within 2 nodes distance then start exploding
|
|
if distance_from_attacking >= self.reach and
|
|
--don't allow explosion to cancel unless out of the reach boundary
|
|
not (self.explosion_animation ~= nil and self.explosion_animation > 0 and distance_from_attacking <= self.defuse_reach) then
|
|
|
|
mobs.set_velocity(self, self.run_velocity)
|
|
mobs.set_mob_animation(self,"run")
|
|
|
|
mobs.reverse_explosion_animation(self,dtime)
|
|
else
|
|
mobs.set_velocity(self,0)
|
|
|
|
--this is the only way I can reference this without dumping extra data on all mobs
|
|
if not self.explosion_animation then
|
|
self.explosion_animation = 0
|
|
end
|
|
|
|
--play ignite sound
|
|
if self.explosion_animation == 0 then
|
|
mobs.play_sound(self,"attack")
|
|
end
|
|
|
|
mobs.set_mob_animation(self,"stand")
|
|
|
|
mobs.handle_explosion_animation(self)
|
|
|
|
self.explosion_animation = self.explosion_animation + (dtime/2.5)
|
|
end
|
|
|
|
--make explosive mobs jump
|
|
--check for nodes to jump over
|
|
--explosive mobs will just ride against walls for now
|
|
local node_in_front_of = mobs.jump_check(self)
|
|
if node_in_front_of == 1 then
|
|
mobs.jump(self)
|
|
end
|
|
|
|
|
|
--do biggening explosion thing
|
|
if self.explosion_animation and self.explosion_animation > self.explosion_timer then
|
|
mcl_explosions.explode(self.object:get_pos(), self.explosion_strength,{ drop_chance = 1.0 })
|
|
self.object:remove()
|
|
end
|
|
end
|
|
|
|
|
|
--this is a small helper function to make working with explosion animations easier
|
|
mobs.reverse_explosion_animation = function(self,dtime)
|
|
|
|
--if explosion animation was greater than 0 then reverse it
|
|
if self.explosion_animation ~= nil and self.explosion_animation > 0 then
|
|
self.explosion_animation = self.explosion_animation - dtime
|
|
if self.explosion_animation < 0 then
|
|
self.explosion_animation = 0
|
|
end
|
|
end
|
|
|
|
mobs.handle_explosion_animation(self)
|
|
end
|
|
|
|
|
|
|
|
|
|
--[[
|
|
______ _
|
|
| ___ \ | |
|
|
| |_/ / _ _ __ ___| |__
|
|
| __/ | | | '_ \ / __| '_ \
|
|
| | | |_| | | | | (__| | | |
|
|
\_| \__,_|_| |_|\___|_| |_|
|
|
]]--
|
|
|
|
|
|
|
|
mobs.punch_attack_walk = function(self,dtime)
|
|
|
|
--this needs an exception
|
|
if self.attacking == nil or not self.attacking:is_player() then
|
|
self.attacking = nil
|
|
return
|
|
end
|
|
|
|
local distance_from_attacking = mobs.get_2d_distance(self.object:get_pos(), self.attacking:get_pos())
|
|
|
|
if distance_from_attacking >= self.minimum_follow_distance then
|
|
mobs.set_velocity(self, self.run_velocity)
|
|
mobs.set_mob_animation(self, "run")
|
|
else
|
|
mobs.set_velocity(self, 0)
|
|
mobs.set_mob_animation(self, "stand")
|
|
end
|
|
|
|
mobs.set_yaw_while_attacking(self)
|
|
|
|
--make punchy mobs jump
|
|
--check for nodes to jump over
|
|
--explosive mobs will just ride against walls for now
|
|
local node_in_front_of = mobs.jump_check(self)
|
|
|
|
if node_in_front_of == 1 then
|
|
mobs.jump(self)
|
|
end
|
|
|
|
--mobs that can climb over stuff
|
|
if self.always_climb and node_in_front_of > 0 then
|
|
mobs.climb(self)
|
|
end
|
|
|
|
|
|
--auto reset punch_timer
|
|
if not self.punch_timer then
|
|
self.punch_timer = 0
|
|
end
|
|
|
|
if self.punch_timer > 0 then
|
|
self.punch_timer = self.punch_timer - dtime
|
|
end
|
|
end
|
|
|
|
mobs.punch_attack = function(self)
|
|
|
|
self.attacking:punch(self.object, 1.0, {
|
|
full_punch_interval = 1.0,
|
|
damage_groups = {fleshy = self.damage}
|
|
}, nil)
|
|
|
|
self.punch_timer = self.punch_timer_cooloff
|
|
|
|
|
|
--knockback
|
|
local pos1 = self.object:get_pos()
|
|
pos1.y = 0
|
|
local pos2 = self.attacking:get_pos()
|
|
pos2.y = 0
|
|
local dir = vector_direction(pos1,pos2)
|
|
|
|
dir = vector_multiply(dir,3)
|
|
|
|
if self.attacking:get_velocity().y <= 1 then
|
|
dir.y = 5
|
|
end
|
|
|
|
self.attacking:add_velocity(dir)
|
|
end
|
|
|
|
|
|
|
|
|
|
--[[
|
|
______ _ _ _ _
|
|
| ___ \ (_) | | (_) |
|
|
| |_/ / __ ___ _ ___ ___| |_ _| | ___
|
|
| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \
|
|
| | | | | (_) | | __/ (__| |_| | | __/
|
|
\_| |_| \___/| |\___|\___|\__|_|_|\___|
|
|
_/ |
|
|
|__/
|
|
]]--
|
|
|
|
|
|
mobs.projectile_attack_walk = function(self,dtime)
|
|
|
|
--this needs an exception
|
|
if self.attacking == nil or not self.attacking:is_player() then
|
|
self.attacking = nil
|
|
return
|
|
end
|
|
|
|
mobs.set_yaw_while_attacking(self)
|
|
|
|
local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos())
|
|
|
|
|
|
if distance_from_attacking >= self.reach then
|
|
mobs.set_velocity(self, self.run_velocity)
|
|
mobs.set_mob_animation(self,"run")
|
|
else
|
|
mobs.set_velocity(self,0)
|
|
mobs.set_mob_animation(self,"stand")
|
|
end
|
|
|
|
--do this to not load data into other mobs
|
|
if not self.projectile_timer then
|
|
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
|
|
end
|
|
|
|
--run projectile timer
|
|
if self.projectile_timer > 0 then
|
|
self.projectile_timer = self.projectile_timer - dtime
|
|
|
|
--shoot
|
|
if self.projectile_timer <= 0 then
|
|
--reset timer
|
|
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
|
|
mobs.shoot_projectile(self)
|
|
end
|
|
end
|
|
|
|
--make shooty mobs jump
|
|
--check for nodes to jump over
|
|
--explosive mobs will just ride against walls for now
|
|
local node_in_front_of = mobs.jump_check(self)
|
|
if node_in_front_of == 1 then
|
|
mobs.jump(self)
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--[[
|
|
_ ______ _ _
|
|
| | | ___| | | |
|
|
| | | |_ | |_ _ | |
|
|
| | | _| | | | | | | |
|
|
|_| | | | | |_| | |_|
|
|
(_) \_| |_|\__, | (_)
|
|
__/ |
|
|
|___/
|
|
]]--
|
|
|
|
|
|
|
|
|
|
--[[
|
|
______ _ _ _ _
|
|
| ___ \ (_) | | (_) |
|
|
| |_/ / __ ___ _ ___ ___| |_ _| | ___
|
|
| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \
|
|
| | | | | (_) | | __/ (__| |_| | | __/
|
|
\_| |_| \___/| |\___|\___|\__|_|_|\___|
|
|
_/ |
|
|
|__/
|
|
]]--
|
|
|
|
local random_pitch_multiplier = {-1,1}
|
|
|
|
mobs.projectile_attack_fly = function(self, dtime)
|
|
|
|
--this needs an exception
|
|
if self.attacking == nil or not self.attacking:is_player() then
|
|
self.attacking = nil
|
|
return
|
|
end
|
|
|
|
--this is specifically for random ghast movement
|
|
if self.fly_random_while_attack then
|
|
|
|
--enable rotation locking
|
|
mobs.movement_rotation_lock(self)
|
|
|
|
self.walk_timer = self.walk_timer - dtime
|
|
|
|
--reset the walk timer
|
|
if self.walk_timer <= 0 then
|
|
--re-randomize the walk timer
|
|
self.walk_timer = math.random(1,6) + math.random()
|
|
--set the mob into a random direction
|
|
self.yaw = (math_random() * (math.pi * 2))
|
|
--create a truly random pitch, since there is no easy access to pitch math that I can find
|
|
self.pitch = math_random() * math.random(1,3) * random_pitch_multiplier[math_random(1,2)]
|
|
end
|
|
|
|
mobs.set_fly_velocity(self, self.run_velocity)
|
|
|
|
else
|
|
|
|
mobs.set_yaw_while_attacking(self)
|
|
|
|
local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos())
|
|
|
|
if distance_from_attacking >= self.reach then
|
|
mobs.set_pitch_while_attacking(self)
|
|
mobs.set_fly_velocity(self, self.run_velocity)
|
|
mobs.set_mob_animation(self,"run")
|
|
else
|
|
mobs.set_pitch_while_attacking(self)
|
|
mobs.set_fly_velocity(self, 0)
|
|
mobs.set_mob_animation(self,"stand")
|
|
end
|
|
end
|
|
|
|
|
|
--do this to not load data into other mobs
|
|
if not self.projectile_timer then
|
|
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
|
|
end
|
|
|
|
--run projectile timer
|
|
if self.projectile_timer > 0 then
|
|
self.projectile_timer = self.projectile_timer - dtime
|
|
|
|
--shoot
|
|
if self.projectile_timer <= 0 then
|
|
|
|
if self.fly_random_while_attack then
|
|
mobs.set_yaw_while_attacking(self)
|
|
self.walk_timer = 0
|
|
end
|
|
--reset timer
|
|
self.projectile_timer = math_random(self.projectile_cooldown_min, self.projectile_cooldown_max)
|
|
mobs.shoot_projectile(self)
|
|
end
|
|
end
|
|
end |