This commit is contained in:
Aria 2025-03-21 22:23:30 +11:00
commit 9c94d113d3
Signed by untrusted user who does not match committer: aria
GPG key ID: 19AB7AA462B8AB3B
10260 changed files with 1237388 additions and 0 deletions

View file

@ -0,0 +1,193 @@
--------------------------------------------------------------------------------
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

View file

@ -0,0 +1,11 @@
{
"frameGrid" : {
"size" : [18, 16],
"dimensions" : [8, 2],
"names" : [
[ null, "idle.1", "idle.2", "idle.3", "idle.4", "idle.5", "idle.6", "null" ],
[ null, "jump.1", "jump.2", "jump.3", null, "fall.1", "fall.2", "fall.3" ]
]
}
}

View file

@ -0,0 +1,245 @@
{
"animatedParts" : {
"stateTypes" : {
"movement" : {
"priority" : 0,
"default" : "idle",
"states" : {
"idle" : {
"frames" : 6,
"mode" : "loop"
},
"jump" : {
"frames" : 3,
"mode" : "end"
},
"fall" : {
"frames" : 3,
"mode" : "end"
}
}
}
},
"parts" : {
"body" : {
"partStates" : {
"movement" : {
"idle" : {
"properties" : {
"image" : "<partImage>:idle.<frame>"
}
},
"jump" : {
"properties" : {
"image" : "<partImage>:jump.<frame>"
}
},
"fall" : {
"properties" : {
"image" : "<partImage>:fall.<frame>"
}
}
}
}
}
}
},
"particleEmitters" : {
"deathPoof" : {
"particles" : [
{
"particle" : {
"type" : "animated",
"animation" : "/animations/puff2c/puff2c.animation",
"size" : 1,
"angularVelocity" : 35,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [0, 0],
"finalVelocity" : [0, 0],
"approach" : [1, 1],
"timeToLive" : 0.4,
"layer" : "middle"
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz1/fizz1.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [-8, 8],
"finalVelocity" : [-3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [-4, 2],
"finalVelocity" : [-3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz1/fizz1.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [8, 8],
"finalVelocity" : [3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [4, 2],
"finalVelocity" : [3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz2/fizz2.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [-8, 8],
"finalVelocity" : [-3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [-4, 2],
"finalVelocity" : [-3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz2/fizz2.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [8, 8],
"finalVelocity" : [3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [4, 2],
"finalVelocity" : [3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz3/fizz3.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [-8, 8],
"finalVelocity" : [-3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [-4, 2],
"finalVelocity" : [-3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz3/fizz3.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [8, 8],
"finalVelocity" : [3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [4, 2],
"finalVelocity" : [3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz4/fizz4.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [-8, 8],
"finalVelocity" : [-3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [-4, 2],
"finalVelocity" : [-3, -4]
}
}
},
{
"particle" : {
"type" : "animated",
"animation" : "/animations/fizz4/fizz4.animation",
"size" : 1,
"angularVelocity" : 20,
"fade" : 1,
"destructionTime" : 7,
"position" : [0, 0],
"initialVelocity" : [8, 8],
"finalVelocity" : [3, -4],
"approach" : [15, 15],
"timeToLive" : 3.45,
"layer" : "middle",
"variance" : {
"initialVelocity" : [4, 2],
"finalVelocity" : [3, -4]
}
}
}
]
}
},
"effects" : {
"blink" : {
"type" : "flash",
"time" : 0.25,
"directives" : "fade=ffffff;0.5"
}
},
"sounds" : {
"turnHostile" : [ ],
"deathPuff" : [ "/sfx/npc/enemydeathpuff.ogg" ]
}
}

View file

@ -0,0 +1,9 @@
{
"name" : "body",
"category" : "heckblob",
"type" : "body",
"frames" : {
"body" : "heckblob.png"
}
}

View file

@ -0,0 +1,120 @@
{
"type" : "heckblob",
"categories" : [ "heckblob" ],
"parts" : [ "body" ],
"animation" : "heckblob.animation",
"reversed" : true,
"dropPools" : [ "basicMonsterTreasure" ],
"baseParameters" : {
"scripts" : [
"/monsters/capturepod.lua",
"/monsters/dungeon/heckblob/behavior.lua",
"/scripts/sensors.lua",
"/scripts/stateMachine.lua",
"/scripts/util.lua",
"/scripts/vec2.lua"
],
"metaBoundBox" : [-1.0, -1.0, 1.0, 1.0],
"scale" : 1.0,
"movementSettings" : {
"collisionPoly" : [ [-1.0, -1.0], [1.0, -1.0], [1.0, 1.0], [-1.0, 1.0] ],
"mass" : 1.0,
"walkSpeed" : 3,
"runSpeed" : 6,
"jumpSpeed" : 2,
"flySpeed" : 15,
"airFriction" : 0.5,
"airForce" : 5.0,
"jumpControlForce" : 5
},
"bodyMaterialKind" : "organic",
"knockoutTime" : 0.1,
"knockoutEffect" : "blink",
"knockoutAnimationStates" : {
"movement" : "idle"
},
"deathParticles" : "deathPoof",
"touchDamage" : {
"poly" : [ [-1.0, -1.0], [1.0, -1.0], [1.0, 1.0], [-1.0, 1.0] ],
"damage" : 12,
"teamType" : "enemy",
"damageSourceKind" : "lash",
"statusEffects" : [ ]
},
"statusSettings" : {
"statusProperties" : {
"targetMaterialKind" : "organic"
},
"appliesEnvironmentStatusEffects" : false,
"minimumLiquidStatusEffectPercentage" : 0.1,
"primaryScriptSources" : [
"/stats/monster_primary.lua"
],
"primaryScriptDelta" : 5,
"stats" : {
"knockbackStunTime" : {
"baseValue" : 0.25
},
"knockbackThreshold" : {
"baseValue" : 10
},
"maxHealth" : {
"baseValue" : 2
},
"protection" : {
"baseValue" : 1.0
},
"healthRegen" : {
"baseValue" : 0.0
}
},
"resources" : {
"stunned" : {
"deltaValue" : -1.0,
"initialValue" : 0.0
},
"health" : {
"maxStat" : "maxHealth",
"deltaStat" : "healthRegen",
"defaultPercentage" : 100
}
}
},
"mouthOffset" : [0, 0],
"feetOffset" : [0, -8],
"blockedSensors" : [ [1.25, 0.0] ],
"moveTimeRange" : [1.0, 2.0],
"moveCooldownTimeRange" : [5.0, 10.0],
"largeJumpYThreshold" : 2.0,
"largeHumpHoldTime" : 5,
"noticeDistance" : 30,
"attackSearchTime" : 10,
"poSize" : "medium",
"spawnVelocity" : [2, 30],
"captureHealthFraction" : 0.5
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B