Jump to content
  • entries
    65
  • comments
    526
  • views
    68,800

A sorta Final Fantasy 2/SaGa stat leveling system.

Kayzee

172,622 views

Here is a little script I was working on for my test game made to count tallies when each stat is used and randomly raise them after battle. It's kinda like the stat leveling system in Final Fantasy 2(j) and the SaGa series, but it works a bit differently.

 

Mostly it is different in that experience levels still exist and are used both to determine your max over all stat level, and whenever you gain a level you get a big random boost to your stat tallies. The actor class's stat growth curves also determines how much each stat level is worth.

 

Anyway the basic idea for how it works is stat tallies are used as percent chance that that stat will level up after battle, so if a stat is tallied 100 times it will always level up, but if it is tallied only 10 times you have a 10% chance. Tallies are remembered across battles but the level up chance only happens at a battle's conclusion. If a stat is leveled up a flat 100 is subtracted from the tally, and it can go into the negative. This practically means stat increases are random but predictable over a large period of time, and since your level acts as a cap for how many stat increases you can have and your class acts to show how many each are worth, the fact that the stats always grow at the same rate is not as important.

 

It's probably not going to be useful for most people's needs since it doesn't try to exactly match the system used in the old games, and is mostly me just experimenting with the mechanics. It might be useful as a base if anyone wants to do something similar though!

 

Here is the script:

 

 

module BattleManager
  #--------------------------------------------------------------------------
  # * EXP Acquisition and Level Up Display
  #--------------------------------------------------------------------------
  def self.gain_exp
    $game_party.all_members.each do |actor|
      actor.gain_exp($game_troop.exp_total)
      actor.param_level_up
      wait_for_message
    end
  end
end

class Game_Battler < Game_BattlerBase
  alias_method :use_item_tally_base, :use_item
  
  def use_item(item)
    self.pre_tally
    use_item_tally_base(item)
    self.post_tally
  end
  
  alias_method :item_apply_tally_base, :item_apply
  def item_apply(user, item)
    self.pre_tally
    user.pre_tally
    item_apply_tally_base(user, item)
    self.post_tally
    user.post_tally
  end
  
  def pre_tally
    return
  end
  
  def post_tally
    return
  end
end

class Game_Actor
  attr_reader :total_tally
  
  alias :th_param_level_setup_actor :setup
  
  def setup(actor_id)
    th_param_level_setup_actor(actor_id)
    @param_growths = [0] * 8
    @param_levels = [@level] * 8
  end
  
  def pre_tally
    @old_hp = @hp
    @old_mp = @mp
    @total_tally = 0
    @param_tally = true
  end
  
  def average_param_level
    @param_levels.inject(0) { |sum, el| sum + el } / 8.0
  end
  
  def grow_param(param_id, amount)
    x = amount * (@level / @param_levels[param_id].to_f)
    if @param_growths[param_id] < 0 || average_param_level <= @level
      puts(self.name + ":" + Vocab::param(param_id) + ":" + x.to_s) if $TEST
      @param_growths[param_id] += x
    end
    @total_tally += x
  end
  
  def post_tally
    x = ([(@old_hp - @hp) / self.mhp.to_f, 0].max * 5).ceil
    grow_param(0, x)
    x = ([(@old_mp - @mp) / self.mmp.to_f, 0].max * 5).ceil
    grow_param(1, x)
    @param_tally = false
  end
  
  def param_base(param_id)
    self.class.params[param_id, @param_levels ? @param_levels[param_id] : @level]
  end
  
  alias_method :param_tally_base, :param
  
  def param(param_id)
    if @param_tally && param_id > 1
      grow_param(param_id, 1)
    end
    return param_tally_base(param_id)
  end
  
  alias :th_param_level_level_up_actor :level_up
  def level_up
    th_param_level_level_up_actor
    8.times do |i|
      @param_growths[i] += rand(100)
    end
  end
  
  Param_Message = "%s's %s has increased by %s points!"
  def param_level_up
	puts self.name + " growth:" if $TEST
    avr = average_param_level
    puts "level: " + @level.to_s if $TEST
    puts "average param level: " + avr.to_s if $TEST
    return unless avr <= @level
    8.times do |i|
      #next unless @param_levels[i] <= @level
      if @param_growths[i] > 0 && (rand(100) - @param_growths[i]) <= 0
        @param_levels[i] += 1
        @param_growths[i] -= 100
        difference = self.class.params[i, @param_levels[i]] - self.class.params[i, @param_levels[i]-1]
        $game_message.add(sprintf(Param_Message, self.name, Vocab::param(i), difference))
      end
      puts(Vocab::param(i) + " Level:" + @param_levels[i].to_s +
            " Growth:" + @param_growths[i].to_s) if $TEST
    end
  end
  
end
 

 

  • Like 4


27 Comments


Recommended Comments



That sounds interesting, reminds of those extra stats in pokemons.

 

So if you have 10 tallies (10% chance), and it levels up, then it will become -90 tallies?

Share this comment


Link to comment

Dohoho, I was actually planning to make something like this (for a game that focuses on a non linear plot, the sort of battle system fits well for it me thinks) after checking out the SaGa series, after seeing you speak fondly of it. Guess I'll use it as base since I'm planning to increase a stat, after a successful hit of a certain skill, after battle to a certain cap.

Share this comment


Link to comment

That sounds interesting, reminds of those extra stats in pokemons.

 

So if you have 10 tallies (10% chance), and it levels up, then it will become -90 tallies?

Yeah, and when it's negative you don't get a level up chance until it's positive again. So basically the maximum gap between level ups is 200 or so tallies if you get lucky and level up at 1% chance, pay the 99 tally duet and somehow are unlucky enough that you have to build your tally's up to 100 again before you level up. Although I am pretty sure using healing skills at the menu builds your tallies too without giving you a chance to level up. I did actually experiment with letting you build your stats and stuff from the menu but it was as part of a larger script. I suppose if you wanted to you could also get rid of the actor.param_level_up in the BattleManager's gain_exp method and call it manually whenever you go to sleep or something.

 

Dohoho, I was actually planning to make something like this (for a game that focuses on a non linear plot, the sort of battle system fits well for it me thinks) after checking out the SaGa series, after seeing you speak fondly of it. Guess I'll use it as base since I'm planning to increase a stat, after a successful hit of a certain skill, after battle to a certain cap.

Yeah I really like the SaGa series a ton! A good many of them are Japanese only though sadly. Games with non linear plots and a skill/stat based leveling system are pretty neat if you ask me. :3

  • Like 1

Share this comment


Link to comment

I didn't know what this meant until just today, when I realized that the SaGa series are remakes of Final Fantasy Legend (at least that's what they were called in America). I grew up with Legend 2, so this appeals to me greatly. In fact, I was just thinking about how I might make a game like that. Thanks, Kayzee!

Share this comment


Link to comment

Hehehe well actuality the first three SaGa games were released on gameboy and translated as Final Fantasy Legend, the next three were the Romancing SaGa games on SNES and were never released over hear, but the next games in the series, the Playstation games SaGa Frontier and SaGa Frontier 2, as well as the PS2 game Unlimited SaGa, were, but didn't do that well. The next game was a remake of the first SNES game for the PS2 called Romancing Saga: Minstrel's Song was released over here but also didn't do too good. So after that the DS remakes of SaGa 2 and SaGa 3 were just never released over here because they figured no one liked the games. :/

 

I have played and liked every single one. :3 I should warn you though if you want to play them that the Romancing SaGa games changed up the formula a lot and it never really went back to the old style of gameplay until the DS remakes. The same kinda stat building is mostly the same but they did away with all the different races and the way weapons and skills work is way way different.

 

I like SaGa Frontier the best out of all of them though, it has all the different races (in one form or another) like the classic SaGas but has the more refined gameplay of the Romancing SaGas, and a lot of special twists of it's own. Romancing SaGa 3 is probably the second best, but I have a soft spot in my heart for Romancing SaGa 2 (even if it was never properly translated to my knowledge) for the generation-based gameplay and Unlimited SaGa (which most people hate, and I admit there are a ton of things wrong with it) for it's weird tabletop D&D feel.

 

But I could go on all day talking about the SaGa games. They may not be the best really, but I like um anyway. :3

Share this comment


Link to comment

This sounds pretty cool.  I wish I had the time to develop all ideas I get from scripts into projects.

Share this comment


Link to comment

If I wanted to simply reset tallies for a parameter (rather than the current behaviour of subtracting 100 no matter when it grows), would I just need to replace '@param_growths -= 100' with '@param_growths -= @param_growths'?

 

Not sure if I will or not until I test it, but I'd just want to check if that's all I'd need to change.

Share this comment


Link to comment

I would say '@param_growths = 0' actually.

 

Keep in mind though, I subtract 100 because I make level ups happen randomly. If I didn't actors could theoretically level up their stats every other battle, though granted the chances would be really really low. But subtracting a flat 100 means you need to use at least 100 tallies between each level up. You get a tally of 10 you get a 10% chance to get a level up, but if you do you have to use 90 tallies to get a change to level up again. 50 tallies means a chance of 50%  and you only have to pay 50 tallies, and 100 tallies a chance of 100% means you don't have to pay any.

Share this comment


Link to comment

O_O OMYGOSH You had it!? I was looking for this for ACE like forever!!

ended up getting help from Siggy instead o-ob

But i will try to look for it for sample later, thanks! :D

Share this comment


Link to comment

Hehe, it's not an exact version of what FF2 or the SaGa games do though. I would have to do more research and possible disassembling to do that. Also at least half the SaGa games rely more on raising weapon/magic skills then leveling up stats. I think it's a good base for a semi-random tally-based growth system though!

  • Like 1

Share this comment


Link to comment

Really? I believe it shows on Line 66 about empty [] or something O_O

Gotta try again but this time, starting a new game.

(previously I tried loading the game)

 

oh wait, do I have to install it below materials and above main or somewhere else?

Share this comment


Link to comment

Yeah, that would probably do it. Loading games means the tally array vars are nil. Sometimes I try to do some ||= trickery to get around that but not this time it seems.

Share this comment


Link to comment

Uh... I should probably shorten or replaces \|s with \.\.s or plain \. instead ._.a

Hold on, still trying to do it ._.

 

edit : Thanks, it works now! :D

 

By the way, how did the logic works in this script?

I mean, did it work for agility, luck, matk and mdef as well?

Share this comment


Link to comment

Yeah it works for every stat! Baaasicly, when you use a skill it goes into "tally mode" and remembers every call to each stat function and remembers how many time it was called. Also counts how many hp or mp you lose. Then when the battle is over it counts them all up and uses them for a chance of doing a level up in that stat.

  • Like 1

Share this comment


Link to comment

Uh, quick question :

When you raised your STR once, will it take over 100 times attacking again in order to get even more STR?

I've tried it for some time grinding, first STR raising went fine, but after some (20 minutes grinding) times, it won't raise anymore o_oa

Share this comment


Link to comment

The way I did it is that you need at least 100 tallies between stat ups yes... also your exp levels effect your stat caps. I didn't want to let the player level up too quickly. Though you don't raise stats by single points each time, you raise it by one level's worth of points. I have been wondering for a while if I should make you level up point by point and only use the class/level thing as a cap, or maybe not at all?

 

Like I said it's not an exact version of what FF2 or the SaGa series does, it's just a similar type of thing. I think the basic idea can be tweeked to what you want though. In particular, in this script experience levels still mean something, and in a real FF2 or SaGa series system experience levels would not exist (though I think the SaGa series has a concept of an over all "battle level" that effects your stat growth and what encounters you get).

Share this comment


Link to comment

Whoa. :o

So that means...

More time the player will 'spend' their time levelling their stats for a looooong time.

Hey, I might add some or more crafting system or gathering so they won't be just focused on the battle then >:D

 

Thanks then :3b

 

*sit and watch beta testers were 'taking their times doing intense levelling' while laughing in the background*

Share this comment


Link to comment

Hehe, well I didn't want to make it too easy to do! It doesn't really take that much longer then normal leveling up I think. I even have a random bonus when leveling up too.

  • Like 1

Share this comment


Link to comment

×
Top ArrowTop Arrow Highlighted