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,192 @@
require "/scripts/vec2.lua"
require "/scripts/util.lua"
function init()
self.fireOffset = config.getParameter("fireOffset", {0,0})
self.fireDirection = config.getParameter("fireDirection")
self.stances = config.getParameter("stances")
self.projectileType = config.getParameter("projectileType")
self.projectileParameters = config.getParameter("projectileParameters")
self.returnSpeed = config.getParameter("returnSpeed", 0)
self.returnDistance = config.getParameter("returnDistance", 1)
self.swingSpeed = {30, 60}
self.swingupTime = 1.5
self.swingupTimer = 0
self.swingRadius = 1.5
self.releaseAngle = 0.15
self.pullSpeed = 50
self.pullForce = 500
self.maxChainLength = 15
self.currentChainLength = 0
self.previousFireMode = "none"
self.ropeSegments = {}
self.ropeOffset = config.getParameter("ropeOffset", self.fireOffset)
self.aimAngle = 0
setStance("idle")
end
function update(dt, fireMode, shiftHeld)
self.stanceTimer = math.max(self.stanceTimer - dt, 0)
checkProjectile()
if self.stanceName == "idle" then
if fireMode == "primary" and self.previousFireMode ~= "primary" then
fire()
end
elseif self.stanceName == "swingup" then
if fireMode == "primary" then
self.swingupTimer = self.swingupTimer + dt
local swingSpeedRatio = math.min(1, self.swingupTimer / self.swingupTime)
world.callScriptedEntity(self.projectileId, "updateOrbit", chainSourcePosition(), self.aimDirection * util.lerp(swingSpeedRatio, self.swingSpeed[1], self.swingSpeed[2]))
elseif self.previousFireMode == "primary" then
-- local releaseAngle = activeItem.aimAngleAndDirection(0, activeItem.ownerAimPosition())
world.callScriptedEntity(self.projectileId, "requestRelease", self.aimDirection > 0 and self.releaseAngle or math.pi - self.releaseAngle)
self.currentChainLength = self.maxChainLength
end
elseif self.stanceName == "release" then
if fireMode == "primary" or world.callScriptedEntity(self.projectileId, "landed") or chainLength() > self.currentChainLength then
setStance("retrieve")
end
elseif self.stanceName == "retrieve" then
self.currentChainLength = math.min(self.currentChainLength, chainLength())
if fireMode == "primary" and mcontroller.onGround() then
mcontroller.controlModifiers({movementSuppressed=true})
world.callScriptedEntity(self.projectileId, "pullChain", chainSourcePosition(), self.pullSpeed, self.pullForce)
elseif chainLength() > self.currentChainLength + 0.1 then
local pullVector = world.distance(world.entityPosition(self.projectileId), chainSourcePosition())
local pullAngle = vec2.angle(pullVector)
mcontroller.controlApproachVelocityAlongAngle(pullAngle, world.callScriptedEntity(self.projectileId, "speed"), 5000, true)
if mcontroller.onGround() then
world.callScriptedEntity(self.projectileId, "pullChain", chainSourcePosition(), 3, 500)
end
end
end
self.previousFireMode = fireMode
updateAim(self.stance.allowRotate, self.stance.allowFlip)
buildRopeSegments()
end
function uninit()
if self.projectileId and world.entityExists(self.projectileId) then
world.callScriptedEntity(self.projectileId, "kill")
end
end
function fire()
self.released = false
self.projectileParameters.orbitDistance = self.swingRadius
self.projectileParameters.orbitSpeed = self.aimDirection > 0 and self.swingSpeed[1] or -self.swingSpeed[1]
self.projectileParameters.pickupDistance = 2.0
local projectileId = world.spawnProjectile(
self.projectileType,
firePosition(),
activeItem.ownerEntityId(),
self.fireDirection,
false,
self.projectileParameters
)
if projectileId then
self.projectileId = projectileId
setStance("swingup")
self.swingupTimer = 0
animator.playSound("fire")
end
end
function release()
setStance("release")
world.callScriptedEntity(self.projectileId, "release")
end
function setStance(stanceName)
self.stanceName = stanceName
self.stance = self.stances[stanceName]
self.stanceTimer = self.stance.duration or 0
animator.setAnimationState("weapon", stanceName == "idle" and "full" or "empty")
animator.rotateGroup("weapon", util.toRadians(self.stance.weaponRotation))
updateAim(self.stance.allowRotate, self.stance.allowFlip)
end
function resetChain()
if self.projectileId then
if world.entityExists(self.projectileId) then
world.callScriptedEntity(self.projectileId, "kill")
end
self.projectileId = nil
end
setStance("idle")
end
function checkProjectile()
if self.projectileId then
if world.entityExists(self.projectileId) then
if not self.released then
self.released = world.callScriptedEntity(self.projectileId, "released")
if self.released then
setStance("release")
end
end
else
resetChain()
end
end
end
function buildRopeSegments()
if self.projectileId and world.entityExists(self.projectileId) then
local position = mcontroller.position()
local handPosition = vec2.add(position, activeItem.handPosition(self.ropeOffset))
activeItem.setScriptedAnimationParameter("p1", handPosition)
activeItem.setScriptedAnimationParameter("p2", world.entityPosition(self.projectileId))
else
activeItem.setScriptedAnimationParameter("p1", nil)
activeItem.setScriptedAnimationParameter("p2", nil)
end
end
function updateAim(allowRotate, allowFlip)
local aimAngle, aimDirection = activeItem.aimAngleAndDirection(self.fireOffset[2], activeItem.ownerAimPosition())
if allowRotate then
self.aimAngle = aimAngle
end
aimAngle = (self.aimAngle or 0) + util.toRadians(self.stance.armRotation)
activeItem.setArmAngle(aimAngle)
if allowFlip then
self.aimDirection = aimDirection
end
activeItem.setFacingDirection((self.aimDirection or 0))
end
function aimVector()
local aimVector = vec2.rotate({1, 0}, self.aimAngle)
aimVector[1] = aimVector[1] * self.aimDirection
return aimVector
end
function firePosition()
local fireOffset = {self.fireOffset[1] * self.aimDirection, self.fireOffset[2]}
return vec2.add(mcontroller.position(), activeItem.handPosition(fireOffset))
end
function chainSourcePosition()
return vec2.add(mcontroller.position(), activeItem.handPosition(self.ropeOffset))
end
function chainLength()
if self.projectileId and world.entityExists(self.projectileId) then
return world.magnitude(world.entityPosition(self.projectileId), chainSourcePosition())
else
return 0
end
end