Modding Help Allow same ability to recast

Discussion in 'Starbound Modding' started by lerdarim, Nov 4, 2019.

  1. lerdarim

    lerdarim Void-Bound Voyager

    Howdy everyone. While making a custom ability i've stumbled across necessity to make it possible to repeatedly use the ability, but restrict anything else for like half-second.

    The ability itself has a windup, dash and wait stances. Windup and dash are the core and are pretty swift, "wait" is exactly that delay before player can move or attack. I need to ignore that delay for second ability cast.

    Here's generic code which checks if ability can be used before going into windup stance.
    Code:
      if self.weapon.currentAbility == nil
         and self.fireMode == "alt"
         and self.cooldownTimer == 0
         and not status.statPositive("activeMovementAbilities")
         and status.overConsumeResource("energy", self.energyUsage) then
    
    First i tried something like "self.weapon:setStance(self.stances.wait)", but "getStance", but then checked weapons.lua and there is no such function, and i'm kinda not much good with lua to patch weapons file for a new function.

    So i decided to go different way and erase cooldown and statsPositive checks from it, nailing it down to
    Code:
      if self.weapon.currentAbility == nil
         and self.fireMode == "alt"
         and status.overConsumeResource("energy", self.energyUsage) then
    , yet this didn'ty work either.

    Then, after a few logical chains in my brain, i've reached such a code
    Code:
    if self.weapon.currentAbility == nil or self.weapon.currentAbility == "myability"
         and self.fireMode == "alt"
         and self.cooldownTimer == 0
         and status.overConsumeResource("energy", self.energyUsage) then
    aaaand this kinda worked. Character started using it non-stop.

    I realized i forgot to enclose or statement, so now i have
    Code:
    if (self.weapon.currentAbility == nil or self.weapon.currentAbility == "myability")
         and self.fireMode == "alt"
         and self.cooldownTimer == 0
         and status.overConsumeResource("energy", self.energyUsage) then
    and sadly it doesn't work...

    Cooldown is pretty small and removing this check does nothing so i left it be. Any ideas what i overlooked? What does "self.weapon.currentAbility" stand for? I mean is it currently active ability's name or primary/secondary(alt)?
     
  2. Zaakari

    Zaakari Zero Gravity Genie

    Could you please clarify what exactly isn't working properly? (windup and dash, but no delay?)
    I did some poking around, and it looks like "currentAbility" holds the actual ability object currently being used (or nil, if no weapon ability is in use). What's this "ability object" you ask? Good question. I'm not sure; but know, at least, that it isn't a string.
    It took a few files before I found its assignment (or, where I think it's getting assigned), but it appears to be assigned in the file "/items/active/weapons/weapon.lua", on line 96 (in the function Weapon:setAbilityState).
     
  3. lerdarim

    lerdarim Void-Bound Voyager

    The ability has 3 stances - windup, dash and wait. While the ability is being cast, you can't attack or recast that ability. Usually you can't control movement, too. I needed to keep all those restrictions, but allow to use this same ability to be used earlier, when it hits "wait" stance. So it would be chained into several ability uses without extra "wait" time, but when you decide to stop using it, you have to wait that "wait" time.
     
  4. Zaakari

    Zaakari Zero Gravity Genie

    All right, sorry for the delay, but I think I have what you want.
    It seems you were very close, and had I known more about weapon abilities, I probably could have answered sooner.

    Enabling Ability Reuse:
    So, you were correct in noting that there is no weapon function "getState".
    However, I had a look at the "weapon.lua" asset, and checked to see what "WeaponAbility:setState" was doing.
    It turns out that it calls "Weapon:setAbilityState", and in that function is the following line:
    Code:
    self.currentState = state
    I wasn't sure what exactly "state" was at that point (whether it was a string or an object or something else), so I went to my custom weapon ability's Lua file and added the following line to the update function:
    Code:
    sb.logInfo("state: " .. tostring(self.weapon.currentState))
    Long story short, the weapon's "currentState" is a reference to a function--in my case either nil (if the ability is not being used), TestSlash:windup, TestSlash:dash or TestSlash:wait).

    Using that bit of knowledge, I added an elseif section to the update function that looks like this:
    Code:
    function TestSlash:update(dt, fireMode, shiftHeld)
      WeaponAbility.update(self, dt, fireMode, shiftHeld)
    
      self.cooldownTimer = math.max(0, self.cooldownTimer - self.dt)
    
      if self.weapon.currentAbility == nil
         and self.fireMode == "alt"
         and mcontroller.onGround()
         and self.cooldownTimer == 0
         and not status.statPositive("activeMovementAbilities")
         and status.overConsumeResource("energy", self.energyUsage) then
    
        self:setState(self.windup)
      elseif self.fireMode == "alt"
        and self.weapon.currentState == self.wait
        and status.overConsumeResource("energy", self.energyUsage) then
    
        self:setState(self.windup)
      end
    end
    This causes the ability to be usable as long as the ability is in no state (nil) or in the wait state.
    All that to say, you were very close to what was required.

    Disabling Movement:
    In order to make the player unable to move during the wait stance, I had to add a "movementSuppressed" control modifier.
    (which was just a guess, by the way. I saw that the windup state had a "jumpingSuppressed" control modifier, so I tried "runningSuppressed", "walkingSuppressed" and then "movementSuppressed")
    Code:
    function TestSlash:wait()
      self.weapon:setStance(self.stances.wait)
    
      util.wait(self.stances.wait.duration, function(dt)
        mcontroller.controlModifiers({--jumpingSuppressed = true,
                                      --runningSuppressed = true,
                                      movementSuppressed = true})
      end)
    end
    I left "jumpingSuppressed" and "runningSuppressed" in as comments, because they are also valid values which could be used, if desired (although, "movementSuppressed" covers both of them).

    In case any of this is unclear, I have also attached a 7zip file containing an unpacked mod that showcases all of this.
    Just spawn the item "testBlade", and use its alternate ability.
     

    Attached Files:

  5. lerdarim

    lerdarim Void-Bound Voyager

    Oh, yay, thanks a lot for digging into this. I really appreciate it, though earlier today i've accidentally noticed the "currentState" variable in uninit func and tried it out and it worked perfectly :D. Although i'm a step ahead in my problems now. I went even further and implemented another state called "window", which is essentially the same as "wait", but player can recast an ability only in "window" state, so it's literally a window :) But problem is, abilities trigger on RMB hold, not on RMB click, so if you hold RMB you don't miss that window and it casts itself multiple times. Question is - how can i set an ability to be used on RMB Press, not Hold?

    Also, i've asked that in another topic but i'll repeat myself here, since you've touched movement suppression. How can i force crouching in some state? So the player character would crouch while in wait state. I know there is "mcontroller.controlCrouch()" function which essentially does that, but it doesn't seem to work together with "mcontroller.controlModifiers", so you either don't crouch, or you do, but you can move freely in wait state, breaking the crouch, too. I was wondering how can i combine them both.
     
  6. Zaakari

    Zaakari Zero Gravity Genie

    The code I gave under "Enabling Ability Reuse" allows you to reuse the ability on RMB press.

    As for the crouching, I'm not sure. I guess crouching is considered movement, hence "movementSuppressed" disabling crouching.
    I tried a bunch of crouch-related values in the "controlModifiers" function, but nothing worked. Sorry.
     
  7. lerdarim

    lerdarim Void-Bound Voyager

    I bet you don't understand me correctly. By RMB Press i mean exactly mouse button click, not holding down. Y'know, like combo attacks on primary ability. If you hold lmb, you just grind one attack, but if you click repeatedly, you produce a bunch of diffrent animations.
     

Share This Page