Modding Discussion Community Weapon(s)

Discussion in 'Starbound Modding' started by MetaFace, Feb 9, 2017.

  1. MetaFace

    MetaFace Guest

    I'm going to take a long hard look at this, this is almost exactly what I need, I suspect it'd take the smallest changes to do what I'm thinking. @Inf_Wolf14, you have helped a lot here. Thanks again for an amazing resource.
     
    Inf_Wolf14 likes this.
  2. Inf_Wolf14

    Inf_Wolf14 Parsec Taste Tester

    The only thing ill say is make sure you credit @AlbertoRota for his work.

    He has helped me and others in the past to great lengths and is a mind behind some really great mods.
    I havent seen him around for a while but id like to make sure he isnt forgotten for his effort. :)
     
  3. MetaFace

    MetaFace Guest

    I will, right in the mod description, and right here. Anyways, I'm out of it for now, I need to time to look over documentation for lua and study the code, learn what it means, so I may have little to no posts here for awhile, but this thread isn't dead.

    I'm going to say that this is probably a good time to come up with possible suggestions for new items or weapons or what have you. See you guys in a little while.
     
    Inf_Wolf14 likes this.
  4. MetaFace

    MetaFace Guest

    Like I said, this tread isn't dead, I've got something (through the little work I've actually worked on this since then, mostly due to the fact I felt that I didn't have the skill). I want someone to look at this alt I've done a little with (I guess it looks more like a primary with an alt built in), it's hard coded for the most part, with "some" customizing, the alt can't be switched out and such, only the position of the weapon and time it takes for the player to recover.

    Code:
    -- Melee primary ability
    MeleeCombo = WeaponAbility:new()
    
    function MeleeCombo:init()
      self.comboStep = 1
    
      self.energyUsage = self.energyUsage or 0
    
      self:computeDamageAndCooldowns()
    
      self.weapon:setStance(self.stances.idle)
    
      self.edgeTriggerTimer = 0
      self.flashTimer = 0
      self.cooldownTimer = self.cooldowns[1]
    
      self.animKeyPrefix = self.animKeyPrefix or ""
    
      self.weapon.onLeaveAbility = function()
        self.weapon:setStance(self.stances.idle)
      end
    end
    
    -- Ticks on every update regardless if this is the active ability
    function MeleeCombo:update(dt, fireMode, shiftHeld)
      WeaponAbility.update(self, dt, fireMode, shiftHeld)
    
      if self.cooldownTimer > 0 then
        self.cooldownTimer = math.max(0, self.cooldownTimer - self.dt)
        if self.cooldownTimer == 0 then
          self:readyFlash()
        end
      end
    
      if self.flashTimer > 0 then
        self.flashTimer = math.max(0, self.flashTimer - self.dt)
        if self.flashTimer == 0 then
          animator.setGlobalTag("bladeDirectives", "")
        end
      end
    
      self.edgeTriggerTimer = math.max(0, self.edgeTriggerTimer - dt)
      if self.lastFireMode ~= (self.activatingFireMode or self.abilitySlot) and fireMode == (self.activatingFireMode or self.abilitySlot) then
        self.edgeTriggerTimer = self.edgeTriggerGrace
      end
      self.lastFireMode = fireMode
    
      if not self.weapon.currentAbility and self:shouldActivate() then
        if mcontroller.onGround() then
          self:setState(self.windup)
        else
          self:setState(self.pogo)
        end
      end
    end
    
    -- State: windup
    function MeleeCombo:windup()
      local stance = self.stances["windup"..self.comboStep]
    
      self.weapon:setStance(stance)
    
      self.edgeTriggerTimer = 0
    
      if stance.hold then
        while self.fireMode == (self.activatingFireMode or self.abilitySlot) do
          coroutine.yield()
        end
      else
        util.wait(stance.duration)
      end
    
      if self.energyUsage then
        status.overConsumeResource("energy", self.energyUsage)
      end
    
      if self.stances["preslash"..self.comboStep] then
        self:setState(self.preslash)
      else
        self:setState(self.fire)
      end
    end
    
    -- State: wait
    -- waiting for next combo input
    function MeleeCombo:wait()
      local stance = self.stances["wait"..(self.comboStep - 1)]
    
      self.weapon:setStance(stance)
    
      util.wait(stance.duration, function()
        if self:shouldActivate() then
          self:setState(self.windup)
          mcontroller.controlModifiers({runningSuppressed = true})
          return
        end
      end)
    
      self.cooldownTimer = math.max(0, self.cooldowns[self.comboStep - 1] - stance.duration)
      self.comboStep = 1
    end
    
    -- State: preslash
    -- brief frame in between windup and fire
    function MeleeCombo:preslash()
      local stance = self.stances["preslash"..self.comboStep]
    
      self.weapon:setStance(stance)
      self.weapon:updateAim()
    
      util.wait(stance.duration)
    
      self:setState(self.fire)
    end
    
    function MeleeCombo:pogo()
      local stance = self.stances["pogo"]
    
      self.weapon:setStance(stance)
      self.weapon:updateAim()
    
      local animStateKey = self.animKeyPrefix .. ("stab")
      animator.setAnimationState("swoosh", animStateKey)
      animator.playSound(animStateKey)
    
      while self.fireMode == (self.activatingFireMode or self.abilitySlot) and not mcontroller.onGround() do
        local damageArea = partDamageArea("swoosh")
        if mcontroller.yVelocity() < 0 then
          animator.setAnimationState("swoosh", animStateKey)
          mcontroller.setYVelocity(-70)
        else
          mcontroller.setYVelocity(-70)
        end
        self.weapon:setDamage(self.stabDamage, damageArea)
      
        coroutine.yield()
      end
      
      if mcontroller.onGround() then
        util.wait(stance.duration, function ()
          mcontroller.controlModifiers({
            facingSuppressed = true,
            movementSuppressed = true
        })
        end)
      end
    end
    
    -- State: fire
    function MeleeCombo:fire()
      local stance = self.stances["fire"..self.comboStep]
    
      self.weapon:setStance(stance)
      self.weapon:updateAim()
    
      local animStateKey = self.animKeyPrefix .. ("fire"..self.comboStep)
      animator.setAnimationState("swoosh", animStateKey)
      animator.playSound(animStateKey)
    
      local swooshKey = self.animKeyPrefix .. (self.elementalType or self.weapon.elementalType) .. "swoosh"
      animator.setParticleEmitterOffsetRegion(swooshKey, self.swooshOffsetRegions[self.comboStep])
      animator.burstParticleEmitter(swooshKey)
    
      util.wait(stance.duration, function()
        local damageArea = partDamageArea("swoosh")
        self.weapon:setDamage(self.stepDamageConfig[self.comboStep], damageArea)
        mcontroller.controlModifiers({runningSuppressed = true})
      end)
    
      --[[if self.comboStep == 3 then
        local direction = {}
        local params = copy(self.projectileParameters)
        params.powerMultiplier = activeItem.ownerPowerMultiplier()
        params.power = params.power * config.getParameter("damageLevelMultiplier")
        params.actionOnReap = {
          {
            action = "projectile",
            inheritDamageFactor = 1,
            type = "physicalshockwave"
          }
        }
        params.timeToLive = 1.0
        for i = 0, 15 do
          local travel = {mcontroller.position()[1], mcontroller.position()[2] - 2}
          travel = {travel[1] + mcontroller.facingDirection() * i, travel[2]}
          table.insert(direction, travel)
        end
        world.spawnProjectile("shockwavespawner", direction, activeItem.ownerEntityId(), {mcontroller.facingDirection(),0}, false, params)
      end]]
    
      if self.comboStep < self.comboSteps then
        self.comboStep = self.comboStep + 1
        self:setState(self.wait)
      else
        self.cooldownTimer = self.cooldowns[self.comboStep]
        self.comboStep = 1
      end
    end
    
    function MeleeCombo:shouldActivate()
      if self.cooldownTimer == 0 and (self.energyUsage == 0 or not status.resourceLocked("energy")) then
        if self.comboStep > 1 then
          return self.edgeTriggerTimer > 0
        else
          return self.fireMode == (self.activatingFireMode or self.abilitySlot)
        end
      end
    end
    
    function MeleeCombo:readyFlash()
      animator.setGlobalTag("bladeDirectives", self.flashDirectives)
      self.flashTimer = self.flashTime
    end
    
    function MeleeCombo:computeDamageAndCooldowns()
      local attackTimes = {}
      for i = 1, self.comboSteps do
        local attackTime = self.stances["windup"..i].duration + self.stances["fire"..i].duration
        if self.stances["preslash"..i] then
          attackTime = attackTime + self.stances["preslash"..i].duration
        end
        table.insert(attackTimes, attackTime)
      end
    
      self.cooldowns = {}
      local totalAttackTime = 0
      local totalDamageFactor = 0
      for i, attackTime in ipairs(attackTimes) do
        self.stepDamageConfig[i] = util.mergeTable(copy(self.damageConfig), self.stepDamageConfig[i])
        self.stepDamageConfig[i].timeoutGroup = "primary"..i
    
        local damageFactor = self.stepDamageConfig[i].baseDamageFactor
        self.stepDamageConfig[i].baseDamage = damageFactor * self.baseDps * self.fireTime
      
        local stabFactor = self.stabDamage.baseDamageFactor
        self.stabDamage.baseDamage = stabFactor * self.baseDps
    
        totalAttackTime = totalAttackTime + attackTime
        totalDamageFactor = totalDamageFactor + damageFactor
    
        local targetTime = totalDamageFactor * self.fireTime
        local speedFactor = 1.0 * (self.comboSpeedFactor ^ i)
        table.insert(self.cooldowns, (targetTime - totalAttackTime) * speedFactor)
      end
    end
    
    function MeleeCombo:uninit()
      self.weapon:setDamage()
    end
    



    Code:
    {
      "animationParts" : { },
      "animationCustom" : {
        "sounds" : {
          "fire1" : [ "/sfx/melee/swing_broadsword.ogg" ],
          "fire2" : [ "/sfx/melee/swing_shortsword.ogg" ],
          "fire3" : [ "/sfx/melee/swing_spear.ogg" ],
          "stab" : ["/sfx/melee/soulseeker_swing.ogg"]
        }
      },
    
      "ability" : {
        "name" : "Heavy Combo Slash",
        "type" : "greatslashcombo",
        "scripts" : ["/items/active/weapons/abilities/warswords/combo/altcombo.lua"],
        "class" : "MeleeCombo",
    
        "comboSteps" : 3,
      
        "projectileParameters" : {
          "power" : 3.5,
          "knockback" : 35,
          "knockbackMode" : "facing"
        },
    
        "flashTime" : 0.15,
        "flashDirectives" : "fade=FFFFFFFF=0.15",
    
        "swooshOffsetRegions" : [
          [0.75, 0.0, 4.25, 5.0],
          [3.0, -0.5, 6.5, 2.0],
          [1.5, -1.0, 5.5, 1.0]
        ],
    
        // cooldown time multiplier for steps after the first, compounded per combo step
        "comboSpeedFactor" : 0.9,
    
        "edgeTriggerGrace" : 0.25,
    
        "fireTime" : 0.6,
        "baseDps" : 28.0,
        "energyUsage" : 50.0,
    
        "damageConfig" : {
          "damageSourceKind" : "broadsword",
          "statusEffects" : [ ],
          "knockbackMode" : "facing",
          "timeout" : 0.5
        },
        "stepDamageConfig" : [
          {
            "baseDamageFactor" : 1.0,
            "knockback" : 25
          },
          {
            "baseDamageFactor" : 0.8,
            "knockback" : 20
          },
          {
            "baseDamageFactor" : 1.0,
            "knockback" : 30
          }
        ],
        "stabDamage" : {
            "baseDamageFactor" : 2.3,
            "knockback" : 0
          },
    
        "stances" : {
        "idle" : {
            "armRotation" : 0,
            "weaponRotation" : 45,
            "weaponOffset" : [-0.125, 5.5],
            "allowRotate" : false,
            "allowFlip" : true
          },
          "windup1" : {
            "duration" : 0.1,
            "armRotation" : 90,
            "weaponRotation" : -10,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
    
            "allowRotate" : false,
            "allowFlip" : true
          },
          "preslash1" : {
            "duration" : 0.025,
            "armRotation" : 55,
            "weaponRotation" : -45,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
    
            "allowRotate" : false,
            "allowFlip" : false
          },
          "fire1" : {
            "duration" : 0.15,
            "armRotation" : -45,
            "weaponRotation" : -55,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
    
            "allowRotate" : false,
            "allowFlip" : false
          },
          "wait1" : {
            "duration" : 0.2,
            "armRotation" : -45,
            "weaponRotation" : -55,
            "weaponOffset" : [-0.125, 5.5],
            "allowRotate" : false,
            "allowFlip" : true,
            "twoHanded" : true
          },
          "windup2" : {
            "duration" : 0.15,
            "armRotation" : -15,
            "weaponRotation" : -60,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
            "allowFlip" : true,
            "allowRotate" : false
          },
          "fire2" : {
            "duration" : 0.2,
            "armRotation" : -150,
            "weaponRotation" : 55,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
            "allowFlip" : true,
            "allowRotate" : false
          },
          "wait2" : {
            "duration" : 0.2,
            "armRotation" : -150,
            "weaponRotation" : 55,
            "weaponOffset" : [-0.125, 5.5],
            "allowRotate" : false,
            "allowFlip" : true,
            "twoHanded" : true
          },
          "windup3" : {
            "duration" : 0.15,
            "armRotation" : -150,
            "weaponRotation" : 55,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
    
            "allowRotate" : false,
            "allowFlip" : true
          },
          "fire3" : {
            "duration" : 0.3,
            "armRotation" : 0,
            "weaponRotation" : -90,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
    
            "allowRotate" : false,
            "allowFlip" : true
          },
          "pogo" : {
            "duration" : 0.6,
            "armRotation" : 0,
            "weaponRotation" : -180,
            "weaponOffset" : [-0.125, 5.5],
            "twoHanded" : true,
          
            "allowRotate" : false,
            "allowFlip" : false
          }
        }
      }
    }
    


    of course you'll need a weapon to reference this on and to adjust the hit box as this is used on a VERY large weapon. Thanks for anyone who provides input, and sorry for not just giving a zip file (as Chromebooks are kinda funny when it comes to zips, at least for me).

    Edit:
    Probably should note that the alt-"alt" activates when in the air, the normal is when on the ground... probably need to make the system better as it is very wonky.
     

Share This Page