Starbound/attic/npcs/chesttrapper/behavior.lua
2025-03-21 22:23:30 +11:00

205 lines
5.4 KiB
Lua

function init()
self.dead = false
self.state = stateMachine.create({
"aggroState",
"spinAttack",
"bombAttack",
"spawnAttack",
"explodeState"
})
self.state.shuffleStates()
entity.setDeathParticleBurst("deathPoof")
end
--------------------------------------------------------------------------------
function update(dt)
if util.trackTarget(entity.configParameter("noticeDistance")) then
attack(self.targetId)
end
entity.setAggressive(self.targetId ~= nil)
entity.setDamageOnTouch(self.targetId ~= nil)
if not self.state.update(dt) then
entity.setAnimationState("movement", "idle")
end
end
--------------------------------------------------------------------------------
function damage(args)
if self.targetId == nil then
attack(args.sourceId)
end
end
--------------------------------------------------------------------------------
function shouldDie()
return entity.health() <= 0 or self.dead
end
--------------------------------------------------------------------------------
function attack(targetId)
local stateName = self.state.stateDesc()
if not string.find(stateName, 'Attack$') and stateName ~= "explodeState" then
if self.state.pickState({ targetId = targetId }) then
self.targetId = targetId
end
end
end
--------------------------------------------------------------------------------
aggroState = {}
function aggroState.enterWith(params)
if params.targetId == nil then return nil end
entity.setAnimationState("movement", "aggro")
return { timer = entity.configParameter("aggroTime") }
end
function aggroState.update(dt, stateData)
mcontroller.controlFly({ 0, entity.configParameter("aggroMoveSpeed") })
stateData.timer = stateData.timer - dt
return stateData.timer <= 0
end
function aggroState.leavingState(stateData)
self.state.pickState({ attack = true })
end
--------------------------------------------------------------------------------
spinAttack = {}
function spinAttack.enterWith(params)
if self.targetId == nil then return true end
if not params.attack then return nil end
entity.setAnimationState("movement", "spin")
return {}
end
function spinAttack.update(dt, stateData)
if self.targetId == nil then return true end
if stateData.targetPosition == nil then
stateData.targetPosition = self.targetPosition
end
local toTarget = world.distance(stateData.targetPosition, mcontroller.position())
if world.magnitude(toTarget) <= 1.0 then
return true
else
mcontroller.controlFly(vec2.mul(vec2.norm(toTarget), mcontroller.baseParameters().flySpeed))
end
return false
end
function spinAttack.leavingState(stateData)
self.state.pickState({ explode = true })
end
--------------------------------------------------------------------------------
bombAttack = {}
function bombAttack.enterWith(params)
if self.targetId == nil then return true end
if not params.attack then return nil end
return {
timer = 0,
totalTime = entity.randomizeParameterRange("bombAttackTimeRange"),
direction = util.randomDirection()
}
end
function bombAttack.enteringState(stateData)
entity.setFireDirection({0, 0}, {1, 0})
-- entity.startFiring("bomb")
end
function bombAttack.update(dt, stateData)
if self.targetId == nil then return true end
mcontroller.controlFly({ 0, 0 })
local ratio = stateData.timer / stateData.totalTime
local angle = ratio * math.pi
local direction = {
math.cos(angle) * stateData.direction,
math.sin(angle)
}
direction = vec2.mul(direction, 2.0)
-- entity.setFireDirection(direction, direction)
stateData.timer = stateData.timer + dt
return stateData.timer >= stateData.totalTime
end
function bombAttack.leavingState(stateData)
-- entity.stopFiring()
self.state.pickState({ explode = true })
end
--------------------------------------------------------------------------------
spawnAttack = {}
function spawnAttack.enterWith(params)
if self.targetId == nil then return true end
if not params.attack then return nil end
return { timer = entity.configParameter("spawnAttackWaitTime") }
end
function spawnAttack.enteringState(stateData)
entity.burstParticleEmitter("deathPoof")
local initialSpeed = entity.configParameter("spawnAttackInitialSpeed")
for _, offset in pairs(entity.configParameter("spawnAttackOffsets")) do
local entityId = world.spawnMonster("glitchspider", entity.toAbsolutePosition(offset))
world.callScriptedEntity(entityId, "setSpawnVelocity", vec2.mul(offset, initialSpeed))
end
end
function spawnAttack.update(dt, stateData)
if self.targetId == nil then return nil end
mcontroller.controlFly({ 0, 0 })
stateData.timer = stateData.timer - dt
return stateData.timer <= 0
end
function spawnAttack.leavingState(stateData)
self.state.pickState({ explode = true })
end
--------------------------------------------------------------------------------
explodeState = {}
function explodeState.enterWith(params)
if not params.explode or self.dead then return nil end
return { timer = entity.configParameter("explodeTime") }
end
function explodeState.enteringState(stateData)
-- entity.startFiring("deathexplosion")
-- entity.setFireDirection({0, 0}, {1, 0})
end
function explodeState.update(dt, stateData)
mcontroller.controlFly({ 0, 0 })
stateData.timer = stateData.timer - dt
return stateData.timer <= 0
end
function explodeState.leavingState(stateData)
-- entity.stopFiring()
self.dead = true
end