RMXP - How to create states with temporary stat boost?

Started by nazra7, May 26, 2016, 02:52:58 pm

Previous topic - Next topic

nazra7

Hello everyone, I am currently working on a commercial strategy rpg using RPG Maker XP that will be similar to Final Fantasy Tactics. In FFT, there are stats that give temporary stat boosts when you take damage called Speed Save, PA Save, ect. I'm trying to make a state like this where, for example, the state will raise the battler's agility stat by 25% of the damage caused each time it takes damage while afflicted with this state. I am able to script this state, but I only know how to add PERMANENT stat increases rather than TEMPORARY stat increases. In Game_Battler 3 script, I'm adding this code which works, but again, it only gives a permanent stat increase instead of a temporary stat increase:

#if Agility Save State
if self.state?(214) #< Agility Save State ID (I know, my game has a TON of states)
self.animation_id = 635 #< Temporary Agility Gain Animation
self.agi += self.damage / 4 #< Permanently increases agility by 25% of the damage caused, need it to be a temporary increase instead
end


I think I can do this, and please correct me if I'm wrong, if I can make a new local variable for each battler, both actors and enemies, that stores a temporary stay gain, something like this:

#if Agility Save State
if self.state?(214) #< Agility Save State ID (I know, my game has a TON of states)
self.animation_id = 635
self.tempagi += self.damage / 4 #< self.tempagi is the new local variable which stores temporary agility gains/losses
self.agi += self.tempagiplus #< temporary stat increase
else
self.agi -= self.tempagiplus #< I know this won't work properly here since it will only trigger when skills are used and deal damage, but I'm putting this here just to make sure this code will correctly remove the temporary stat gain/losss
end


But when I use code I get a undefined method error for the variable tempagi. How do I make this variable a local variable that can be used in the code self.tempagi? Or if there is a better way to make a temporary stat gain like this, please let me know.

Any advice will be greatly appreciated! Thanks in advance.

KK20

I'm not sure how much programming experience you have, so I'll try to make it straight to the point.

For starters, whenever you do self.SOMETHING, you're specifically calling the self's class method, which are the def SOMETHING. A variable is represented with @SOMETHING. You might have noticed in Game_Battler 1 in the initialize method @animation_id. In your sample code, you can use @animation_id instead of self.animation_id and the result would be the same.

But why? You might have noticed this line:
  attr_accessor :animation_id             # animation ID

attr_accessor essentially creates a GET and SET method for the variable @animation_id. Something like this:

def animation_id
  return @animation_id
end

def animation_id=(id)
  @animation_id = id
end

This is useful when you want to access this variable OUTSIDE of the Game_Battler class.

The reason for your self.tempagi error is because you didn't define a tempagi method. The first thing you think would work would be to add this line to Game_Battler

attr_accessor :tempagi

...but not just yet. @tempagi will have a value equal to nil (equivalent of null in other languages), so it will error when you try to add a number to it in your += operator. So we need to initialize it. If you're just editing the default RMXP scripts (which isn't really recommended unless you know what you're doing), then just add this to the bottom of Game_Battler#initialize:
@tempagi = 0

Now you're in business. If we're just using this variable inside the Game_Battler class and don't need it anywhere else, working with @tempagi is fine--as long as you change self.tempagi to @tempagi, you can remove the attr_accessor.


As for your idea, it is logical and correct. You will need to create another variable to keep track of this temporary addition to the actor's stat. What I don't agree with is the addition to self.agi, which will add onto the equipment stat bonuses variable (you will definitely want to keep these two separate). You will want to change one line in your Game_Battler#agi method to something like this:
n = [[base_agi + @agi_plus + @tempagi, 1].max, 999].min

And then you can change your else-block in your sample to
@tempagi = 0


With that, your code should be good to go. Hopefully you can pick up Ruby relatively quickly--to be determined in making a commercial game without it would be disastrous.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

nazra7

Sorry for the late reply, and thanks very much! That was very helpful. It took a little bit but I've got it working. I only have one problem now. I want to set all of the battlers' temp stats back to zero when a battle ends. I'm using a tactics based custom battle script. So I used this to try to set temp stats back to zero:

   #(I tried using just "actors + enemies" and "$game_system.actors + $game_system.enemies" instead, but both produced errors. Neutrals are a new battler type made by the custom battle system)

    for battler in $game_system.tactics_actors + $game_system.tactics_neutral + $game_system.tactics_enemies
    @tempmaxhp = 0
    @tempmaxsp = 0
    @tempstr = 0
    @tempdex = 0
    @tempagi = 0
    @tempint = 0
    end


And it works when I put in the Game_Battler 3 script with the rest of my custom states, but it won't work when I put it where the script ends the battle in the battle scene script. In the battle system I'm using, it replaces the "def battle_end(result)" in the default scene_battle scripts with "def end_battle(result=0)" in its own battle scene script. I tried putting the above code in there and it doesn't work for some reason. It doesn't produce an error, but when the battle ends, the temporary stat bonuses don't get set back to zero, they just stay the same. I tried making it produce an error just to see if that part of the script is even being used, and it successfully produced that error, so I don't know why it's not working. Here is what it looks like right now:

  #----------------------------------------------------------------------------
  # Exit Battle
  # result: 0-win, 1-lose, 2-escape
  #----------------------------------------------------------------------------
  def end_battle(result=0)
    RPG::BGM.fade(400)
    @battle_exiting = true
    @cursor_active = false
    @tbs_phase = 8
    for window in @windows.values
      unless window == nil
        window.visible = false
        window.active = false
      end
    end
    @result_phase = 0
    if result == 1 and $game_troop.can_lose? == true
      update_scene
    else
      for battler in actors + neutral + enemies
        battler.clear_tbs_actions(true)
      end
      $game_party.remove_states_battle
     
    for battler in $game_system.tactics_actors + $game_system.tactics_neutral + $game_system.tactics_enemies
    @tempmaxhp = 0 #(tried making this = gibberish to make sure it produces an error correctly, and it does)
    @tempmaxsp = 0
    @tempstr = 0
    @tempdex = 0
    @tempagi = 0
    @tempint = 0
    end
     
    end   
    if $game_temp.battle_proc != nil
      $game_temp.battle_proc.call(result)
      $game_temp.battle_proc = nil
    end
  end
 


If you could let me know what I'm doing wrong, I'd greatly appreciate it!

KK20

Are your tempSTAT variables defined as attr_accessor ? If so, you will need to change your assignments to
battler.tempSTAT = 0

By just doing @tempSTAT, your code assumes that there is a variable in Scene_Battle (or whatever the battle system class is called) named tempSTAT and assigns it to that.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

nazra7

Thanks very much. It's all working properly now. :haha: I'm learning ruby little by little. I'm more used to C++ but this is totally different.