2024-03-23 06:54:06 +01:00

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