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,205 @@
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

View file

@ -0,0 +1,246 @@
{
"animatedParts" : {
"stateTypes" : {
"movement" : {
"priority" : 0,
"default" : "idle",
"states" : {
"idle" : {
"frames" : 1
},
"aggro" : {
"frames" : 3,
"cycle" : 0.25,
"mode" : "end"
},
"spin" : {
"frames" : 8,
"cycle" : 0.5,
"mode" : "loop"
}
}
}
},
"parts" : {
"chest" : {
"partStates" : {
"movement" : {
"idle" : {
"properties" : {
"image" : "<partImage>:aggro.1"
}
},
"aggro" : {
"properties" : {
"image" : "<partImage>:aggro.<frame>"
}
},
"spin" : {
"properties" : {
"image" : "<partImage>:spin.<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,112 @@
{
"type" : "chesttrapper",
"categories" : [ "chesttrapper" ],
"parts" : [ "chest" ],
"animation" : "chesttrapper.animation",
"dropPools" : [ "noMeatMonsterTreasure" ],
"baseParameters" : {
"scripts" : [
"/monsters/dungeon/chesttrapper/behavior.lua",
"/scripts/stateMachine.lua",
"/scripts/util.lua",
"/scripts/vec2.lua"
],
"metaBoundBox" : [-1.0, -1.125, 1.0, 1.0],
"scale" : 1.0,
"movementSettings" : {
"collisionPoly" : [ [-1.0, -1.125], [1.0, -1.125], [1.0, 1.0], [-1.0, 1.0] ],
"mass" : 1.0,
"walkSpeed" : 3,
"runSpeed" : 6,
"jumpSpeed" : 5,
"flySpeed" : 25,
"airFriction" : 0.1,
"airForce" : 100.0
},
"bodyMaterialKind" : "organic",
"knockoutTime" : 0.1,
"knockoutEffect" : "blink",
"deathParticles" : "deathPoof",
"touchDamage" : {
"poly" : [ [-1.0, -1.125], [1.0, -1.125], [1.0, 1.0], [-1.0, 1.0] ],
"damage" : 20,
"teamType" : "enemy",
"damageSourceKind" : "bite",
"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" : 12
},
"protection" : {
"baseValue" : 1.0
},
"healthRegen" : {
"baseValue" : 0.0
},
"poisonImmunity" : {
"baseValue" : 1.0
}
},
"resources" : {
"stunned" : {
"deltaValue" : -1.0,
"initialValue" : 0.0
},
"health" : {
"maxStat" : "maxHealth",
"deltaStat" : "healthRegen",
"defaultPercentage" : 100
}
}
},
"mouthOffset" : [0, 0],
"feetOffset" : [0, -8],
"noticeDistance" : 5,
"aggroTime" : 0.5,
"aggroMoveSpeed" : 7.5,
"bombAttackTimeRange" : [0.25, 0.5],
"explodeTime" : 0.5,
"spawnAttackWaitTime" : 0.4,
"spawnAttackOffsets" : [ [-1, 1], [0, 1], [1, 1] ],
"spawnAttackInitialSpeed" : 16
}
}

View file

@ -0,0 +1,11 @@
{
"frameGrid" : {
"size" : [18, 18],
"dimensions" : [8, 2],
"names" : [
[ "aggro.1", "aggro.2", "aggro.3", null, null, null, null, null ],
[ "spin.1", "spin.2", "spin.3", "spin.4", "spin.5", "spin.6", "spin.7", "spin.8" ]
]
}
}

View file

@ -0,0 +1,9 @@
{
"name" : "medievalchest",
"category" : "chesttrapper",
"type" : "chest",
"frames" : {
"chest" : "medievalchest.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,9 @@
{
"name" : "royalchest",
"category" : "chesttrapper",
"type" : "chest",
"frames" : {
"chest" : "royalchest.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB