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,223 @@
require "/scripts/util.lua"
require "/items/active/weapons/weapon.lua"
-- whip primary attack plus swinging from torches like a boss
SuperWhipCrack = WeaponAbility:new()
function SuperWhipCrack:init()
self.damageConfig.baseDamage = self.chainDps * self.fireTime
self.weapon:setStance(self.stances.idle)
animator.setAnimationState("attack", "idle")
activeItem.setScriptedAnimationParameter("chains", nil)
self.cooldownTimer = self:cooldownTime()
self.weapon.onLeaveAbility = function()
self.weapon:setStance(self.stances.idle)
end
self.projectileConfig = self.projectileConfig or {}
self.chain = config.getParameter("chain")
self.anchorObjects = config.getParameter("anchorObjects", {"torch"})
self.anchor = nil
self.snapDistance = config.getParameter("snapDistance", 3.0)
end
-- Ticks on every update regardless if this is the active ability
function SuperWhipCrack:update(dt, fireMode, shiftHeld)
WeaponAbility.update(self, dt, fireMode, shiftHeld)
self.cooldownTimer = math.max(0, self.cooldownTimer - self.dt)
if self.fireMode == "primary" and self:canStartAttack() then
self:setState(self.windup)
self.fireHeld = true
elseif self.fireMode ~= "primary" and self.fireHeld then
self.fireHeld = false
self:disconnect()
end
end
function SuperWhipCrack:canStartAttack()
return not self.weapon.currentAbility and self.cooldownTimer == 0
end
-- State: windup
function SuperWhipCrack:windup()
self.weapon:setStance(self.stances.windup)
animator.setAnimationState("attack", "windup")
util.wait(self.stances.windup.duration)
self:setState(self.extend)
end
-- State: extend
function SuperWhipCrack:extend()
self.weapon:setStance(self.stances.extend)
animator.setAnimationState("attack", "extend")
animator.playSound("swing")
util.wait(self.stances.extend.duration)
if self.fireHeld then
self.anchor = self:findAnchor()
end
if self.anchor then
animator.setAnimationState("attack", "fire")
self:setState(self.swing)
else
animator.setAnimationState("attack", "fire")
self:setState(self.fire)
end
end
-- State: swing
function SuperWhipCrack:swing()
self.weapon:setStance(self.stances.swing)
self.weapon:updateAim()
self.cooldownTimer = self:cooldownTime()
while self.anchor do
if world.entityExists(self.anchor) then
local chainEndPos = vec2.add(world.entityPosition(self.anchor), {0.5, 0.5})
local chainStartPos = vec2.add(mcontroller.position(), activeItem.handPosition(self.chain.startOffset))
if not world.lineCollision(chainStartPos, chainEndPos) then
local aimVector = world.distance(chainEndPos, chainStartPos)
local swingAngle = vec2.angle(aimVector)
if not mcontroller.onGround() then
mcontroller.controlApproachVelocityAlongAngle(swingAngle, 0, 1000, true)
else
mcontroller.controlModifiers({movementSuppressed = true})
end
if self.weapon.aimDirection < 0 then
self.weapon.aimAngle = vec2.angle({-aimVector[1], aimVector[2]})
else
self.weapon.aimAngle = swingAngle
end
self.weapon:updateAim()
self.chain.endPosition = chainEndPos
activeItem.setScriptedAnimationParameter("chains", {self.chain})
coroutine.yield()
else
self:disconnect()
end
else
self:disconnect()
end
end
end
function SuperWhipCrack:disconnect()
self.anchor = nil
animator.setAnimationState("attack", "idle")
self.chain.endPosition = nil
activeItem.setScriptedAnimationParameter("chains", nil)
end
-- State: fire
function SuperWhipCrack:fire()
self.weapon:setStance(self.stances.fire)
self.weapon:updateAim()
local chainStartPos = vec2.add(mcontroller.position(), activeItem.handPosition(self.chain.startOffset))
local chainLength = world.magnitude(chainStartPos, activeItem.ownerAimPosition())
chainLength = math.min(self.chain.length[2], math.max(self.chain.length[1], chainLength))
self.chain.endOffset = vec2.add(self.chain.startOffset, {chainLength, 0})
local collidePoint = world.lineCollision(chainStartPos, vec2.add(mcontroller.position(), activeItem.handPosition(self.chain.endOffset)))
if collidePoint then
chainLength = world.magnitude(chainStartPos, collidePoint) - 0.25
if chainLength < self.chain.length[1] then
animator.setAnimationState("attack", "idle")
return
else
self.chain.endOffset = vec2.add(self.chain.startOffset, {chainLength, 0})
end
end
local chainEndPos = vec2.add(mcontroller.position(), activeItem.handPosition(self.chain.endOffset))
activeItem.setScriptedAnimationParameter("chains", {self.chain})
animator.resetTransformationGroup("endpoint")
animator.translateTransformationGroup("endpoint", self.chain.endOffset)
animator.burstParticleEmitter("crack")
animator.playSound("crack")
self.projectileConfig.power = self:crackDamage()
self.projectileConfig.powerMultiplier = activeItem.ownerPowerMultiplier()
local projectileAngle = vec2.withAngle(self.weapon.aimAngle)
if self.weapon.aimDirection < 0 then projectileAngle[1] = -projectileAngle[1] end
world.spawnProjectile(
self.projectileType,
chainEndPos,
activeItem.ownerEntityId(),
projectileAngle,
false,
self.projectileConfig
)
util.wait(self.stances.fire.duration, function()
if self.damageConfig.baseDamage > 0 then
self.weapon:setDamage(self.damageConfig, {self.chain.startOffset, {self.chain.endOffset[1] + 0.75, self.chain.endOffset[2]}}, self.fireTime)
end
end)
animator.setAnimationState("attack", "idle")
activeItem.setScriptedAnimationParameter("chains", nil)
self.cooldownTimer = self:cooldownTime()
end
function SuperWhipCrack:cooldownTime()
return self.fireTime - (self.stances.windup.duration + self.stances.extend.duration + self.stances.fire.duration)
end
function SuperWhipCrack:uninit(unloaded)
self.weapon:setDamage()
activeItem.setScriptedAnimationParameter("chains", nil)
end
function SuperWhipCrack:chainDamage()
return (self.chainDps * self.fireTime) * config.getParameter("damageLevelMultiplier")
end
function SuperWhipCrack:crackDamage()
return (self.crackDps * self.fireTime) * config.getParameter("damageLevelMultiplier")
end
function SuperWhipCrack:findAnchor()
local objectsNearCursor = world.objectQuery(activeItem.ownerAimPosition(), 5, {boundMode = "metaboundbox", order = "nearest"})
if #objectsNearCursor > 0 then
local objectName = world.entityName(objectsNearCursor[1])
local anchorValid = false
for _, anchorObject in pairs(self.anchorObjects) do
if anchorObject == objectName then
anchorValid = true
break
end
end
if anchorValid then
local pos = vec2.add(world.entityPosition(objectsNearCursor[1]), {0.5, 0.5})
local distToCursor = world.magnitude(pos, activeItem.ownerAimPosition())
local distToHand = world.magnitude(pos, vec2.add(mcontroller.position(), activeItem.handPosition(self.chain.startOffset)))
if distToCursor <= self.snapDistance and distToHand <= self.chain.length[2] and distToHand >= self.chain.length[1] then
return objectsNearCursor[1]
end
end
end
end