v1.4.4
After Width: | Height: | Size: 262 B |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"animationCustom" : {
|
||||
"animatedParts" : { "parts" : {
|
||||
"bayonet" : {
|
||||
"properties" : {
|
||||
"zLevel" : -1,
|
||||
"centered" : true,
|
||||
"offset" : [2.75, -0.25],
|
||||
"image" : "/items/active/weapons/ranged/abilities/generic/bayonet.png"
|
||||
}
|
||||
}
|
||||
}},
|
||||
"sounds" : {
|
||||
"stab" : [ "/sfx/melee/swing_dagger.ogg" ]
|
||||
}
|
||||
},
|
||||
|
||||
"ability" : {
|
||||
"type" : "bayonet",
|
||||
"scripts" : []
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
function setupAbility(altAbilityConfig)
|
||||
local knockbackAttack = altAbilityConfig
|
||||
|
||||
function knockbackAttack.init()
|
||||
-- sb.logInfo("Initializing knockbackAttack")
|
||||
end
|
||||
|
||||
function knockbackAttack.update(dt, fireMode, shiftHeld)
|
||||
if fireMode == "alt"
|
||||
and storage.fireTimer == 0
|
||||
and not world.pointTileCollision(firePosition())
|
||||
and status.overConsumeResource("energy", knockbackAttack.energyCost) then
|
||||
|
||||
storage.fireTimer = knockbackAttack.cooldown -- TODO: maybe use separate cooldown?
|
||||
-- TODO: appropriate projectile
|
||||
animator.setAnimationState("firing", "fire", true)
|
||||
animator.setPartTag("muzzleFlash", "variant", math.random(1, 3))
|
||||
animator.playSound("knockback")
|
||||
animator.burstParticleEmitter("knockback")
|
||||
self.recoilTimer = config.getParameter("recoilTime", 0.08)
|
||||
mcontroller.addMomentum(vec2.mul(aimVector(), -knockbackAttack.momentum))
|
||||
-- TODO: knock back enemies
|
||||
end
|
||||
end
|
||||
|
||||
return knockbackAttack
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"animationCustom" : {
|
||||
"sounds" : {
|
||||
"knockback" : [ "/sfx/gun/grenadeblast1.ogg", "/sfx/gun/grenadeblast2.ogg", "/sfx/gun/grenadeblast3.ogg" ]
|
||||
},
|
||||
"particleEmitters" : {
|
||||
"knockback" : {
|
||||
"emissionRate" : 10.0,
|
||||
"particles" : [
|
||||
{
|
||||
"particle" : {
|
||||
"type" : "animated",
|
||||
"animation" : "/animations/smoke/smoke.animation",
|
||||
"timeToLive" : 0.8,
|
||||
"initialVelocity" : [10.0, 0.0],
|
||||
"finalVelocity" : [1.0, 2.0],
|
||||
"approach" : [15, 10],
|
||||
"variance" : {
|
||||
"position" : [0, 0.5],
|
||||
"initialVelocity" : [5.0, 3.0],
|
||||
"timeToLive" : 0.2
|
||||
}
|
||||
},
|
||||
"offset" : [2.75, 0.125],
|
||||
"count" : 2
|
||||
},
|
||||
{
|
||||
"particle" : {
|
||||
"type" : "animated",
|
||||
"animation" : "/animations/mediumflame/mediumflame.animation",
|
||||
"timeToLive" : 0.6,
|
||||
"initialVelocity" : [10.0, 0.0],
|
||||
"finalVelocity" : [1.0, 2.0],
|
||||
"approach" : [15, 7],
|
||||
"variance" : {
|
||||
"position" : [0, 0.5],
|
||||
"initialVelocity" : [5.0, 3.0],
|
||||
"timeToLive" : 0.2
|
||||
}
|
||||
},
|
||||
"offset" : [2.75, 0.125],
|
||||
"count" : 4
|
||||
},
|
||||
{
|
||||
"particle" : {
|
||||
"type" : "ember",
|
||||
"color" : [240, 230, 70, 255],
|
||||
"light" : [160, 120, 70],
|
||||
"fade" : 0.9,
|
||||
"initialVelocity" : [20, 0.0],
|
||||
"finalVelocity" : [0, -10.0],
|
||||
"approach" : [10, 20],
|
||||
"timeToLive" : 0.6,
|
||||
"layer" : "middle",
|
||||
"variance" : {
|
||||
"position" : [0, 0.5],
|
||||
"size" : 0.5,
|
||||
"initialVelocity" : [10.0, 4.0],
|
||||
"timeToLive" : 0.2
|
||||
}
|
||||
},
|
||||
"offset" : [2.75, 0.125],
|
||||
"count" : 10
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"ability" : {
|
||||
"type" : "knockback",
|
||||
"scripts" : ["/items/active/weapons/ranged/abilities/shotgun/knockbackattack.lua"],
|
||||
"cooldown" : 2.0,
|
||||
"energyCost" : 30,
|
||||
"momentum" : 20
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"frameGrid" : {
|
||||
"size" : [96, 48],
|
||||
"dimensions" : [3, 1],
|
||||
|
||||
"names" : [
|
||||
[ "1", "2", "3" ]
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
require "/scripts/poly.lua"
|
||||
require "/scripts/vec2.lua"
|
||||
|
||||
function setupAbility(altAbilityConfig)
|
||||
local vacuum = WeaponAbility:new()
|
||||
|
||||
function vacuum:init()
|
||||
self.cooldownTimer = 0
|
||||
self:reset()
|
||||
end
|
||||
|
||||
function vacuum:update(dt, fireMode, shiftHeld)
|
||||
WeaponAbility.update(self, dt, fireMode, shiftHeld)
|
||||
|
||||
self.cooldownTimer = math.max(0, self.cooldownTimer - self.dt)
|
||||
|
||||
if self.fireMode == "alt"
|
||||
and not self.active
|
||||
and self.cooldownTimer == 0
|
||||
and not status.resourceLocked("energy") then
|
||||
|
||||
self:setState(self.fire)
|
||||
end
|
||||
end
|
||||
|
||||
function vacuum:fire()
|
||||
self.weapon:setStance(self.stances.fire)
|
||||
-- self.weapon.aimAngle = 0
|
||||
-- self.weapon:updateAim()
|
||||
animator.setAnimationState("vacuum", "active")
|
||||
animator.playSound("vacuumStart")
|
||||
animator.playSound("vacuumLoop", -1)
|
||||
|
||||
local vacuumPoint = {
|
||||
type = "RadialForceRegion",
|
||||
center = animator.partPoint("vacuumCone", "vacuumPoint"),
|
||||
targetRadialVelocity = self.pointSpeed,
|
||||
outerRadius = 1.5,
|
||||
innerRadius = 0.5,
|
||||
controlForce = self.pointForce
|
||||
}
|
||||
|
||||
self.active = true
|
||||
|
||||
while self.fireMode == "alt" and status.overConsumeResource("energy", self.energyUsage * self.dt) do
|
||||
mcontroller.controlModifiers({runningSuppressed = true})
|
||||
|
||||
local forceVector = vec2.rotate(self.coneSpeed, self.weapon.aimAngle)
|
||||
forceVector[1] = forceVector[1] * self.weapon.aimDirection
|
||||
|
||||
local vacuumConeTop = {
|
||||
type = "DirectionalForceRegion",
|
||||
polyRegion = animator.partPoly("vacuumCone", "vacuumPolyTop"),
|
||||
xTargetVelocity = forceVector[1],
|
||||
yTargetVelocity = -forceVector[2],
|
||||
controlForce = self.coneForce
|
||||
}
|
||||
local vacuumConeBottom = {
|
||||
type = "DirectionalForceRegion",
|
||||
polyRegion = animator.partPoly("vacuumCone", "vacuumPolyBottom"),
|
||||
xTargetVelocity = forceVector[1],
|
||||
yTargetVelocity = forceVector[2],
|
||||
controlForce = self.coneForce
|
||||
}
|
||||
activeItem.setItemForceRegions({vacuumConeTop, vacuumConeBottom, vacuumPoint})
|
||||
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
activeItem.setItemForceRegions({})
|
||||
|
||||
animator.setAnimationState("vacuum", "idle")
|
||||
animator.stopAllSounds("vacuumLoop")
|
||||
|
||||
self.cooldownTimer = self.cooldownTime
|
||||
|
||||
self.active = false
|
||||
end
|
||||
|
||||
function vacuum:reset()
|
||||
animator.setAnimationState("vacuum", "idle")
|
||||
animator.stopAllSounds("vacuumLoop")
|
||||
activeItem.setItemForceRegions({})
|
||||
self.active = false
|
||||
end
|
||||
|
||||
function vacuum:uninit()
|
||||
self:reset()
|
||||
end
|
||||
|
||||
return vacuum
|
||||
end
|
After Width: | Height: | Size: 2.4 KiB |
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"animationCustom" : {
|
||||
"animatedParts" : {
|
||||
"stateTypes" : {
|
||||
"vacuum" : {
|
||||
"default" : "idle",
|
||||
"states" : {
|
||||
"idle" : { },
|
||||
"active" : {
|
||||
"frames" : 3,
|
||||
"cycle" : 0.3,
|
||||
"mode" : "loop"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parts" : {
|
||||
"vacuumCone" : {
|
||||
"properties" : {
|
||||
"zLevel" : -1,
|
||||
"centered" : true,
|
||||
"offset" : [6.0, 0.0],
|
||||
"transformationGroups" : [ "muzzle" ],
|
||||
"vacuumPolyTop" : [ [-4.5, 0], [-4.5, 1.5], [6.0, 4.0], [6.0, 0] ],
|
||||
"vacuumPolyBottom" : [ [-4.5, -1.5], [-4.5, 0], [6.0, 0], [6.0, -4.0] ],
|
||||
"vacuumPoint" : [-5.0, 0.25]
|
||||
},
|
||||
"partStates" : {
|
||||
"vacuum" : {
|
||||
"idle" : {
|
||||
"properties" : {
|
||||
"image" : ""
|
||||
}
|
||||
},
|
||||
"active" : {
|
||||
"properties" : {
|
||||
"image" : "/items/active/weapons/ranged/abilities/vacuum/vacuum.png:<frame>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sounds" : {
|
||||
"vacuumStart" : [ ],
|
||||
"vacuumLoop" : [ ]
|
||||
}
|
||||
},
|
||||
|
||||
"ability" : {
|
||||
"type" : "vacuum",
|
||||
"scripts" : ["/items/active/weapons/ranged/abilities/vacuum/vacuum.lua"],
|
||||
|
||||
"cooldownTime" : 0.5,
|
||||
|
||||
"coneSpeed" : [-20, 5],
|
||||
"coneForce" : 400,
|
||||
"pointSpeed" : -10,
|
||||
"pointForce" : 500,
|
||||
|
||||
"energyUsage" : 20,
|
||||
|
||||
"stances" : {
|
||||
"fire" : {
|
||||
"armRotation" : 0,
|
||||
"weaponRotation" : 0,
|
||||
"twoHanded" : true,
|
||||
|
||||
"allowRotate" : true,
|
||||
"allowFlip" : true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"animationCustom" : {
|
||||
"sounds" : {
|
||||
"altFire" : [ "/sfx/gun/blowgun1.ogg", "/sfx/gun/blowgun2.ogg", "/sfx/gun/blowgun3.ogg" ]
|
||||
},
|
||||
"particleEmitters" : {
|
||||
"altMuzzleFlash" : {
|
||||
"active" : false,
|
||||
"emissionRate" : 8,
|
||||
"transformationGroups" : ["muzzle"],
|
||||
"offsetRegion" : [0, 0, 0, 0],
|
||||
"particles" : [ ]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"ability" : {
|
||||
"type" : "vacuumsphere",
|
||||
"scripts" : ["/items/active/weapons/ranged/abilities/altfire.lua"],
|
||||
|
||||
"elementalProjectiles" : {
|
||||
"physical" : "vacuumsphereprimer",
|
||||
"fire" : "vacuumsphereprimer",
|
||||
"electric" : "vacuumsphereprimer",
|
||||
"ice" : "vacuumsphereprimer",
|
||||
"poison" : "vacuumsphereprimer"
|
||||
},
|
||||
"projectileParameters" : {},
|
||||
"projectileCount" : 1,
|
||||
"inaccuracy" : 0,
|
||||
"baseDps" : 0,
|
||||
"energyUsageMultiplier" : 0.5,
|
||||
"fireTime" : 2.0,
|
||||
"fireType" : "auto",
|
||||
|
||||
"stances" : {
|
||||
"fire" : {
|
||||
"duration" : 0.15,
|
||||
"armRotation" : 5,
|
||||
"weaponRotation" : 5,
|
||||
"twoHanded" : true,
|
||||
|
||||
"allowRotate" : false,
|
||||
"allowFlip" : false
|
||||
},
|
||||
"cooldown" : {
|
||||
"duration" : 0.15,
|
||||
"armRotation" : 5,
|
||||
"weaponRotation" : 5,
|
||||
"twoHanded" : true,
|
||||
|
||||
"allowRotate" : false,
|
||||
"allowFlip" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"itemName" : "delaygun",
|
||||
"maxStack" : 1,
|
||||
"rarity" : "legendary",
|
||||
"description" : "Meh, I'll kill you later.",
|
||||
"shortdescription" : "Test Delay Rifle",
|
||||
"tooltipKind" : "gun",
|
||||
"weaponType" : "Delay Rifle",
|
||||
"twoHanded" : true,
|
||||
"itemTags" : ["weapon"],
|
||||
|
||||
"inventoryIcon" : "delaygun.png",
|
||||
|
||||
"animation" : "delaygun.animation",
|
||||
"animationParts" : {
|
||||
"gun" : "delaygun.png",
|
||||
"muzzleFlash" : "muzzleflash.png"
|
||||
},
|
||||
"animationCustom" : {
|
||||
"animatedParts" : { "parts" : {
|
||||
"gun" : { "properties" : {
|
||||
"offset" : [0.75, 0.125]
|
||||
}},
|
||||
"muzzleFlash" : { "properties" : {
|
||||
"offset" : [4.0, 0.375]
|
||||
}}
|
||||
}},
|
||||
"sounds" : {
|
||||
"fire" : [ "/sfx/gun/ar6.ogg" ]
|
||||
}
|
||||
},
|
||||
"fireOffset" : [3.625, 0.375],
|
||||
"aimOffset" : 0, // fireOffset[2] - gun offset - 0.25
|
||||
|
||||
"scripts" : ["delaygun.lua"],
|
||||
|
||||
"level" : 5,
|
||||
"fireTime" : 0.3,
|
||||
"inaccuracy" : 0.01,
|
||||
|
||||
"projectileType" : "delaybullet",
|
||||
"projectileParameters" : {
|
||||
"power" : 3
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"animatedParts" : {
|
||||
"stateTypes" : {
|
||||
"firing" : {
|
||||
"default" : "off",
|
||||
"states" : {
|
||||
"off" : {},
|
||||
"fire" : {
|
||||
"frames" : 2,
|
||||
"cycle" : 0.07,
|
||||
"mode" : "transition",
|
||||
"transition" : "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"parts" : {
|
||||
"gun" : {
|
||||
"properties" : {
|
||||
"centered" : true,
|
||||
"image" : "<partImage>",
|
||||
"offset" : [0.5, 0.125]
|
||||
}
|
||||
},
|
||||
"muzzleFlash" : {
|
||||
"properties" : {
|
||||
"zLevel" : -1,
|
||||
"centered" : true,
|
||||
"offset" : [3.625, 0.375],
|
||||
"fullbright" : true
|
||||
},
|
||||
|
||||
"partStates" : {
|
||||
"firing" : {
|
||||
"off" : {
|
||||
"properties" : {
|
||||
"image" : ""
|
||||
}
|
||||
},
|
||||
"fire" : {
|
||||
"properties" : {
|
||||
"image" : "<partImage>:<variant>.<frame>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"lights" : {
|
||||
"muzzleFlash" : {
|
||||
"active" : false,
|
||||
"position" : [3.25, 0.25],
|
||||
"color" : [60, 60, 0]
|
||||
}
|
||||
},
|
||||
|
||||
"sounds" : {
|
||||
"fire" : [ ]
|
||||
}
|
||||
}
|
101
assets/devel/items/active/weapons/ranged/delaygun/delaygun.lua
Normal file
|
@ -0,0 +1,101 @@
|
|||
require "/scripts/vec2.lua"
|
||||
|
||||
function init()
|
||||
-- scale damage and calculate energy cost
|
||||
self.pType = config.getParameter("projectileType")
|
||||
self.pParams = config.getParameter("projectileParameters", {})
|
||||
if not self.pParams.power then
|
||||
local projectileConfig = root.projectileConfig(self.pType)
|
||||
self.pParams.power = projectileConfig.power
|
||||
end
|
||||
self.pParams.power = self.pParams.power * root.evalFunction("weaponDamageLevelMultiplier", config.getParameter("level", 1))
|
||||
self.energyPerShot = 3 * self.pParams.power
|
||||
|
||||
self.fireOffset = config.getParameter("fireOffset")
|
||||
updateAim()
|
||||
|
||||
storage.fireTimer = storage.fireTimer or 0
|
||||
self.recoilTimer = 0
|
||||
|
||||
animator.setPartTag("muzzleFlash", "variant", "1")
|
||||
activeItem.setCursor("/cursors/reticle0.cursor")
|
||||
|
||||
self.activeBullets = {}
|
||||
end
|
||||
|
||||
function activate(fireMode, shiftHeld)
|
||||
if fireMode == "alt" then
|
||||
triggerBullets()
|
||||
end
|
||||
end
|
||||
|
||||
function update(dt, fireMode, shiftHeld)
|
||||
updateAim()
|
||||
updateBullets()
|
||||
|
||||
storage.fireTimer = math.max(storage.fireTimer - dt, 0)
|
||||
self.recoilTimer = math.max(self.recoilTimer - dt, 0)
|
||||
|
||||
if fireMode == "primary"
|
||||
and storage.fireTimer == 0
|
||||
and not world.pointTileCollision(firePosition())
|
||||
and status.overConsumeResource("energy", self.energyPerShot) then
|
||||
|
||||
storage.fireTimer = config.getParameter("fireTime", 1.0)
|
||||
fire()
|
||||
end
|
||||
|
||||
activeItem.setRecoil(self.recoilTimer > 0)
|
||||
animator.setLightActive("muzzleFlash", self.recoilTimer > 0)
|
||||
end
|
||||
|
||||
function fire()
|
||||
self.pParams.powerMultiplier = activeItem.ownerPowerMultiplier()
|
||||
local bulletId = world.spawnProjectile(
|
||||
self.pType,
|
||||
firePosition(),
|
||||
activeItem.ownerEntityId(),
|
||||
aimVector(),
|
||||
false,
|
||||
self.pParams
|
||||
)
|
||||
if bulletId then
|
||||
self.activeBullets[#self.activeBullets + 1] = bulletId
|
||||
end
|
||||
animator.setAnimationState("firing", "fire", true)
|
||||
animator.setPartTag("muzzleFlash", "variant", math.random(1, 3))
|
||||
animator.playSound("fire")
|
||||
self.recoilTimer = config.getParameter("recoilTime", 0.08)
|
||||
end
|
||||
|
||||
function updateAim()
|
||||
self.aimAngle, self.aimDirection = activeItem.aimAngleAndDirection(config.getParameter("aimOffset"), activeItem.ownerAimPosition())
|
||||
activeItem.setArmAngle(self.aimAngle)
|
||||
activeItem.setFacingDirection(self.aimDirection)
|
||||
end
|
||||
|
||||
function updateBullets()
|
||||
local newBullets = {}
|
||||
for i, bullet in ipairs(self.activeBullets) do
|
||||
if world.entityExists(bullet) then
|
||||
newBullets[#newBullets + 1] = bullet
|
||||
end
|
||||
end
|
||||
self.activeBullets = newBullets
|
||||
end
|
||||
|
||||
function triggerBullets()
|
||||
for i, bullet in ipairs(self.activeBullets) do
|
||||
world.callScriptedEntity(bullet, "trigger")
|
||||
end
|
||||
end
|
||||
|
||||
function firePosition()
|
||||
return vec2.add(mcontroller.position(), activeItem.handPosition(self.fireOffset))
|
||||
end
|
||||
|
||||
function aimVector()
|
||||
local aimVector = vec2.rotate({1, 0}, self.aimAngle + sb.nrand(config.getParameter("inaccuracy", 0), 0))
|
||||
aimVector[1] = aimVector[1] * self.aimDirection
|
||||
return aimVector
|
||||
end
|
BIN
assets/devel/items/active/weapons/ranged/delaygun/delaygun.png
Normal file
After Width: | Height: | Size: 350 B |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"frameGrid" : {
|
||||
"size" : [15, 15],
|
||||
"dimensions" : [2, 3],
|
||||
|
||||
"names" : [
|
||||
[ "1.1", "1.2" ],
|
||||
[ "2.1", "2.2" ],
|
||||
[ "3.1", "3.2" ]
|
||||
]
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 379 B |
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"itemName" : "guidedrocketlauncher",
|
||||
|
||||
"maxStack" : 1,
|
||||
"rarity" : "legendary",
|
||||
"description" : "It's time to rock some wicked trick shots.",
|
||||
"shortdescription" : "Guided Rocket Launcher",
|
||||
"tooltipKind" : "gun",
|
||||
"weaponType" : "Gun",
|
||||
"twoHanded" : true,
|
||||
"itemTags" : ["weapon"],
|
||||
|
||||
"inventoryIcon" : "guidedrocketlauncher.png",
|
||||
"animation" : "guidedrocketlauncher.animation",
|
||||
"animationCustom" : { },
|
||||
"scripts" : ["guidedrocketlauncher.lua"],
|
||||
"fireOffset" : [2.0, 1.0],
|
||||
|
||||
"level" : 6,
|
||||
"fireTime" : 2.0,
|
||||
"inaccuracy" : 0.02,
|
||||
"projectileType" : "guidedrocket",
|
||||
"projectileParameters" : {
|
||||
"power" : 12
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"animatedParts" : {
|
||||
"stateTypes" : {
|
||||
"reload" : {
|
||||
"default" : "ready",
|
||||
"states" : {
|
||||
"ready" : {},
|
||||
"reload" : {
|
||||
"frames" : 4,
|
||||
"cycle" : 1.0,
|
||||
"mode" : "transition",
|
||||
"transition" : "ready"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"parts" : {
|
||||
"gun" : {
|
||||
"properties" : {
|
||||
"centered" : true,
|
||||
"image" : "guidedrocketlauncher.png",
|
||||
"offset" : [-0.75, 0.75]
|
||||
}
|
||||
},
|
||||
"reloadLights" : {
|
||||
"properties" : {
|
||||
"centered" : true,
|
||||
"offset" : [-0.5, 0.875],
|
||||
"zLevel" : 1,
|
||||
"fullbright" : true
|
||||
},
|
||||
|
||||
"partStates" : {
|
||||
"reload" : {
|
||||
"ready" : {
|
||||
"properties" : {
|
||||
"image" : "reloadlights.png:ready"
|
||||
}
|
||||
},
|
||||
"reload" : {
|
||||
"properties" : {
|
||||
"image" : "reloadlights.png:reload.<frame>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"particleEmitters" : {
|
||||
"fireParticles" : {
|
||||
"emissionRate" : 10.0,
|
||||
"particles" : [
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"sounds" : {
|
||||
"fire" : [ "/sfx/gun/rocket1.ogg" ]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
require "/scripts/vec2.lua"
|
||||
|
||||
function init()
|
||||
-- scale damage and calculate energy cost
|
||||
self.pType = config.getParameter("projectileType")
|
||||
self.pParams = config.getParameter("projectileParameters", {})
|
||||
if not self.pParams.power then
|
||||
local projectileConfig = root.projectileConfig(self.pType)
|
||||
self.pParams.power = projectileConfig.power
|
||||
end
|
||||
self.pParams.power = self.pParams.power * root.evalFunction("weaponDamageLevelMultiplier", config.getParameter("level", 1))
|
||||
self.energyPerShot = 3 * self.pParams.power
|
||||
|
||||
self.fireOffset = config.getParameter("fireOffset")
|
||||
updateAim()
|
||||
|
||||
storage.fireTimer = storage.fireTimer or 0
|
||||
self.recoilTimer = 0
|
||||
|
||||
animator.setAnimationRate(1 / config.getParameter("fireTime", 1.0))
|
||||
|
||||
self.activeRockets = {}
|
||||
updateCursor()
|
||||
end
|
||||
|
||||
function update(dt, fireMode, shiftHeld)
|
||||
updateAim()
|
||||
|
||||
storage.fireTimer = math.max(storage.fireTimer - dt, 0)
|
||||
self.recoilTimer = math.max(self.recoilTimer - dt, 0)
|
||||
|
||||
if fireMode ~= "none"
|
||||
and storage.fireTimer <= 0
|
||||
and not world.pointTileCollision(firePosition())
|
||||
and status.overConsumeResource("energy", self.energyPerShot) then
|
||||
|
||||
storage.fireTimer = config.getParameter("fireTime", 1.0)
|
||||
fire()
|
||||
end
|
||||
|
||||
activeItem.setRecoil(self.recoilTimer > 0)
|
||||
|
||||
updateRockets()
|
||||
updateCursor()
|
||||
end
|
||||
|
||||
function updateCursor()
|
||||
if #self.activeRockets > 0 then
|
||||
activeItem.setCursor("/cursors/chargeready.cursor")
|
||||
else
|
||||
activeItem.setCursor("/cursors/reticle0.cursor")
|
||||
end
|
||||
end
|
||||
|
||||
function uninit()
|
||||
for i, rocket in ipairs(self.activeRockets) do
|
||||
world.callScriptedEntity(rocket, "setTarget", nil)
|
||||
end
|
||||
end
|
||||
|
||||
function fire()
|
||||
self.pParams.powerMultiplier = activeItem.ownerPowerMultiplier()
|
||||
local rocketId = world.spawnProjectile(
|
||||
self.pType,
|
||||
firePosition(),
|
||||
activeItem.ownerEntityId(),
|
||||
aimVector(),
|
||||
false,
|
||||
self.pParams
|
||||
)
|
||||
if rocketId then
|
||||
self.activeRockets[#self.activeRockets + 1] = rocketId
|
||||
end
|
||||
animator.setAnimationState("reload", "reload", true)
|
||||
animator.burstParticleEmitter("fireParticles")
|
||||
animator.playSound("fire")
|
||||
self.recoilTimer = config.getParameter("recoilTime", 0.12)
|
||||
end
|
||||
|
||||
function updateAim()
|
||||
self.aimAngle, self.aimDirection = activeItem.aimAngleAndDirection(self.fireOffset[2], activeItem.ownerAimPosition())
|
||||
activeItem.setArmAngle(self.aimAngle)
|
||||
activeItem.setFacingDirection(self.aimDirection)
|
||||
end
|
||||
|
||||
function updateRockets()
|
||||
local newRockets = {}
|
||||
for i, rocket in ipairs(self.activeRockets) do
|
||||
if world.entityExists(rocket) then
|
||||
newRockets[#newRockets + 1] = rocket
|
||||
end
|
||||
end
|
||||
self.activeRockets = newRockets
|
||||
|
||||
for i, rocket in ipairs(self.activeRockets) do
|
||||
world.callScriptedEntity(rocket, "setTarget", activeItem.ownerAimPosition())
|
||||
end
|
||||
end
|
||||
|
||||
function firePosition()
|
||||
return vec2.add(mcontroller.position(), activeItem.handPosition(self.fireOffset))
|
||||
end
|
||||
|
||||
function aimVector()
|
||||
local aimVector = vec2.rotate({1, 0}, self.aimAngle + sb.nrand(config.getParameter("inaccuracy", 0), 0))
|
||||
aimVector[1] = aimVector[1] * self.aimDirection
|
||||
return aimVector
|
||||
end
|
After Width: | Height: | Size: 456 B |
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"frameGrid" : {
|
||||
"size" : [10, 3],
|
||||
"dimensions" : [1, 5],
|
||||
|
||||
"names" : [
|
||||
[ "reload.1" ],
|
||||
[ "reload.2" ],
|
||||
[ "reload.3" ],
|
||||
[ "reload.4" ],
|
||||
[ "ready" ]
|
||||
]
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 221 B |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"itemName" : "metagun",
|
||||
"level" : 1,
|
||||
"maxStack" : 1,
|
||||
"rarity" : "legendary",
|
||||
"description" : "It might be a little too meta.",
|
||||
"shortdescription" : "Meta Gun",
|
||||
"tooltipKind" : "gun",
|
||||
"weaponType" : "Gun",
|
||||
"twoHanded" : true,
|
||||
"itemTags" : ["weapon"],
|
||||
|
||||
"inventoryIcon" : "metagunicon.png",
|
||||
"animation" : "metagun.animation",
|
||||
"animationCustom" : {},
|
||||
"scripts" : ["metagun.lua"],
|
||||
|
||||
"fireTime" : 0.2,
|
||||
"fireOffset" : [4.5, 0.5],
|
||||
"projectileType" : "delayedplasmaball",
|
||||
"projectileParameters" : {}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"animatedParts" : {
|
||||
"stateTypes" : {
|
||||
"firing" : {
|
||||
"default" : "off",
|
||||
"states" : {
|
||||
"off" : {},
|
||||
"fire" : {
|
||||
"frames" : 2,
|
||||
"cycle" : 0.1,
|
||||
"mode" : "transition",
|
||||
"transition" : "cooldown",
|
||||
"properties" : {
|
||||
"immediateSound" : "/sfx/gun/ar1.ogg"
|
||||
},
|
||||
"frameProperties" : {
|
||||
"stateNudge" : [ [-0.125, 0], [0, 0] ]
|
||||
}
|
||||
},
|
||||
"cooldown" : {
|
||||
"cycle" : 0.1,
|
||||
"mode" : "transition",
|
||||
"transition" : "fire"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"parts" : {
|
||||
"gun" : {
|
||||
"properties" : {
|
||||
"centered" : true,
|
||||
"image" : "metagun.png",
|
||||
"offset" : [1.8, 0.5]
|
||||
}
|
||||
},
|
||||
"muzzleFlash" : {
|
||||
"properties" : {
|
||||
"zLevel" : 1,
|
||||
"centered" : true,
|
||||
"offset" : [5.0, 0.625]
|
||||
},
|
||||
|
||||
"partStates" : {
|
||||
"firing" : {
|
||||
"off" : {
|
||||
"properties" : {
|
||||
"image" : ""
|
||||
}
|
||||
},
|
||||
"fire" : {
|
||||
"properties" : {
|
||||
"image" : "muzzleflash.png:<variant>.<frame>"
|
||||
}
|
||||
},
|
||||
"cooldown" : {
|
||||
"properties" : {
|
||||
"image" : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
assets/devel/items/active/weapons/ranged/metagun/metagun.lua
Normal file
|
@ -0,0 +1,95 @@
|
|||
require "/scripts/vec2.lua"
|
||||
|
||||
function init()
|
||||
-- sb.logInfo("Initializing metagun")
|
||||
|
||||
-- self.recoil = 0
|
||||
-- self.recoilRate = 0
|
||||
|
||||
self.fireOffset = config.getParameter("fireOffset")
|
||||
updateAim()
|
||||
|
||||
self.active = false
|
||||
storage.fireTimer = storage.fireTimer or 0
|
||||
|
||||
animator.setPartTag("muzzleFlash", "variant", "1")
|
||||
end
|
||||
|
||||
function uninit()
|
||||
-- sb.logInfo("Uninitializing metagun")
|
||||
end
|
||||
|
||||
function update(dt, fireMode, shiftHeld)
|
||||
-- sb.logInfo("Updating metagun with fireMode %s and shiftHeld %s", fireMode, shiftHeld)
|
||||
|
||||
updateAim()
|
||||
|
||||
if fireMode == "none" then
|
||||
stopFiring()
|
||||
end
|
||||
|
||||
storage.fireTimer = math.max(storage.fireTimer - dt, 0)
|
||||
|
||||
-- if self.active then
|
||||
-- self.recoilRate = 0
|
||||
-- else
|
||||
-- self.recoilRate = math.max(1, self.recoilRate + (10 * dt))
|
||||
-- end
|
||||
-- self.recoil = math.max(self.recoil - dt * self.recoilRate, 0)
|
||||
|
||||
if self.active and storage.fireTimer <= 0 then
|
||||
if animator.animationState("firing") == "off" then
|
||||
animator.setAnimationState("firing", "fire")
|
||||
end
|
||||
animator.setPartTag("muzzleFlash", "variant", math.random(1, 3))
|
||||
storage.fireTimer = config.getParameter("fireTime", 1.0)
|
||||
|
||||
if not world.pointTileCollision(firePosition()) then
|
||||
world.spawnProjectile(
|
||||
config.getParameter("projectileType"),
|
||||
firePosition(),
|
||||
activeItem.ownerEntityId(),
|
||||
aimVector(),
|
||||
false,
|
||||
config.getParameter("projectileParameters", {})
|
||||
)
|
||||
-- self.recoil = self.recoil + 0.5
|
||||
else
|
||||
animator.setAnimationState("firing", "off")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function activate(fireMode, shiftHeld)
|
||||
-- sb.logInfo("Activating metagun with fireMode %s and shiftHeld %s", fireMode, shiftHeld)
|
||||
|
||||
if not self.active then
|
||||
startFiring()
|
||||
end
|
||||
end
|
||||
|
||||
function startFiring()
|
||||
self.active = true
|
||||
end
|
||||
|
||||
function stopFiring()
|
||||
self.active = false
|
||||
animator.setAnimationState("firing", "off")
|
||||
end
|
||||
|
||||
function updateAim()
|
||||
self.aimAngle, self.aimDirection = activeItem.aimAngleAndDirection(self.fireOffset[2], activeItem.ownerAimPosition())
|
||||
self.aimAngle = self.aimAngle -- + self.recoil * 0.3
|
||||
activeItem.setArmAngle(self.aimAngle)
|
||||
activeItem.setFacingDirection(self.aimDirection)
|
||||
end
|
||||
|
||||
function firePosition()
|
||||
return vec2.add(mcontroller.position(), activeItem.handPosition(self.fireOffset))
|
||||
end
|
||||
|
||||
function aimVector()
|
||||
local aimVector = vec2.rotate({1, 0}, self.aimAngle + sb.nrand(config.getParameter("inaccuracy", 0), 0))
|
||||
aimVector[1] = aimVector[1] * self.aimDirection
|
||||
return aimVector
|
||||
end
|
BIN
assets/devel/items/active/weapons/ranged/metagun/metagun.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/devel/items/active/weapons/ranged/metagun/metagunicon.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"frameGrid" : {
|
||||
"size" : [15, 15],
|
||||
"dimensions" : [2, 3],
|
||||
|
||||
"names" : [
|
||||
[ "1.1", "1.2" ],
|
||||
[ "2.1", "2.2" ],
|
||||
[ "3.1", "3.2" ]
|
||||
]
|
||||
}
|
||||
}
|
BIN
assets/devel/items/active/weapons/ranged/metagun/muzzleflash.png
Normal file
After Width: | Height: | Size: 379 B |
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"frameGrid" : {
|
||||
"size" : [10, 3],
|
||||
"dimensions" : [1, 5],
|
||||
|
||||
"names" : [
|
||||
[ "reload.1" ],
|
||||
[ "reload.2" ],
|
||||
[ "reload.3" ],
|
||||
[ "reload.4" ],
|
||||
[ "ready" ]
|
||||
]
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 221 B |
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"itemName" : "testrocket",
|
||||
|
||||
"maxStack" : 1,
|
||||
"rarity" : "legendary",
|
||||
"description" : "Fwoosh... pchoom!",
|
||||
"shortdescription" : "Rocket Lawnchair",
|
||||
"tooltipKind" : "gun",
|
||||
"weaponType" : "Gun",
|
||||
"twoHanded" : true,
|
||||
"itemTags" : ["weapon"],
|
||||
|
||||
"inventoryIcon" : "testrocket.png",
|
||||
"animation" : "testrocket.animation",
|
||||
"animationCustom" : {},
|
||||
"scripts" : ["testrocket.lua"],
|
||||
"fireOffset" : [2.0, 1.0],
|
||||
|
||||
"level" : 6,
|
||||
"fireTime" : 2.0,
|
||||
"inaccuracy" : 0.02,
|
||||
"projectileType" : "rocketshell",
|
||||
"projectileParameters" : {
|
||||
"power" : 12
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"animatedParts" : {
|
||||
"stateTypes" : {
|
||||
"reload" : {
|
||||
"default" : "ready",
|
||||
"states" : {
|
||||
"ready" : {},
|
||||
"reload" : {
|
||||
"frames" : 4,
|
||||
"cycle" : 1.0,
|
||||
"mode" : "transition",
|
||||
"transition" : "ready"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"parts" : {
|
||||
"gun" : {
|
||||
"properties" : {
|
||||
"centered" : true,
|
||||
"image" : "testrocket.png",
|
||||
"offset" : [-0.75, 0.75]
|
||||
}
|
||||
},
|
||||
"reloadLights" : {
|
||||
"properties" : {
|
||||
"centered" : true,
|
||||
"offset" : [-0.5, 0.875],
|
||||
"zLevel" : 1,
|
||||
"fullbright" : true
|
||||
},
|
||||
|
||||
"partStates" : {
|
||||
"reload" : {
|
||||
"ready" : {
|
||||
"properties" : {
|
||||
"image" : "reloadlights.png:ready"
|
||||
}
|
||||
},
|
||||
"reload" : {
|
||||
"properties" : {
|
||||
"image" : "reloadlights.png:reload.<frame>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"particleEmitters" : {
|
||||
"fireParticles" : {
|
||||
"emissionRate" : 10.0,
|
||||
"particles" : [
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
},
|
||||
{
|
||||
"particle" : "rocketbarrelpuff",
|
||||
"offset" : [2, 0.75]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"sounds" : {
|
||||
"fire" : [ "/sfx/gun/rocket_shot.ogg" ]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
require "/scripts/vec2.lua"
|
||||
|
||||
function init()
|
||||
-- scale damage and calculate energy cost
|
||||
self.pType = config.getParameter("projectileType")
|
||||
self.pParams = config.getParameter("projectileParameters", {})
|
||||
if not self.pParams.power then
|
||||
local projectileConfig = root.projectileConfig(self.pType)
|
||||
self.pParams.power = projectileConfig.power
|
||||
end
|
||||
self.pParams.power = self.pParams.power * root.evalFunction("weaponDamageLevelMultiplier", config.getParameter("level", 1))
|
||||
self.energyPerShot = 3 * self.pParams.power
|
||||
|
||||
self.fireOffset = config.getParameter("fireOffset")
|
||||
updateAim()
|
||||
|
||||
storage.fireTimer = storage.fireTimer or 0
|
||||
self.recoilTimer = 0
|
||||
|
||||
animator.setAnimationRate(1 / config.getParameter("fireTime", 1.0))
|
||||
end
|
||||
|
||||
function update(dt, fireMode, shiftHeld)
|
||||
updateAim()
|
||||
|
||||
storage.fireTimer = math.max(storage.fireTimer - dt, 0)
|
||||
self.recoilTimer = math.max(self.recoilTimer - dt, 0)
|
||||
|
||||
if fireMode ~= "none"
|
||||
and storage.fireTimer <= 0
|
||||
and not world.pointTileCollision(firePosition())
|
||||
and status.overConsumeResource("energy", self.energyPerShot) then
|
||||
|
||||
storage.fireTimer = config.getParameter("fireTime", 1.0)
|
||||
fire()
|
||||
end
|
||||
|
||||
activeItem.setRecoil(self.recoilTimer > 0)
|
||||
end
|
||||
|
||||
function fire()
|
||||
self.pParams.powerMultiplier = activeItem.ownerPowerMultiplier()
|
||||
world.spawnProjectile(
|
||||
self.pType,
|
||||
firePosition(),
|
||||
activeItem.ownerEntityId(),
|
||||
aimVector(),
|
||||
false,
|
||||
self.pParams
|
||||
)
|
||||
animator.setAnimationState("reload", "reload", true)
|
||||
animator.burstParticleEmitter("fireParticles")
|
||||
animator.playSound("fire")
|
||||
self.recoilTimer = config.getParameter("recoilTime", 0.12)
|
||||
end
|
||||
|
||||
function updateAim()
|
||||
self.aimAngle, self.aimDirection = activeItem.aimAngleAndDirection(self.fireOffset[2], activeItem.ownerAimPosition())
|
||||
activeItem.setArmAngle(self.aimAngle)
|
||||
activeItem.setFacingDirection(self.aimDirection)
|
||||
end
|
||||
|
||||
function firePosition()
|
||||
return vec2.add(mcontroller.position(), activeItem.handPosition(self.fireOffset))
|
||||
end
|
||||
|
||||
function aimVector()
|
||||
local aimVector = vec2.rotate({1, 0}, self.aimAngle + sb.nrand(config.getParameter("inaccuracy", 0), 0))
|
||||
aimVector[1] = aimVector[1] * self.aimDirection
|
||||
return aimVector
|
||||
end
|
After Width: | Height: | Size: 456 B |