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

193 lines
5 KiB
Lua

--------------------------------------------------------------------------------
function init()
self.sensors = sensors.create()
capturepod.onInit()
self.state = stateMachine.create({
"attackState",
"moveState",
"captiveState"
})
self.state.leavingState = function(stateName)
entity.setAnimationState("movement", "idle")
end
self.jumpHoldTime = 0;
entity.setAggressive(true)
entity.setDamageOnTouch(true)
entity.setDeathParticleBurst("deathPoof")
entity.setAnimationState("movement", "idle")
end
--------------------------------------------------------------------------------
function update(dt)
util.trackTarget(entity.configParameter("noticeDistance"))
if self.targetId ~= nil and not attacking() then
self.state.pickState(self.targetId)
end
self.state.update(dt)
self.sensors.clear()
-- Update animation
if mcontroller.onGround() then
entity.setAnimationState("movement", "idle")
else
local velocity = mcontroller.velocity()
if velocity[2] < 0 then
entity.setAnimationState("movement", "fall")
else
entity.setAnimationState("movement", "jump")
end
end
end
--------------------------------------------------------------------------------
function damage(args)
capturepod.onDamage(args)
end
--------------------------------------------------------------------------------
function setSpawnDirection(direction)
local spawnVelocity = entity.configParameter("spawnVelocity")
mcontroller.setVelocity({ spawnVelocity[1] * direction, spawnVelocity[2] })
end
--------------------------------------------------------------------------------
function poSize()
return entity.configParameter("poSize")
end
--------------------------------------------------------------------------------
function attacking()
return self.state.stateDesc() == "attackState"
end
--------------------------------------------------------------------------------
function move(delta, run)
if not mcontroller.onGround() and self.jumpHoldTime > 0 then
mcontroller.controlHoldJump()
self.jumpHoldTime = math.max(0, self.jumpHoldTime - dt)
end
if mcontroller.onGround() then
if delta[2] > entity.configParameter("largeJumpYThreshold") then
self.jumpHoldTime = entity.configParameter("largeHumpHoldTime")
else
self.jumpHoldTime = 0
end
end
mcontroller.controlMove(delta[1], true)
end
--------------------------------------------------------------------------------
moveState = {}
function moveState.enter()
if capturepod.isCaptive() then return nil end
return {
timer = entity.randomizeParameterRange("moveTimeRange"),
direction = util.toDirection(math.random(100) - 50)
}
end
function moveState.update(dt, stateData)
if self.sensors.blockedSensors.collision.any(true) then
stateData.direction = -stateData.direction
end
move({ stateData.direction, 0 }, false)
stateData.timer = stateData.timer - dt
if stateData.timer <= 0 then
return true, entity.randomizeParameterRange("moveCooldownTimeRange")
end
return false
end
--------------------------------------------------------------------------------
attackState = {}
function attackState.enterWith(targetId)
return { timer = 0 }
end
function attackState.update(dt, stateData)
if self.targetPosition == nil then return true end
if self.targetId == nil then
stateData.timer = stateData.timer + dt
if stateData.timer > entity.configParameter("attackSearchTime") then
return true
end
end
local toTarget = world.distance(self.targetPosition, mcontroller.position())
move(toTarget, true)
return false
end
--------------------------------------------------------------------------------
captiveState = {
closeDistance = 4,
runDistance = 12,
}
function captiveState.enter()
if not capturepod.isCaptive() or self.targetId ~= nil then return nil end
return { running = false }
end
function captiveState.update(dt, stateData)
-- Translate owner uuid to entity id
if self.ownerEntityId ~= nil then
if not world.entityExists(self.ownerEntityId) then
self.ownerEntityId = nil
end
end
if self.ownerEntityId == nil then
local playerIds = world.entityQuery(mcontroller.position(), 50, {includedTypes = {"player"}})
for _, playerId in pairs(playerIds) do
if world.entityUniqueId(playerId) == storage.ownerUuid then
self.ownerEntityId = playerId
break
end
end
end
-- Owner is nowhere around
if self.ownerEntityId == nil then
return false
end
local ownerPosition = world.entityPosition(self.ownerEntityId)
local toOwner = world.distance(ownerPosition, mcontroller.position())
local distance = math.abs(toOwner[1])
local movement
if distance < captiveState.closeDistance then
stateData.running = false
movement = 0
elseif toOwner[1] < 0 then
movement = -1
elseif toOwner[1] > 0 then
movement = 1
end
if distance > captiveState.runDistance then
stateData.running = true
end
move({ movement, toOwner[2] }, stateData.running)
return false
end