164 lines
5.3 KiB
Lua
164 lines
5.3 KiB
Lua
rp_mobs_mobs.microtasks.dogfight = function(attack_range, attack_toolcaps, attack_time)
|
|
return rp_mobs.create_microtask({
|
|
label = "dogfight",
|
|
start_animation = "punch",
|
|
on_start = function(self, mob)
|
|
self.statedata.attack_target = mob._temp_custom_state.angry_at
|
|
-- For attack timer; initialize at attack_time + 1 to guarantee an instant attack
|
|
self.statedata.attack_timer = attack_time + 1
|
|
-- Time of last punch for punch() function
|
|
self.statedata.last_punch = nil
|
|
end,
|
|
on_step = function(self, mob, dtime)
|
|
if self.statedata.last_punch then
|
|
self.statedata.last_punch = self.statedata.last_punch + dtime
|
|
end
|
|
if not self.statedata.attack_target then
|
|
return
|
|
elseif self.statedata.attack_target:get_hp() == 0 then
|
|
return
|
|
end
|
|
local mpos = mob.object:get_pos()
|
|
local tpos = self.statedata.attack_target:get_pos()
|
|
local mpos_h = table.copy(mpos)
|
|
local tpos_h = table.copy(tpos)
|
|
mpos_h.y = 0
|
|
tpos_h.y = 0
|
|
local dir = vector.direction(mpos_h, tpos_h)
|
|
local yaw = minetest.dir_to_yaw(dir)
|
|
mob.object:set_yaw(yaw)
|
|
if not tpos then
|
|
return
|
|
end
|
|
local dist = vector.distance(mpos, tpos)
|
|
if dist <= attack_range then
|
|
self.statedata.attack_timer = self.statedata.attack_timer + dtime
|
|
if self.statedata.attack_timer > attack_time then
|
|
local time_from_last_punch = self.statedata.last_punch or 1000000
|
|
local dir = vector.direction(mpos, tpos)
|
|
rp_mobs.default_mob_sound(mob, "attack")
|
|
self.statedata.attack_target:punch(mob.object, time_from_last_punch, attack_toolcaps, dir)
|
|
self.statedata.attack_timer = 0
|
|
end
|
|
else
|
|
self.statedata.attack_timer = 0
|
|
end
|
|
end,
|
|
is_finished = function(self, mob)
|
|
if self.statedata.attack_target == nil then
|
|
return true
|
|
elseif self.statedata.attack_target:get_hp() == 0 then
|
|
return true
|
|
elseif self.statedata.attack_target._dying then
|
|
return true
|
|
else
|
|
local mpos = mob.object:get_pos()
|
|
local tpos = self.statedata.attack_target:get_pos()
|
|
if not tpos then
|
|
return true
|
|
end
|
|
local dist = vector.distance(mpos, tpos)
|
|
if dist > attack_range then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end,
|
|
})
|
|
end
|
|
|
|
rp_mobs_mobs.create_dogfight_decider = function(attack_range, attack_toolcaps, attack_time)
|
|
return function (task_queue, mob)
|
|
local mt_dogfight = rp_mobs_mobs.microtasks.dogfight
|
|
local task = rp_mobs.create_task({label="dogfight"})
|
|
rp_mobs.add_microtask_to_task(mob, mt_dogfight, task)
|
|
rp_mobs.add_task_to_task_queue(task_queue, task)
|
|
end
|
|
end
|
|
|
|
rp_mobs_mobs.create_player_angry_decider = function()
|
|
return function (task_queue, mob)
|
|
local mt = rp_mobs.create_microtask({
|
|
label = "mark players as attack target",
|
|
on_step = function(self, mob, dtime)
|
|
-- Children are never angry
|
|
if mob._child then
|
|
return
|
|
end
|
|
-- Closest player becomes target
|
|
if mob._temp_custom_state.closest_player then
|
|
-- Don't change attack target if already set
|
|
if not mob._temp_custom_state.angry_at then
|
|
local player = mob._temp_custom_state.closest_player
|
|
if player and player:is_player() and player:get_hp() > 0 then
|
|
mob._temp_custom_state.angry_at = player
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
else
|
|
mob._temp_custom_state.angry_at = nil
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
end
|
|
end
|
|
else
|
|
mob._temp_custom_state.angry_at = nil
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
end
|
|
end,
|
|
is_finished = function()
|
|
return false
|
|
end,
|
|
})
|
|
local task = rp_mobs.create_task({label="mark players as attack target"})
|
|
rp_mobs.add_microtask_to_task(mob, mt, task)
|
|
rp_mobs.add_task_to_task_queue(task_queue, task)
|
|
end
|
|
end
|
|
|
|
rp_mobs_mobs.create_angry_cooldown_decider = function(range, cooldown_time)
|
|
return function (task_queue, mob)
|
|
local mt = rp_mobs.create_microtask({
|
|
label = "stop being angry at target when out of range for a time",
|
|
on_start = function(self, mob)
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
end,
|
|
on_step = function(self, mob, dtime)
|
|
if mob._temp_custom_state.angry_at then
|
|
local mobpos = mob.object:get_pos()
|
|
local targetpos = mob._temp_custom_state.angry_at:get_pos()
|
|
if not targetpos then
|
|
mob._temp_custom_state.angry_at = nil
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
return
|
|
end
|
|
local dist = vector.distance(mobpos, targetpos)
|
|
if dist > range then
|
|
mob._temp_custom_state.angry_at_timer = mob._temp_custom_state.angry_at_timer + dtime
|
|
if mob._temp_custom_state.angry_at_timer > cooldown_time then
|
|
mob._temp_custom_state.angry_at = nil
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
end
|
|
else
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
end
|
|
end
|
|
end,
|
|
is_finished = function()
|
|
return false
|
|
end,
|
|
})
|
|
local task = rp_mobs.create_task({label="anger cooldown"})
|
|
rp_mobs.add_microtask_to_task(mob, mt, task)
|
|
rp_mobs.add_task_to_task_queue(task_queue, task)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
rp_mobs_mobs.on_punch_make_hostile = function(mob, puncher, time_from_last_punch, tool_capabilities, dir, damage, ...)
|
|
-- Children are never angry
|
|
if not mob._child and puncher and puncher:is_player() then
|
|
mob._temp_custom_state.angry_at = puncher
|
|
mob._temp_custom_state.angry_at_timer = 0
|
|
end
|
|
return rp_mobs.on_punch_default(mob, puncher, time_from_last_punch, tool_capabilities, dir, damage, ...)
|
|
end
|