Custom Formulae and Scripts

So I have been talked into following up my last tutorial with another one. This one will be expanding on the previous one by going in to building upon the default scripts. First I want to talk about why you would do this and then go through a few worked examples.

One reason you might want to extend the default scripts for a formula could be the case that what you want to achieve doesn’t fit in the custom formula box. This is pretty easy to accomplish. Next up, you want to build in a default formula. I know that you can just use the same formula in every skill but I personally consider that bad practice. What if you discover your formula doesn’t act as you intended later in the game, fancy re-databasing all the skills and items? Or you want to create states that do different things to the formulas. We’ll be covering all that in this tutorial.

Let’s start by quickly analysing the formula box itself; as I’m sure you are aware a refers to the the attacker or user and b refers to the defender or recipient, now a and b refer either to an instance of Game_Actor or Game_Enemy. A quick glance at this class diagram shows us that both inherit from Game_Battler (which in turn inherits from Game_BattlerBase).

Why was that important? Simple because we have to decide where we are going to place our new bits of code. Personally I would recommend one of three places:

  • Game_Battler
  • Game_BattlerBase
  • A new Module

A module might in many ways make the most sense but being as I’m aiming this tutorial at people with limited scripting experience I’d rather avoid modules. Also if the code is added in Game_Battler we can directly access more variables directly (which suits me). So if we go to Materials in the script editor and insert us a new section then we need to add the code to add to the class:

class Game_Battler < Game_BattlerBase

end

Right next lets get down to examples. First let’s go through how to use a formula that’s too big for the box. Next let’s add a new method:

class Game_Battler < Game_BattlerBase
  def custom_formula_fireball

  end
  
end

If you don’t consider yourself to be a scripter then the easiest thing for you would probably be to enter the formula exactly how you would have in the custom formula box. Good news, we can do that. What we need to do is pass our new method the a,b from the custom formula. So this is what we’re upto:

Custom Formula Box:

 a.custom_formula_fireball(a,b)

Note: b.custom_formula_fireball(a,b) would be equally valid.

Script Editor:

class Game_Battler < Game_BattlerBase
  def custom_formula_fireball(a,b)

  end
  
end

So all that leaves us to do it put the formula in the method. I’m going to use the gambler example from the previous tutorial:

class Game_Battler < Game_BattlerBase
  def custom_formula_fireball(a,b)
    c=1+rand(6);d=1+rand(6);if c==1 and d==1;10000;elsif c==d;c*400;else;(c+d)*100;end;
  end
  
end

So that’s how to bypass the length limit on the custom formulae. If that’s all you’re interested in then you can stop here. I’ll be carrying onto covering adding a default formula and manipulating it.

I’m not going to cover anything to do with developing your formula I’m just going to show you how to implement it, here’s the formula I was using in my last game:

class Game_Battler < Game_BattlerBase
  def basef(a,b, magic = false)
    if magic
      return ([a.mat / 5, a.mat-b.mdf].max * (a.mat ** 0.5)).to_i
    else
      return ([a.atk / 5, a.atk-b.def].max * (a.atk ** 0.5)).to_i
    end
  end
  
end

First thing I’m going to point out is that I also pass a boolean (true or false) to the method to define whether it’s a magic attack or a physical one. You could do the same if you wanted. Just an example on the custom formula box:

a.basef(a,b,true)

Anyway the main reason for doing this is so that if you find your formula doesn’t work well later in the game you’ll only have to change it once. You can also simplify formulas if you wanted by making more methods. So for example in my last ill-fated game I had a character who could heal but I didn’t want him to be a dedicated healer so I made all his heals inflict statuses (with the turns they lasted reflecting the power of the heals) and if a character was affected by one of these statuses they only received half-healing. So the method I made looked like this:

def sorcery_healing?
  return state?(51) || state?(52) || state?(53)
end

My healing skill custom formulae looked a little like this

b.sorcery_healing? ? 100 : 200

Any how that just about concludes everything I wanted to cover in this tutorial, I hope it helped you.

8
  

30 comments

  1. Darn you Fomar. I was going to try and avoid doing any scripting, but this tutorial gave me so many ideas that I’m going to end up scripting now.

    Seriously though this is great. I assume this is how you made the Barehand script (I don’t have it in front of me at the moment).

    • Fomar0153 says:

      Yeah the last bit of the tutorial was how I made my barehand script. Glad you enjoyed it!

  2. DionisioVega says:

    Thanks for this, it explains why my attempts to do just this failed horribly… never used the class Game_Battler < Game_BattlerBase…
    Once again, thanks.

  3. DionisioVega says:

    Got one more question for you, will we still be able to use stuff like:
    a.weapons.include?($data_weapons[1])
    in the separate script, or do we have to pass that information?

  4. Xypher says:

    with the

    def sorcery_healing?
    return state?(51) || state?(52) || state?(53)
    end

    would it be possible to set that up with certain enemies so it would reflect something like

    def boss?
    enemy_id || enemy_id || enemy_id
    end

  5. Xypher says:

    Ahh, wasn’t expecting an answer so soon, Thank you.

    Just wondering, what does the “@” do.

    • Fomar0153 says:

      It just means it’s an instance variable.

      local variables have no symbol
      instance variables use @
      global variables use $
      and @@ means it’s a class variable

  6. Xypher says:

    It is possible to show an image using a custom formula?

    I tried
    screen.pictures[1].show(“123″, 0, 0, 0, 100, 100, 255, 0)
    and
    $game_troop.screen.pictures[1].show(“123″, 0, 0, 0, 100, 100, 255, 0)

    but neither worked.

    • Xypher says:

      I found out that the $game_troop.screen.pictures[1].show(“123″, 0, 0, 0, 100, 100, 255, 0) and it was the $game_troop.screen.pictures[1].erase was causing it to be immediately erased, so my problem is now adding a wait to the script, however when i do that it doesn’t process the rest of the script.

      • Fomar0153 says:

        hmm maybe add:
        SceneManager.scene.abs_wait(60)
        or put the erase in a common event and add a wait in that.

  7. Xypher says:

    Awesome, the SceneManager.scene.abs_wait method worked.
    Thanks.

  8. Xypher says:

    Is it possible to change the scope of a skill from a formula script?

    • Fomar0153 says:

      No, the scope will have already been used to determine targets before damage calculation.

  9. Livera says:

    Hi fomar, I have a few question:
    1. What’s to_i and to_f?
    2. If I want to make skill to add state/buff/debuff to unknown recipient (either ally or enemy) and I make a script like lhis:
    def state_add(a, c, d)
    if rand(100) < d
    a.add_state(c)
    end
    end
    And then I wrote in the formula box: a.state_add(b, 5, 10). My question is, if rand(100) is less than 5, does the target (b) inflicted by state 5 (confusion)? Or is it the user(a)?
    Sorry if the question is a bit dumb…

    • Livera says:

      Sry, I mistyped something.
      “If rand(100) is less than 5, does the target (b) inflicted by state 5 (confusion)? Or is it the user(a)?”
      is supposed to be:
      “If rand(100) is less than 10, does the target (b) inflicted by state 5 (confusion)? Or is it the user(a)?”

    • Fomar0153 says:

      .to_i makes a number an integer e.g.
      “23″.to_i => 23
      23.5.to_i => 23
      23.to_i => 23
      .to_f makes a number a float e.g.
      23.to_f => 23.0

      If I understand right you want to confuse the target or the user:
      if rand(100) < 10; a.add_state(5); else; b.add_state(5); end;
      Then put the damage formula on the end.

      • Livera says:

        Ooh I see… so that’s how it works :D
        For the second question, it’s not really what I meant, but since I decided not to use it, so you can just ignore it :)
        Thank you, by the way

      • Livera says:

        Hi Fomar, sry it seems that I have another question.
        I want to make a skill that increase number of attack to X times. Is there anyway to make it? Because not all actor/weapon only attack once, I can’t add additional attack by 2. Is there any script to modify number of attack?
        Thx once again

        • Fomar0153 says:

          I don’t keep a particularly good track of other scripter’s scripts.

          • Livera says:

            Umm, I think I wrote it wrong… it suppose to be: “Is there any way to modify number of attack?”. Because I can only get number of attack using atk_times_add, is there any way to change number of attack with custom formula?

          • Fomar0153 says:

            No, look for individual weapon attack skills or something.