Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
Faellin

Working on a leveling system

Recommended Posts

Its quite simple. Most characters are going to get an option to upgrade classes upon reaching a certain level, by visiting a certain spot in the game depending on their class. Their improved class is going to gain access to new abilities, higher stats and the ability to weild super weapons you will find throughout the game.

 

I'm just wondering how I should end up setting this event sequence. Any ideas?

 

And as a note, there are going to be several characters for each class type. Each having a focus on different stat types, weapon skils, and whatnot.

Share this post


Link to post
Share on other sites

This may help you take a look. This is a Class system based on an online game called Ragnarok.

 

 

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# RO Job/Skill System by Blizzard
# Version: 2.2b
# Type: Ragnarok Online Job/Skill System Clone
# Date: 5.11.2007
# Date 1.0b: 4.1.2008
# Date 1.01b: 4.1.2008
# Date 1.2b: 26.1.2008
# Date 1.3b: 2.6.2008
# Date 1.4b: 8.6.2008
# Date 1.5b: 6.8.2008
# Date 1.6b: 23.11.2009
# Date 2.0b: 17.2.2010
# Date 2.01b: 4.9.2010
# Date 2.1b: 22.1.2011
# Date 2.2b: 22.6.2012
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#   
#  This work is protected by the following license:
# #----------------------------------------------------------------------------
# #  
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# #  
# #  You are free:
# #  
# #  to Share - to copy, distribute and transmit the work
# #  to Remix — to adapt the work
# #  
# #  Under the following conditions:
# #  
# #  Attribution. You must attribute the work in the manner specified by the
# #  author or licensor (but not in any way that suggests that they endorse you
# #  or your use of the work).
# #  
# #  Noncommercial. You may not use this work for commercial purposes.
# #  
# #  Share alike. If you alter, transform, or build upon this work, you may
# #  distribute the resulting work only under the same or similar license to
# #  this one.
# #  
# #  - For any reuse or distribution, you must make clear to others the license
# #    terms of this work. The best way to do this is with a link to this web
# #    page.
# #  
# #  - Any of the above conditions can be waived if you get permission from the
# #    copyright holder.
# #  
# #  - Nothing in this license impairs or restricts the author's moral rights.
# #  
# #----------------------------------------------------------------------------
# 
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# 
#   Special Thanks for requesting this goes to Nightfox!
# 
# 
# new in 1.0b:
#   - fixed font problem
#   - now beta
# 
# new in 1.01b:
#   - fixed a crash problem where enemies would be tested on skill levels
# 
# new in 1.2b:
#   - actors can now learn Chaos Drive transformation skills through this
#     system (REQUIRES CRLS 5.0 OR HIGHER)
#   - classes/jobs now can have stat modifiers
# 
# new in 1.3b:
#   - skills can now have other skills as requirements
# 
# new in 1.4b:
#   - added option to hide skills that haven't met the prerequisites yet
#   - improved coding and the way data display is being refreshed
# 
# new in 1.5b:
#   - fixed bug with forgetting skills
#   - added option to forget all skills from other classes when changing the
#     class
# 
# new in 1.6b:
#   - now more compatible with Blizz-ABS 2.57
# 
# new in 2.0b:
#   - fixed bug where HP/SP wouldn't apply when the max HP/SP were decreased
#   - fixed bug with skill usage when JOB_ONLY was not active
#   - now more compatible with Blizz-ABS 2.7
#   - improved coding
# 
# new in 2.01b:
#   - fixed bug when activating JOB_ONLY
# 
# new in 2.1b:
#   - fixed a few small problems with Blizz-ABS
# 
# new in 2.2b:
#   - fixed a the bug where during actor parameter testing the class of the
#     dummy actor would change and unequip equipment
#   - fixed crash bug that could occur when trying to change the class again
# 
#   
# Compatibility:
#   
#   95% compatible with SDK v1.x, 60% compatible with SDK v2.x. Can cause
#   incompatibility issues with other exotic Skill Systems, CMS-es and CBS-es.
#   Fully compatible with Blizz-ABS, not compatible with Mr. Mo's ABS. WILL
#   corrupt old savegames.
# 
# 
# Explanantion:
#   
#   This script allows you to use a skill system that is very similar to the
#   skill system of the MMORPG Ragnarok Online. By gaining jobs and job levels
#   the characters get points which they can use to learn and make skills
#   stronger. Stronger skills have a higher numerical effect and lower SP cost.
#   This script also allows the usage of a job change system.
#   
#   
# Features:
#   
#   - job/class level and and change system
#   - skill level system that can be turned off as well
#   - gain Job Points for each Job Level and use them to power up your skills
#     or learn new ones
#   - increased SP cost and decreased skill power for skills that have not
#     been improved to the maximum level
#   - two fully functional scenes for class changing and skill
#     learning/improving
#   - easy setup and use
#   - compatible with Blizz-ABS and RTAB
#   - wide range of possible uses
#   
#   
# Instructions:
#   
# - How the system works:
#   
#   When a skill is learned, its power is less than 100%, its SP cost is higher
#   than 100% and its level is 1. To learn a skill only 1 JP (Job Point) is
#   needed. For every increase of the skill's level another JP is needed. When
#   the skill has reached its maximum level, the power is exactly 100% and the
#   SP cost exactly is 100%. Everything between is linearry distributed.
#   
#   Example:
#     Skill ID:       15
#     Min Lvl:         1
#     Max Lvl:        11
#     Lvl 1 Power:    20%
#     Max Power:     100%
#     Lvl 1 Cost:    150%
#     Min Cost:      100%
#   These would be the statistics of a skill at level 5:
#     Current Lvl:     5
#     Current Power:  52%
#     Current Cost:  130%
#   
# - Configuration
#   
#   INIT_JP      - initial number of Job Points
#   LVL1_POWER   - set this number to the percentage of the skill power a skill
#                  should have when having level 1
#   LVL1_COST    - set this number to the percentage of the CP cost a skill
#                  should have when having level 1
#   LVLUP_RATE   - if you have the feeling that you reach a job level to
#                  quickly increase this number or the other way around
#   EXP_RATIO    - this number determines the JOBEXP / EXP ratio in percents
#                  (i.e. if you set number to 144 and get 2000 EXP, you will
#                  get 2880 JOBEXP)
#   RESET_LVLS   - if you set this value to true, each skill that is forgotten
#                  will be completely deleted, the JP will NOT be returned, you
#                  have to do that manually
#   JOB_ONLY     - if you set this value to true, the skill level system will
#                  be turned off completely
#   USE_LEVEL    - if you set this value to true, the level required for a
#                  class change is not the current class' job level, but the
#                  real level
#   USE_ALL      - if you set this value to true, a character is not allowed to
#                  change his job as long as his JP are not zero, this creates
#                  virtually the impression that each class his its own JP
#   CLASS_SKILLS - if you set this value to true, all skills learned from one
#                  class will be removed, this option does not affect the game
#                  if the JOB_ONLY option is being used
#   HIDE_SKILLS  - if you se this to true, skills won't be displayed in the
#                  window where you can learn skills until all requirements are
#                  met
#   RO_RIGHT     - if you set this value to true, the windows in the scenes
#                  will appear at the right side
#   EVASION      - name displayed for the attribute "Evasion"
#   UP_COLOR     - color of text that displays increasing stats
#   DOWN_COLOR   - color of text that displays decreasing stats
#   CD_SKILLS    - if you are using CRLS and want actors to be able to learn CD
#                  skills through this system, you need to include all
#                  learnable IDs of CD skills so the system knows that those
#                  are not normal skills, but CD skills
#   
#   Press CTRL+F and type "START RO Skill Database" (without the double quotes)
#   and setup your skill database. The skills available for a job/class are the
#   ones you specify in your class database. The level required to be able to
#   learn a skill is now the job level. In other words, you need the given job
#   level to be able to learn that specific skill.
#   
# 
# Additional Informations:
#   
#   If you wish to call the class change scene, use a "Call Script" event
#   command and type following command into the window:
#   
#     $scene = Scene_ClassChange.new
#   
#   If you wish to call the job point distribution scene, use this command:
#   
#     $scene = Scene_SkillChange.new
#   
#   If you want to manually change a skill and/or job level/EXP, simply use:
#   
#     $game_actors[ID].skill_level_change(NUMBER, S_ID)
#     $game_actors[ID].job_level_change(NUMBER, C_ID)
#     $game_actors[ID].add_job_exp(NUMBER, C_ID)
#   
#   ID     - ID of the actor in the database
#   C_ID   - ID of the class in the database
#   S_ID   - ID of the skill in the database
#   NUMBER - numeric value
#   
#   If you leave out C_ID, the current class ID will be used. Keep in mind that
#   you can CHANGE skill and job level, but you can only INCREASE Job EXP.
#   You can also manually change the value of the Job Points.
#   
#     $game_actors[ID].jp = NUMBER
#   
#   Keep in mind that increasing the job level manually will cause that JP are
#   being increased as well while decreasing the job level will NOT cause the
#   JP to decrease.
#   Here are the formulas for new effect and cost calculation for reference.
#   
#     effect = ORIGINAL * (LVL1_POWER + (skill_level - 1) *
#              (100 - LVL1_POWER) / (skill_maxlevel - 1)) / 100
#     cost   = ORIGINAL * (LVL1_COST - (skill_level - 1) *
#              (LVL1_COST - 100) / (skill_maxlevel - 1)) / 100
#   
#   This is the formula for calculation of how much EXP are needed to reach
#   the next job level.
# 
#     EXP_needed_for_lvl(lvl) = LVLUP_RATE * lvl * (lvl - 1)
#   
#   
# Important note:
#   
#   If you use this system to learn CD skills, it is recommended that you leave
#   the skills' maximum level at only 1 as the consumption cost of the stats
#   cannot change in CRLS. CD skills also don't appear in the improvement
#   screen. Don't forget that you need to let the class be able to learn the CD
#   skills just like a normal skill. If you don't have CRLS installed, the
#   skill will be learned as if it was a normal skill.
#   
#   
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

# used for compatibility
$ro_jobskill_clone = 2.2

#==============================================================================
# module BlizzCFG
#------------------------------------------------------------------------------
#  This module serves for configuration in my scripts and for consistency.
#==============================================================================

module BlizzCFG
  
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  INIT_JP = 1
  LVL1_POWER = 50
  LVL1_COST = 200
  LVLUP_RATE = 20
  EXP_RATIO = 20
  RESET_LVLS = false
  JOB_ONLY = false
  USE_LEVEL = false
  USE_ALL = false
  CLASS_SKILLS = !false
  HIDE_SKILLS = false
  RO_RIGHT = false
  EVASION = 'EVA'
  UP_COLOR = Color.new(0, 255, 0) # (R, G, B)
  DOWN_COLOR = Color.new(255, 0, 0) # (R, G, B)
  CD_SKILLS = [61]
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

  def self.roskill_maxlevel(id)
    case id
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START RO Skill Database
# 
#   You can define the max level of each skill here. Use following template to
#   set up your configuration:
# 
#     when ID then return NUMBER
# 
#   ID     - the skill ID
#   NUMBER - the maximum level
# 
#   Note that using values lower than 1 WILL CAUSE BUGS! Default value is 1 and
#   skills that are not defined here will have the default value automatically
#   applied.
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    when 57 then return 5
    #when 61 then return 3
    when 62 then return 5
    when 63 then return 10
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END RO Skill Database
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    end
    return 1
  end
  
  def self.roskill_reqs(id)
    case id
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START RO Skill Requirement Database
# 
#   You have the option to make skills require not only a specific level, but
#   other skills and their levels as well. Such a skill will not appear in the
#   list of skills until all requirements are met.
#   Use following template to set up your configuration:
# 
#     when ID then return [[SKILL_ID1, MIN_LEVEL1], [SKILL_ID2, MIN_LEVEL2], ...]
# 
#   ID        - the skill ID
#   SKILL_ID  - ID of the required skill
#   MIN_LEVEL - minimum required level of the required skill
# 
#   You can add as many requirements as you want, separate them with commas.
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    when 2 then return [[1, 2]]
    when 62 then return [[61, 1], [63, 4]]
    when 3 then return [[1, 3], [2, 2]]
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END RO Skill Requirement Database
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    end
    return []
  end
  
  def self.rojob_maxlevel(id)
    case id
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START RO Job Database
# 
#   You can define the max level of each job here. Use following template to
#   set up your configuration:
# 
#     when ID then return NUMBER
# 
#   ID     - the class ID
#   NUMBER - the maximum level
# 
#   Note that using values lower than 1 WILL CAUSE BUGS! Default value is 1 and
#   jobs that are not defined here will have the default value automatically
#   applied.
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    when 1 then return 10
    when 2 then return 30
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END RO Job Database
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    end
    return 1
  end
  
  def self.rojob_next(id)
    case id
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START RO Job-Connection Database
#   
#   Here you can define job change trees. When you have one job active you can
#   change to any other job that is defined here. It is possible to define
#   recursive trees where a class can be changed back as well without problems.
#   Use following template to set up your configuration:
# 
#     when ID then return [[MIN_LEVEL1, NEW_ID1], [MIN_LEVEL2, NEW_ID2], ...]
# 
#   ID        - the current class ID
#   MIN_LEVEL - minimum level required to be allowed to change
#   NEW_ID    - the ID of the new class
# 
#   You can add as many next classes as you want, separate them with commas.
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    when 1 then return [[1, 2], [15, 3]]
    when 2 then return [[10, 1], [15, 3], [1, 4], [1, 5], [1, 6]]
    when 3 then return [[1, 2], [6, 7]]
    when 4 then return [[1, 2]]
    when 5 then return [[1, 2], [8, 6], [10, 8]]
    when 6 then return [[1, 2], [11, 3]]
    when 7 then return [[1, 2], [5, 1], [5, 4]]
    when 8 then return [[1, 2], [5, 7]]
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END RO Job-Connection Database
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    end
    return [[]]
  end
  
  def self.job_stat_mod(id)
    p_maxhp = p_maxsp = p_str = p_dex = p_agi = p_int = 0
    m_maxhp = m_maxsp = m_str = m_dex = m_agi = m_int = 1.0
    case id
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Job Stat Modifier Database
#   
#   You are able to set up modifiers for actor stats that change depending on
#   the current job. Use following template to set up your configuration:
# 
#     when ID
#       p_maxhp = PLUS
#       p_maxsp = PLUS
#       p_str = PLUS
#       p_dex = PLUS
#       p_agi = PLUS
#       p_int = PLUS
#       m_maxhp = MULTI
#       m_maxsp = MULTI
#       m_str = MULTI
#       m_dex = MULTI
#       m_agi = MULTI
#       m_int = MULTI
# 
#     ID    - the current class ID
#     PLUS  - an integer value (default is 0)
#     MULTI - a decimal value (default is 1.0)
# 
#   The values that have p_ before that name are static modifiers. For example,
#   if you use 100, then the given stat will increase by 100 if the actor has
#   the given class. If you use -200, then it will decrease by 200 from the
#   actor's basis.
#   The values that have m_ before that name are dynamic modifiers. For
#   example, if you use 1.1, then the given stat will increase by 10% if the
#   actor has the given class. If you use 0.8, then it will decrease by 20%
#   from the actor's basis.
#   
# Note:
#   
#   It might be a good idea to create a neutral class if you are using this
#   feature. If you don't set up a class here, then the default values will be
#   applied. Keep in mind that first all static modifiers will be applied and
#   afterwards the dynamic modifiers.
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    when 1
      p_maxhp = 100
      p_maxsp = -20
      p_str = 20
      p_dex = 10
      p_agi = 10
      p_int = -20
      m_maxhp = 1.1
      m_maxsp = 0.9
      m_str = 1.1
      m_dex = 1.1
      m_agi = 1.0
      m_int = 0.8
    when 2
      p_maxhp = -200
      p_maxsp = 50
      p_str = -20
      p_dex = 0
      p_agi = 0
      p_int = 30
      m_maxhp = 0.9
      m_maxsp = 1.1
      m_str = 0.7
      m_dex = 0.9
      m_agi = 1.1
      m_int = 1.2
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END RO Job Stat Modifier Database
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    end
    return [p_maxhp, m_maxhp, p_maxsp, m_maxsp, p_str, m_str, p_dex, m_dex,
        p_agi, m_agi, p_int, m_int]
  end
  
  # constants
  
  YesNo = ['Yes', 'No']
  AreYouSure = 'Are you sure?'
  Current = 'Current'
  JobPoints = 'Job Points'
  JobLevel = 'Job Level'
  JobEXP = 'Job EXP'
  EXP = 'EXP'
  Next = 'next'
  EmptyEXP = '------'
  None = 'None'
  Lv = 'Lv'
  SkillLevel = 'Skill Level'
  MaximumLevel = 'Maximum Level'
  Cost = 'Cost'
  Power = 'Power'
  ClassCommands = ['Select', 'Next', 'Previous', 'Exit']
  ChangeClass = 'Change Class?'
  SkillCommands = ['Learn new Skill', 'Improve Skill', 'Next', 'Previous', 'Exit']
  LearnSkill = 'Learn Skill?'
  ImproveSkill = 'Improve Skill?'
  
end

#==============================================================================
# Game_Actor
#------------------------------------------------------------------------------
#  This class was enhanced with various additional variables to make this
#  system work properly. Also a number of methods were added to handle the new
#  data.
#==============================================================================

class Game_Actor
  
  # setting all accessible variables
  attr_accessor :jp
  #----------------------------------------------------------------------------
  # override setup
  #  Adds some hashes for additional data.
  #----------------------------------------------------------------------------
  alias setup_skilllevels_later setup
  def setup(id)
    @skill_level, @job_level, @job_exp, @jp = {}, {}, {}, BlizzCFG::INIT_JP
    setup_skilllevels_later(id)
    @skills = [] unless BlizzCFG::JOB_ONLY
  end
  #----------------------------------------------------------------------------
  # job_level
  #  id - class ID
  #  Safe return of any job level, current job level is default.
  #----------------------------------------------------------------------------
  def job_level(id = @class_id)
    return (@job_level[id] == nil ? 1 : @job_level[id])
  end
  #----------------------------------------------------------------------------
  # job_exp
  #  id - class ID
  #  Safe return of any job exp, current job exp are default.
  #----------------------------------------------------------------------------
  def job_exp(id = @class_id)
    return (@job_exp[id] == nil ? 0 : @job_exp[id])
  end
  #----------------------------------------------------------------------------
  # job_level_change
  #  val  - new level value
  #  id   - class ID
  #  flag - determines whether EXP should be updated or not
  #  This method processes change of a job level.
  #----------------------------------------------------------------------------
  def job_level_change(val, id = @class_id, flag = true)
    # get level
    new_level = BlizzCFG.rojob_maxlevel(id)
    # limit level value
    if new_level > val
      new_level = val
    elsif new_level < 1
      new_level = 1
    end
    # get Job Points
    jp = new_level - self.job_level(id)
    # increase Job Points
    @jp += jp if jp > 0
    # set new Job level
    @job_level[id] = new_level
    # set Job EXP if the setting flag is active
    @job_exp[id] = BlizzCFG::LVLUP_RATE * new_level * (new_level - 1) if flag
  end
  #----------------------------------------------------------------------------
  # override exp=
  #  val  - new exp value
  #  This method was modified to add job EXP each time real EXP are added.
  #----------------------------------------------------------------------------
  alias exp_is_rosys_later exp=
  def exp=(val)
    # store old EXP and skills
    old_exp, skills = @exp, @skills.clone
    exp_is_rosys_later(val)
    # no skills can be learned, remove any learned skills
    @skills = skills
    # increase Job EXP
    exp = @exp - old_exp
    add_job_exp(exp * BlizzCFG::EXP_RATIO / 100) if exp > 0
  end
  #----------------------------------------------------------------------------
  # add_job_exp
  #  val - new exp value
  #  id  - class ID
  #  This method executes job exp increasing.
  #----------------------------------------------------------------------------
  def add_job_exp(val, id = @class_id)
    max_level = BlizzCFG.rojob_maxlevel(id)
    # set new Job EXP
    exp1 = self.job_exp(id) + val
    exp2 = BlizzCFG::LVLUP_RATE * max_level * (max_level - 1)
    @job_exp[id] = (exp1 < exp2 ? exp1 : exp)
    # as long as Job level can be increased
    while self.job_level(id) < max_level && self.job_exp(id) >=
        BlizzCFG::LVLUP_RATE * self.job_level(id) * (self.job_level(id) + 1)
      # increase Job level
      job_level_change(self.job_level(id) + 1, id, false)
    end
  end
  #----------------------------------------------------------------------------
  # job_max_level?
  #  Checks if the Job's level is at the maximum.
  #----------------------------------------------------------------------------
  def job_max_level?
    return (self.job_level >= BlizzCFG.rojob_maxlevel(@class_id))
  end
  #----------------------------------------------------------------------------
  # override base_maxhp
  #  This method was changed to allow class stat modifiers.
  #----------------------------------------------------------------------------
  alias base_maxhp_rosys_later base_maxhp
  def base_maxhp
    result, mods = base_maxhp_rosys_later, BlizzCFG.job_stat_mod(@class_id)
    return ((result + mods[0]) * mods[1]).to_i
  end
  #----------------------------------------------------------------------------
  # override base_maxsp
  #  This method was changed to allow class stat modifiers.
  #----------------------------------------------------------------------------
  alias base_maxsp_rosys_later base_maxsp
  def base_maxsp
    result, mods = base_maxsp_rosys_later, BlizzCFG.job_stat_mod(@class_id)
    return ((result + mods[2]) * mods[3]).to_i
  end
  #----------------------------------------------------------------------------
  # override base_str
  #  This method was changed to allow class stat modifiers.
  #----------------------------------------------------------------------------
  alias base_str_rosys_later base_str
  def base_str
    result, mods = base_str_rosys_later, BlizzCFG.job_stat_mod(@class_id)
    return ((result + mods[4]) * mods[5]).to_i
  end
  #----------------------------------------------------------------------------
  # override base_dex
  #  This method was changed to allow class stat modifiers.
  #----------------------------------------------------------------------------
  alias base_dex_rosys_later base_dex
  def base_dex
    result, mods = base_dex_rosys_later, BlizzCFG.job_stat_mod(@class_id)
    return ((result + mods[6]) * mods[7]).to_i
  end
  #----------------------------------------------------------------------------
  # override base_agi
  #  This method was changed to allow class stat modifiers.
  #----------------------------------------------------------------------------
  alias base_agi_rosys_later base_agi
  def base_agi
    result, mods = base_agi_rosys_later, BlizzCFG.job_stat_mod(@class_id)
    return ((result + mods[8]) * mods[9]).to_i
  end
  #----------------------------------------------------------------------------
  # override base_int
  #  This method was changed to allow class stat modifiers.
  #----------------------------------------------------------------------------
  alias base_int_rosys_later base_int
  def base_int
    result, mods = base_int_rosys_later, BlizzCFG.job_stat_mod(@class_id)
    return ((result + mods[10]) * mods[11]).to_i
  end
  #----------------------------------------------------------------------------
  # get_skill_sp_cost_factor
  #  skill_id - skill ID
  #  Returns the SP cost factor of the skill for this actor.
  #----------------------------------------------------------------------------
  def get_skill_sp_cost_factor(skill_id)
    return 1 if skill_max_level?(skill_id)
    return ((BlizzCFG::LVL1_COST - (self.skill_level(skill_id) - 1) *
        (BlizzCFG::LVL1_COST - 100.0) /
        (BlizzCFG.roskill_maxlevel(skill_id) - 1)) / 100)
  end
  #----------------------------------------------------------------------------
  # get_skill_damage_factor
  #  skill_id - skill ID
  #  Returns the damage factor of the skill for this actor.
  #----------------------------------------------------------------------------
  def get_skill_damage_factor(skill_id)
    return 1 if skill_max_level?(skill_id)
    return (BlizzCFG::LVL1_POWER + (self.skill_level(skill_id) - 1) *
        (100.0 - BlizzCFG::LVL1_POWER) /
        (BlizzCFG.roskill_maxlevel(skill_id) - 1)) / 100
  end
  #----------------------------------------------------------------------------
  # skill_max_level?
  #  skill_id - skill ID
  #  Checks if a skill has reached the max level.
  #----------------------------------------------------------------------------
  def skill_max_level?(skill_id)
    return (self.skill_level(skill_id) >= BlizzCFG.roskill_maxlevel(skill_id))
  end
  # if the JOB_ONLY option is not being used, a couple of methods are being
  # parsed for skill level handling
  unless BlizzCFG::JOB_ONLY
  #----------------------------------------------------------------------------
  # skill_level
  #  id - skill ID
  #  Safe return of a skill level for this actor.
  #----------------------------------------------------------------------------
  def skill_level(id)
    return (@skill_level[id] == nil ? 1 : @skill_level[id])
  end
  #----------------------------------------------------------------------------
  # skill_level_change
  #  val - new level value
  #  id  - skill ID
  #  This method processes change of a skill level.
  #----------------------------------------------------------------------------
  def skill_level_change(val, id)
    max_level = BlizzCFG.roskill_maxlevel(id)
    if val > max_level
      @skill_level[id] = max_level
    elsif max_level < 1
      @skill_level[id] = 1
    else
      @skill_level[id] = val
    end
  end
  #----------------------------------------------------------------------------
  # override forget_skill
  #  id - skill ID
  #  This method additionally resets a level when a skill gets removed.
  #----------------------------------------------------------------------------
  alias forget_skill_rosys_later forget_skill
  def forget_skill(id)
    learned = @skills.include?(id)
    forget_skill_rosys_later(id)
    # reset skill level of forgotten skill if that option is active
    @skill_level[id] = 1 if BlizzCFG::RESET_LVLS && learned && !@skills.include?(id)
  end
  #----------------------------------------------------------------------------
  # override skill_can_use?
  #  skill_id - skill ID
  #  This method additionally takes into account the increased SP cost.
  #----------------------------------------------------------------------------
  alias skill_can_use_rosys_later? skill_can_use?
  def skill_can_use?(skill_id)
    skill = $data_skills[skill_id]
    # if not enough SP considering skill level SP cost modification
    if self.sp < (skill.sp_cost * get_skill_sp_cost_factor(skill.id)).to_i
      # skill cannot be used
      return false
    end
    return skill_can_use_rosys_later?(skill_id)
  end
  end
  
end

#==============================================================================
# Game_Battler
#------------------------------------------------------------------------------
#  This class was modified to support skill levels.
#==============================================================================

unless BlizzCFG::JOB_ONLY
class Game_Battler
  
  #----------------------------------------------------------------------------
  # override skill_effect
  #  user  - the skill performer
  #  skill - the skill
  #  This method was modified to support changed damage handling.
  #----------------------------------------------------------------------------
  alias skill_effect_rosys_later skill_effect
  def skill_effect(user, skill)
    # stores old values and executes skill
    last_hp = self.hp
    last_sr = self.sr if $crls && self.is_a?(Game_Actor)
    result = skill_effect_rosys_later(user, skill)
    # if skill was a success and effect needs to be modified
    if result && self.damage.is_a?(Numeric) && user.is_a?(Game_Actor) &&
        !user.skill_max_level?(skill.id)
      # restore values
      self.hp = last_hp
      self.sr = last_sr if $crls && self.is_a?(Game_Actor)
      # modifiy damage considering skill level
      self.damage = (self.damage * user.get_skill_damage_factor(skill.id)).to_i
      # apply skill effect on HP
      self.hp -= self.damage
    end
    return result
  end
  
end

#==============================================================================
# Window_Skill
#------------------------------------------------------------------------------
#  This class was modified to display correct SP consumption if skill levels
#  are being used.
#==============================================================================

class Window_Skill < Window_Selectable
  
  #--------------------------------------------------------------------------
  # override draw_item
  #  i - index
  #  This method was modified to print the correct SP cost.
  #--------------------------------------------------------------------------
  alias draw_item_rosys_later draw_item
  def draw_item(i)
    draw_item_rosys_later(i)
    skill = @data[i]
    # decide color depending on the fact if currently usable
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    # remove old SP display
    self.contents.fill_rect(236 + i % 2 * 320, i / 2 * 32, 48, 32,
        Color.new(0, 0, 0, 0))
    # calculate SP cost considering skill level
    sp_cost = (skill.sp_cost * @actor.get_skill_sp_cost_factor(skill.id)).to_i
    # draw SP cost
    self.contents.draw_text(236 + i % 2 * 320, i / 2 * 32, 48, 32,
        sp_cost.to_s, 2)
  end
  
end

#==============================================================================
# Map_Battler
#------------------------------------------------------------------------------
#  This is a Blizz-ABS class.
#==============================================================================

# if Blizz-ABS is being used
if $BlizzABS && BlizzABS::VERSION >= 2.7
class Map_Battler
  
  #----------------------------------------------------------------------------
  # override skill_consumption
  #  Corrects SP consumption in Blizz-ABS.
  #----------------------------------------------------------------------------
  alias skill_consumption_rosys_later skill_consumption
  def skill_consumption(skill)
    if self.is_a?(Map_Actor) && self.valid? &&
        !@battler.skill_max_level?(skill.id)
      skill = skill.clone
      skill.sp_cost = (skill.sp_cost *
          @battler.get_skill_sp_cost_factor(skill.id)).to_i
      if $tons_version != nil && $tons_version >= 7.4 && $game_system.HP_SKILL
        skill.hp_cost = (skill.hp_cost *
            @battler.get_skill_sp_cost_factor(skill.id)).to_i
      end
    end
    skill_consumption_rosys_later(skill)
  end
  
end

#==============================================================================
# Hud
#------------------------------------------------------------------------------
#  This is a Blizz-ABS class.
#==============================================================================

class Hud < Sprite
  
  def get_skills_left
    # stop if skill is not hot skill or does not exist
    return -2 if @skill == nil || @skill == 0
    # infinite usages if SP cost is zero
    return -1 if $data_skills[@skill].sp_cost == 0
    # get SP cost
    sp_cost = ($data_skills[@skill].sp_cost * 
        actor.get_skill_sp_cost_factor(@skill)).to_i
    # if using SP Cost Mod Status
    if $tons_version != nil && $tons_version >= 6.54 &&
        $game_system.SP_COST_MOD
      # get modified cost
      sp_cost = BlizzCFG.get_cost_mod(actor.states, sp_cost)
    end
    # infinite usages if SP cost is zero
    return -1 if sp_cost == 0
    # calculate skills left to use
    return (@sp / sp_cost)
  end
  
end
end

#==============================================================================
# Scene_Battle
#------------------------------------------------------------------------------
#  This class was modified to support correct SP consumption if skill levels
#  are being used.
#==============================================================================

class Scene_Battle
  
  #----------------------------------------------------------------------------
  # override use_skill
  #  skill - the skill to be used
  #  Corrects SP consumption in DBS and RTAB.
  #----------------------------------------------------------------------------
  alias make_skill_action_result_rosys_later make_skill_action_result
  def make_skill_action_result(battler = nil)
    # if RTAB is being used
    if battler != nil
      # store old SP and make result
      old_sp = battler.sp
      make_skill_action_result_rosys_later(battler)
    else
      # store old SP and make result
      old_sp, battler = @active_battler.sp, @active_battler
      make_skill_action_result_rosys_later
    end
    # if skill was really used and SP consumption needs to be modified
    if battler.is_a?(Game_Actor) && @phase4_step != 1 &&
        battler.sp != @skill.sp_cost && !battler.skill_max_level?(@skill.id)
      # change SP considering skill level
      battler.sp = old_sp - (@skill.sp_cost *
          battler.get_skill_sp_cost_factor(@skill.id)).to_i
      @status_window.refresh
    end
  end
  
end
end

#==============================================================================
# Window_Base
#------------------------------------------------------------------------------
#  This class was enhanced with a few drawing utility mehods.
#==============================================================================

class Window_Base < Window
  
  #----------------------------------------------------------------------------
  # draw_actor_battler
  #  actor - the actor
  #  x     - x coordinate
  #  y     - y coordinate
  #  Draws the actor's battler graphic in a window.
  #----------------------------------------------------------------------------
  def draw_actor_battler(actor, x, y)
    # get bitmap and dimentions
    bitmap = RPG::Cache.battler(actor.battler_name, actor.battler_hue)
    cw, ch = bitmap.width, bitmap.height
    src_rect = Rect.new(0, 0, cw, ch)
    # transfer bitmap on window
    self.contents.blt(x - cw / 2, y - ch / 2, bitmap, src_rect)
  end
  #----------------------------------------------------------------------------
  # draw_actor_job
  #  actor - the actor
  #  x     - x coordinate
  #  y     - y coordinate
  #  width - max width
  #  Draws the actor's job data.
  #----------------------------------------------------------------------------
  def draw_actor_job(actor, x, y, width)
    self.contents.font.color = system_color
    # draw all static system words
    self.contents.draw_text(x, y, width, 32, BlizzCFG::Current + ':')
    self.contents.draw_text(x, y + 32, width, 32, BlizzCFG::JobPoints + ':')
    self.contents.draw_text(x, y + 64, width, 32, BlizzCFG::JobLevel + ':')
    self.contents.draw_text(x, y + 96, width, 32, BlizzCFG::JobEXP + ':')
    self.contents.draw_text(x, y + 128, width, 32, BlizzCFG::Next + ':')
    self.contents.font.color = normal_color
    # draw all the data
    self.contents.draw_text(x, y, width, 32, actor.class_name, 2)
    self.contents.draw_text(x, y + 64, width, 32, actor.job_level.to_s, 2)
    self.contents.draw_text(x, y + 96, width, 32, actor.job_exp.to_s, 2)
    nex = BlizzCFG::LVLUP_RATE * actor.job_level * (actor.job_level + 1)
    if actor.job_max_level?
      self.contents.draw_text(x, y + 128, width, 32, BlizzCFG::EmptyEXP, 2)
    else
      self.contents.draw_text(x, y + 128, width, 32,
          (nex - actor.job_exp).to_s, 2)
    end
    # change color to red if no Job Points left
    self.contents.font.color = Color.new(255, 0, 0) if actor.jp == 0
    self.contents.draw_text(x, y + 32, width, 32, actor.jp.to_s, 2)
  end
  
end

#==============================================================================
# Window_Dialog
#------------------------------------------------------------------------------
#  Confirmation Dialog window class.
#==============================================================================

class Window_Dialog < Window_Command
  
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(width, commands = BlizzCFG::YesNo,
        caption = BlizzCFG::AreYouSure)
    # add another command, serves as fix
    commands = commands + ['']
    # set caption
    @caption = caption
    @cursor_width = 32
    super(width, commands)
    # font fix
    if $fontface != nil
      self.contents.font.name = $fontface
      self.contents.font.size = $fontsize
    elsif $defaultfonttype != nil
      self.contents.font.name = $defaultfonttype
      self.contents.font.size = $defaultfontsize
    end
    # set variables
    self.x, self.y, self.z = 320 - self.width / 2, 200 - self.height / 2, 1500
    @item_max, self.opacity = commands.size - 1, 192
    commands.each {|c|
        w = self.contents.text_size(c).width
        @cursor_width = w if @cursor_width < w}
    @cursor_width += 32
    # refresh display
    refresh
    update_cursor_rect
  end
  #----------------------------------------------------------------------------
  # refresh
  #  Added caption text.
  #----------------------------------------------------------------------------
  def refresh
    super
    self.contents.font.color = system_color
    self.contents.draw_text(4, 0, self.width - 40, 32, @caption, 1)
  end
  #----------------------------------------------------------------------------
  # draw_item
  #  i     - index
  #  color - font color
  #  Changed method to draw commands one line off.
  #----------------------------------------------------------------------------
  def draw_item(index, color)
    self.contents.font.color = color
    rect = Rect.new(4, 32 * (index + 1), self.contents.width - 8, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    self.contents.draw_text(rect, @commands[index], 1)
  end
  #----------------------------------------------------------------------------
  # update_cursor_rect
  #  Changed method to draw cursor one line off.
  #----------------------------------------------------------------------------
  def update_cursor_rect
    if @index < 0 || @item_max == 0
      self.cursor_rect.empty
    else
      x = (self.contents.width - @cursor_width) / 2
      self.cursor_rect.set(x, (@index + 1) * 32, @cursor_width, 32)
    end
  end
  
end

#==============================================================================
# Window_ClassStatus
#------------------------------------------------------------------------------
#  This window displays the character status and includes data about the
#  current Job like Level, EXP and Job Points along with stat change if the
#  class is being changed.
#==============================================================================

class Window_ClassStatus < Window_Base
  
  # setting all accessible variables
  attr_accessor :actor
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(actor)
    super(BlizzCFG::RO_RIGHT ? 0 : 224, 0, 416, 480)
    @actor = actor
    self.contents = Bitmap.new(width - 32, height - 32)
    # font fix
    if $fontface != nil
      self.contents.font.name = $fontface
      self.contents.font.size = $fontsize
    elsif $defaultfonttype != nil
      self.contents.font.name = $defaultfonttype
      self.contents.font.size = $defaultfontsize
    end
    refresh
  end
  #----------------------------------------------------------------------------
  # refresh
  #  Processes all that is being drawn.
  #----------------------------------------------------------------------------
  def refresh(id = nil)
    self.contents.clear
    # stop if actor doesn't exist
    return if @actor == nil
    actor = @actor.clone
    # can't use Game_Actor#class_id= because it unequips equipment
    actor.instance_variable_set('@class_id', id) if id != nil
    # draw actor data
    draw_actor_battler(@actor, 280, 128)
    draw_actor_name(@actor, 4, 0)
    draw_actor_level(@actor, 4, 32)
    draw_actor_state(@actor, 4, 64)
    draw_actor_hp(@actor, 4, 160, 160)
    draw_actor_sp(@actor, 4, 192, 160)
    draw_actor_hp_mod(@actor, 4, 160, actor, 160)
    draw_actor_sp_mod(@actor, 4, 192, actor, 160)
    draw_actor_job(@actor, 188, 288, 192)
    (0..6).each {|i|
        draw_actor_parameter(@actor, 4, 224 + 32 * i, i)
        draw_actor_parameter_mod(@actor, 4, 224 + 32 * i, i, actor)}
    self.contents.font.color = system_color
    self.contents.draw_text(4, 96, 80, 32, BlizzCFG::EXP)
    self.contents.draw_text(4, 128, 80, 32, BlizzCFG::Next)
    self.contents.font.color = normal_color
    self.contents.draw_text(4, 96, 156, 32, @actor.exp_s, 2)
    self.contents.draw_text(4, 128, 156, 32, @actor.next_rest_exp_s, 2)
  end
  #--------------------------------------------------------------------------
  # draw_actor_hp_mod
  #  actor - the actor
  #  x     - x-coordinate
  #  y     - y-coordinate
  #  other - the actor before
  #  width - maximal allowed width
  #  This method erases the max HP value to redraw it in the right color.
  #--------------------------------------------------------------------------
  def draw_actor_hp_mod(actor, x, y, other, width = 144)
    # stop if width exceeds max
    return if width - 32 < 108
    # decide color
    if other.maxhp > actor.maxhp
      self.contents.font.color = BlizzCFG::UP_COLOR
    elsif other.maxhp < actor.maxhp
      self.contents.font.color = BlizzCFG::DOWN_COLOR
    else
      return
    end
    # delete old display
    self.contents.fill_rect(x + width - 48, y, 48, 32, Color.new(0, 0, 0, 0))
    # draw
    self.contents.draw_text(x + width - 48, y, 48, 32, other.maxhp.to_s)
  end
  #--------------------------------------------------------------------------
  # draw_actor_sp_mod
  #  actor - the actor
  #  x     - x-coordinate
  #  y     - y-coordinate
  #  other - the actor before
  #  width - maximal allowed width
  #  This method erases the max HP value to redraw it in the right color.
  #--------------------------------------------------------------------------
  def draw_actor_sp_mod(actor, x, y, other, width = 144)
    # stop if width exceeds max
    return if width - 32 < 108
    # decide color
    if other.maxsp > actor.maxsp
      self.contents.font.color = BlizzCFG::UP_COLOR
    elsif other.maxsp < actor.maxsp
      self.contents.font.color = BlizzCFG::DOWN_COLOR
    else
      return
    end
    # delete old display
    self.contents.fill_rect(x + width - 48, y, 48, 32, Color.new(0, 0, 0, 0))
    # draw
    self.contents.draw_text(x + width - 48, y, 48, 32, other.maxsp.to_s)
  end
  #--------------------------------------------------------------------------
  # draw_actor_parameter_mod
  #  actor - the actor
  #  x     - x-coordinate
  #  y     - y-coordinate
  #  other - the actor before
  #  type  - which stat
  #  This method erases a stat value to redraw it in the right color.
  #--------------------------------------------------------------------------
  def draw_actor_parameter_mod(actor, x, y, type, other)
    # decide parameter
    case type
    when 3 then str, v1, v2 = $data_system.words.str, actor.str, other.str
    when 4 then dex, v1, v2 = $data_system.words.dex, actor.dex, other.dex
    when 5 then agi, v1, v2 = $data_system.words.agi, actor.agi, other.agi
    when 6 then int, v1, v2 = $data_system.words.int, actor.int, other.int
    else
      return
    end
    # decide color
    if v2 > v1
      self.contents.font.color = BlizzCFG::UP_COLOR
    elsif v2 < v1
      self.contents.font.color = BlizzCFG::DOWN_COLOR
    else
      return
    end
    # delete old display
    self.contents.fill_rect(x + 120, y, 36, 32, Color.new(0, 0, 0, 0))
    # draw
    self.contents.draw_text(x + 120, y, 36, 32, v2.to_s, 2)
  end
  
end
  
#==============================================================================
# Window_Class
#------------------------------------------------------------------------------
#  This window is a slight modification of the Window_Command window to avoid
#  recoding.
#==============================================================================

class Window_Class < Window_Command
  
  #----------------------------------------------------------------------------
  # draw_item
  #  i     - index
  #  color - font color
  #  Changed to draw class/job and level requirement.
  #----------------------------------------------------------------------------
  def draw_item(i, color)
    self.contents.font.color = color
    rect = Rect.new(4, 32 * i, self.contents.width - 8, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    self.contents.draw_text(rect, @commands[i][0])
    self.contents.draw_text(rect, @commands[i][1], 2)
  end
  
end

#==============================================================================
# Window_SkillLearn
#------------------------------------------------------------------------------
#  This window displays all skills that can be still learned.
#==============================================================================

class Window_SkillLearn < Window_Command
  
  # setting all accessible variables
  attr_reader :commands
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(width, actor)
    @actor = actor
    super(width, refresh_skills)
    self.z, self.height, self.index = 500, 224, -1
    self.x, self.active = BlizzCFG::RO_RIGHT ? 320 : 0, false
  end
  #----------------------------------------------------------------------------
  # refresh_skills
  #  This method sets up the skill list again.
  #----------------------------------------------------------------------------
  def refresh_skills
    skills = $data_classes[@actor.class_id].learnings.clone
    # if using the option to hide skills that don't meet the requirements
    if BlizzCFG::HIDE_SKILLS
      # temporary variable
      lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level)
      # get all learnable skills that weren't learned already
      skills = skills.find_all {|learn|
          @actor.job_level >= learn.level &&
          BlizzCFG.roskill_reqs(learn.skill_id).all? {|r|
              @actor.skills.include?(r[0]) && @actor.skill_level(r[0]) >= r[1]}}
    end
    # filter out all skills that weren't learned already
    skills = skills.find_all {|learn| !@actor.skills.include?(learn.skill_id)}
    return (skills.size == 0 ? [nil] : skills)
  end
  #----------------------------------------------------------------------------
  # refresh
  #  This method was modifies to draw "None" is no skills are available and
  #  refreshes the skill list upon redrawing.
  #----------------------------------------------------------------------------
  def refresh
    @commands = refresh_skills
    @item_max = @commands.size
    if @commands[0] == nil
      self.contents.clear
      self.contents.font.color = disabled_color
      self.contents.draw_text(4, 0, self.contents.width - 8, 32, BlizzCFG::None)
    else
      super
    end
  end
  #----------------------------------------------------------------------------
  # draw_item
  #  i     - index
  #  color - font color
  #  Draws a specific skill and the level requirement to learn it.
  #----------------------------------------------------------------------------
  def draw_item(i, color = nil)
    lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level)
    # decide color depending on which level is used
    if !BlizzCFG::HIDE_SKILLS && (lvl < @commands[i].level ||
        BlizzCFG.roskill_reqs(@commands[i].skill_id).any? {|r|
             !@actor.skills.include?(r[0]) || @actor.skill_level(r[0]) < r[1]})
      self.contents.font.color = disabled_color
    else
      self.contents.font.color = normal_color
    end
    # get rectangle
    rect = Rect.new(32, 32 * i, self.contents.width - 36, 32)
    # get icon bitmap
    bitmap = RPG::Cache.icon($data_skills[@commands[i].skill_id].icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    # draw bitmap
    self.contents.blt(4, 4 + 32 * i, bitmap, Rect.new(0, 0, 24, 24), opacity)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    # draw name and requirement if not using the hiding option
    self.contents.draw_text(rect, $data_skills[@commands[i].skill_id].name)
    unless BlizzCFG::HIDE_SKILLS
      self.contents.draw_text(rect,
        "(#{BlizzCFG::Lv} #{@commands[i].level})", 2)
    end
  end
  #----------------------------------------------------------------------------
  # update_help
  #  Updates the skill status display.
  #----------------------------------------------------------------------------
  def update_help
    @help_window.set_text(@commands[index] == nil ? 0 : @commands[index].skill_id)
  end
  
end

#==============================================================================
# Window_SkillImprove
#------------------------------------------------------------------------------
#  This window displays skills that are already learned.
#==============================================================================

class Window_SkillImprove < Window_Command
  
  # setting all accessible variables
  attr_accessor :commands
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(width, actor)
    @actor, skills = actor, actor.skills
    skills = [nil] if skills.size == 0
    super(width, skills)
    self.z, self.height, self.index = 500, 224, -1
    self.x, self.active = BlizzCFG::RO_RIGHT ? 0 : 320, false
  end
  #----------------------------------------------------------------------------
  # set_commands
  #  commands - new commands
  #  Sets a new list of skills and updates the display.
  #----------------------------------------------------------------------------
  def set_commands(commands)
    commands = [nil] if commands.size == 0
    @commands, @item_max = commands, commands.size
    self.contents.dispose
    self.contents = Bitmap.new(width - 32, @item_max * 32)
    refresh
  end
  #----------------------------------------------------------------------------
  # refresh
  #  Changed to draw "None" if no skills are available.
  #----------------------------------------------------------------------------
  def refresh
    if @commands[0] == nil
      self.contents.clear
      self.contents.font.color = disabled_color
      self.contents.draw_text(4, 0, self.contents.width - 8, 32, BlizzCFG::None)
    else
      super
    end
  end
  #----------------------------------------------------------------------------
  # draw_item
  #  i     - index
  #  color - font color
  #  Draws a specific skill with SP cost, considering the changed SO cost due
  #  to the skill level.
  #----------------------------------------------------------------------------
  def draw_item(i, color = nil)
    skill = $data_skills[@commands[i]]
    # decide color whether skill can still be improved
    if @actor.skill_max_level?(skill.id)
      self.contents.font.color = disabled_color
    else
      self.contents.font.color = color
    end
    # get rectangle
    rect = Rect.new(32, 32 * i, self.contents.width - 36, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    # get icon bitmap
    bitmap = RPG::Cache.icon(skill.icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    # draw bitmap
    self.contents.blt(4, 4 + 32 * i, bitmap, Rect.new(0, 0, 24, 24), opacity)
    self.contents.draw_text(rect, skill.name)
    # calculate SP cost considering skill level
    sp_cost = (skill.sp_cost * @actor.get_skill_sp_cost_factor(skill.id)).to_i
    # draw SP cost
    self.contents.draw_text(rect, sp_cost.to_s, 2)
  end
  #----------------------------------------------------------------------------
  # update_help
  #  Updates the skill status display.
  #----------------------------------------------------------------------------
  def update_help
    @help_window.set_text(@commands[index] == nil ? 0 : @commands[index])
  end
  
end

#==============================================================================
# Window_SkillLevel
#------------------------------------------------------------------------------
#  This window displays the current skill's data like Level, Power Percentage,
#  modified SP Cost, etc.
#==============================================================================

class Window_SkillLevel < Window_Base
  
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(actor)
    super(BlizzCFG::RO_RIGHT ? 0 : 416, 0, 224, 192)
    @actor, self.contents = actor, Bitmap.new(width - 32, height - 32)
    # font fix
    if $fontface != nil
      self.contents.font.name = $fontface
      self.contents.font.size = $fontsize
    elsif $defaultfonttype != nil
      self.contents.font.name = $defaultfonttype
      self.contents.font.size = $defaultfontsize
    end
    @help_window = Window_Help.new
  end
  #----------------------------------------------------------------------------
  # refresh
  #  Helping method for easier code overview that redraws the display no matter
  #  what.
  #----------------------------------------------------------------------------
  def refresh
    return if @skill == nil
    id, @skill = @skill.id, nil
    set_text(id)
  end
  #----------------------------------------------------------------------------
  # set_text
  #  id - skill ID
  #  This method draws the currently selected skill's data and stores it so the
  #  display only gets redrawn each time it changes.
  #----------------------------------------------------------------------------
  def set_text(id)
    # stop if same skill as before
    return if @skill == $data_skills[id]
    self.contents.clear
    @skill = $data_skills[id]
    # if skill doesn't exist
    if @skill == nil
      # emtpy description window and stop
      @help_window.set_text('')
      return
    end
    # get icon bitmap and draw it
    bitmap = RPG::Cache.icon(@skill.icon_name)
    self.contents.blt(4, 4, bitmap, Rect.new(0, 0, 24, 24))
    self.contents.draw_text(32, 0, 156, 32, @skill.name)
    # calculate SP cost considering skill level
    sp_cost = (@skill.sp_cost * @actor.get_skill_sp_cost_factor(@skill.id)).to_i
    # calculate damage multiplier considering skill level
    power = (100 * @actor.get_skill_damage_factor(@skill.id)).to_i
    self.contents.font.color = system_color
    # draw all static words
    self.contents.draw_text(4, 32, 184, 32, BlizzCFG::SkillLevel + ':')
    self.contents.draw_text(4, 64, 184, 32, BlizzCFG::MaximumLevel + ':')
    self.contents.draw_text(4, 96, 184, 32, BlizzCFG::Cost + ':')
    self.contents.draw_text(4, 128, 184, 32, BlizzCFG::Power + ':')
    self.contents.draw_text(4, 64, 184, 32,
        BlizzCFG.roskill_maxlevel(@skill.id).to_s, 2)
    self.contents.font.color = normal_color
    # draw all the data
    self.contents.draw_text(4, 32, 184, 32, @actor.skill_level(@skill.id).to_s, 2)
    sp_cost = "#{sp_cost} #{$data_system.words.sp}"
    self.contents.draw_text(4, 96, 184, 32, sp_cost, 2)
    self.contents.draw_text(4, 128, 184, 32, "#{power}%", 2)
    # set help window text to skill description
    @help_window.set_text(@skill.description, 1)
  end
  #----------------------------------------------------------------------------
  # dispose
  #  This method was enhanced to dispose the skill description window.
  #----------------------------------------------------------------------------
  def dispose
    @help_window.dispose
    super
  end
  
end

#==============================================================================
# Window_JobLevel
#------------------------------------------------------------------------------
#  This window displays job data.
#==============================================================================

class Window_JobLevel < Window_Base
  
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(actor)
    super(BlizzCFG::RO_RIGHT ? 416 : 0, 0, 224, 192)
    @actor, self.contents = actor, Bitmap.new(width - 32, height - 32)
    # font fix
    if $fontface != nil
      self.contents.font.name = $fontface
      self.contents.font.size = $fontsize
    elsif $defaultfonttype != nil
      self.contents.font.name = $defaultfonttype
      self.contents.font.size = $defaultfontsize
    end
    refresh
  end
  #----------------------------------------------------------------------------
  # refresh
  #  This method draws the job data.
  #----------------------------------------------------------------------------
  def refresh
    self.contents.clear
    draw_actor_job(@actor, 4, 0, 184)
  end
  
end

#==============================================================================
# Scene_ClassChange
#------------------------------------------------------------------------------
#  This scene processes the class/job change system.
#==============================================================================

class Scene_ClassChange
  
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(index = 0, scene = Scene_Map)
    @actor, @scene = $game_party.actors[index], scene
  end
  #----------------------------------------------------------------------------
  # main
  #  Main processing method.
  #----------------------------------------------------------------------------
  def main
    # create main command window
    @command_window = Window_Command.new(224, BlizzCFG::ClassCommands)
    @command_window.x = BlizzCFG::RO_RIGHT ? 416 : 0
    # create status window
    @status_window = Window_ClassStatus.new(@actor)
    @old_index = 0
    make_class_window
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      break if $scene != self
    end
    Graphics.freeze
    # delete all windows
    @command_window.dispose
    @status_window.dispose
    @class_window.dispose
  end
  #----------------------------------------------------------------------------
  # make_class_window
  #  This method helps to make the code easier to overview.
  #----------------------------------------------------------------------------
  def make_class_window
    # delete old window if there is one
    @class_window.dispose unless @class_window == nil || @class_window.disposed?
    # get configuration and initialize data
    @configs = BlizzCFG.rojob_next(@actor.class_id)
    commands, lvl = [], (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level)
    # if no configs
    if @configs[0].size == 0
      # set to "None"
      commands = [[BlizzCFG::None, '']]
    else
      # add command data
      @configs.each {|c| commands.push([$data_classes[c[1]].name,
          "(#{BlizzCFG::Lv} #{c[0]})"])}
    end
    # create window with given data
    @class_window = Window_Class.new(224, commands)
    @class_window.x, @class_window.y = BlizzCFG::RO_RIGHT ? 416 : 0, 160
    @class_window.height, @class_window.index = 320, -1
    # if no configuration
    if @configs[0].size == 0
      # set text color to disabled
      @class_window.disable_item(0)
      @command_window.disable_item(0)
    else
      # disable each new class/job that does not fulfill the requirement
      @configs.each_index {|i|
          @class_window.disable_item(i) if lvl < @configs[i][0]}
      @command_window.refresh
    end
  end
  #----------------------------------------------------------------------------
  # update
  #  This is the main update method which calls the appropriate method
  #  depending on which window is currently active.
  #----------------------------------------------------------------------------
  def update
    if @command_window.active
      @command_window.update
      update_command
    elsif @sure_window != nil
      @sure_window.update
      update_sure
    elsif @class_window.active
      @class_window.update
      update_classchange
    end
  end
  #----------------------------------------------------------------------------
  # update_comand
  #  This method updates the command window input.
  #----------------------------------------------------------------------------
  def update_command
    # if cancel button pressed
    if Input.trigger?(Input::B)
      # play sound and return to previous scene
      $game_system.se_play($data_system.cancel_se)
      $scene = @scene.new
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      size = $game_party.actors.size
      # depending on chosen option activate jobchange, change actor or leave
      case @command_window.index
      when 0
        if @configs[0].size == 0
          $game_system.se_play($data_system.buzzer_se)
          return
        end
        $game_system.se_play($data_system.decision_se)
        @command_window.active, @class_window.active = false, true
        @class_window.index = @old_index
        @status_window.refresh(@configs[@class_window.index][1])
      when 1 then $scene = self.class.new((@actor.index + 1) % size, @scene)
      when 2 then $scene = self.class.new((@actor.index + size - 1) % size, @scene)
      when 3 then $scene = @scene.new
      end
      $game_system.se_play($data_system.decision_se)
    end
  end
  #----------------------------------------------------------------------------
  # update_classchange
  #  This method updates the class change window input.
  #----------------------------------------------------------------------------
  def update_classchange
    # if cancel button pressed
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      @command_window.active = true
      @old_index = @class_window.index
      @class_window.active, @class_window.index = false, -1
      @status_window.refresh
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level)
      # if requirements are not fulfilled
      if lvl < @configs[@class_window.index][0]
        $game_system.se_play($data_system.buzzer_se)
      else
        $game_system.se_play($data_system.decision_se)
        # create confirmation window
        @sure_window = Window_Dialog.new(224, BlizzCFG::YesNo,
            BlizzCFG::ChangeClass)
        @sure_window.z, @class_window.active = 500, false
      end
    # if up/down is being pressed
    elsif Input.trigger?(Input::UP) || Input.trigger?(Input::DOWN)
      # apply status window change
      @status_window.refresh(@configs[@class_window.index][1])
    end
  end
  #----------------------------------------------------------------------------
  # update_sure
  #  This method updates the confirmation window input.
  #----------------------------------------------------------------------------
  def update_sure
    # if cancel button pressed
    if Input.trigger?(Input::B)
      # play sound and remove confirmation window
      $game_system.se_play($data_system.cancel_se)
      @sure_window.dispose
      @class_window.active, @sure_window = true, nil
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      # either accept or decline and remove confirmation window
      case @sure_window.index
      when 0
        id = @actor.class_id
        @actor.class_id = @configs[@class_window.index][1]
        @actor.hp, @actor.sp = @actor.hp, @actor.sp
        @status_window.refresh
        if !BlizzCFG::JOB_ONLY && BlizzCFG::CLASS_SKILLS &&
            @actor.class_id != id && $data_classes[id] != nil
          # remove all skills
          $data_classes[id].learnings.each {|i| @actor.forget_skill(i.skill_id)}
        end
        make_class_window
        @sure_window.dispose
        @command_window.active, @sure_window = true, nil
        @old_index = 0
      when 1
        @sure_window.dispose
        @class_window.active, @sure_window = true, nil
      end
    end
  end
  
end

#==============================================================================
# Scene_SkillChange
#------------------------------------------------------------------------------
#  This scene processes the learning and improving (leveling up) of RO skills.
#==============================================================================

class Scene_SkillChange
  
  #----------------------------------------------------------------------------
  # Initialization
  #----------------------------------------------------------------------------
  def initialize(index = 0, scene = Scene_Map)
    @actor, @scene = $game_party.actors[index], scene
  end
  #----------------------------------------------------------------------------
  # main
  #  This is the main processing method.
  #----------------------------------------------------------------------------
  def main
    # create main command window
    @command_window = Window_Command.new(192, BlizzCFG::SkillCommands)
    # create other windows
    @learn_window = Window_SkillLearn.new(320, @actor)
    @skill_window = Window_SkillImprove.new(320, @actor)
    @status_window = Window_SkillLevel.new(@actor)
    @job_window = Window_JobLevel.new(@actor)
    # set window positions
    @command_window.y = @status_window.y = @job_window.y = 64
    @command_window.x, @learn_window.y, @skill_window.y = 224, 256, 256
    @learn_window.x, @skill_window.x = 320, 0 if BlizzCFG::RO_RIGHT
    @learn_window.help_window = @skill_window.help_window = @status_window
    # skill status window must be clear
    @status_window.set_text(0)
    # disable command if no skills in the given category
    @command_window.disable_item(0) if @learn_window.commands[0] == nil
    @command_window.disable_item(1) if @skill_window.commands[0] == nil
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      break if $scene != self
    end
    Graphics.freeze
    # remove all windows
    [@command_window, @learn_window, @skill_window, @status_window,
        @job_window].each {|win|win.dispose}
  end
  #----------------------------------------------------------------------------
  # update
  #  This is the main update method which calls the appropriate method
  #  depending on which window is currently active.
  #----------------------------------------------------------------------------
  def update
    if @command_window.active
      @command_window.update
      update_command
    elsif @sure_window != nil
      @sure_window.update
      # update the correct confirmation
      @learn_window.index >= 0 ? update_sure_learn : update_sure_skill
    elsif @learn_window.active
      @learn_window.update
      update_learn
    elsif @skill_window.active
      @skill_window.update
      update_skill
    end
  end
  #----------------------------------------------------------------------------
  # update_sure
  #  This method updates the command window input.
  #----------------------------------------------------------------------------
  def update_command
    # if cancel button pressed
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      $scene = @scene.new
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      size = $game_party.actors.size
      # choose next menu, change actor or leave
      case @command_window.index
      when 0
        # if no skills in this category
        if @learn_window.commands[0] == nil
          # play sound and stop
          $game_system.se_play($data_system.buzzer_se)
          return
        end
        # play sound and activate other window
        $game_system.se_play($data_system.decision_se)
        @command_window.active, @learn_window.active = false, true
        @learn_window.index = 0
      when 1
        # if no skills in this category
        if @skill_window.commands[0] == nil
          # play sound and stop
          $game_system.se_play($data_system.buzzer_se)
          return
        end
        # play sound and activate other window
        $game_system.se_play($data_system.decision_se)
        @command_window.active, @skill_window.active = false, true
        @skill_window.index = 0
      when 2 then $scene = self.class.new((@actor.index + 1) % size, @scene)
      when 3 then $scene = self.class.new((@actor.index + size - 1) % size, @scene)
      when 4 then $scene = @scene.new
      end
      $game_system.se_play($data_system.decision_se)
    end
  end
  #----------------------------------------------------------------------------
  # update_sure
  #  This method updates the skill learn window input.
  #----------------------------------------------------------------------------
  def update_learn
    # if cancel button pressed
    if Input.trigger?(Input::B)
      # play sound and return to main command
      $game_system.se_play($data_system.cancel_se)
      @command_window.active, @learn_window.active = true, false
      @status_window.set_text(0)
      @learn_window.index = -1
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level)
      # temporary variable
      learn = @learn_window.commands[@learn_window.index]
      # if skill doesn't exist, cannot be learned, no Job Points or reqs not fulfilled
      if learn == nil || @actor.jp == 0 || lvl < learn.level ||
          BlizzCFG.roskill_reqs(learn.skill_id).any? {|r|
              !@actor.skills.include?(r[0]) || @actor.skill_level(r[0]) < r[1]}
        # play sound
        $game_system.se_play($data_system.buzzer_se)
      else
        # play sound and create confirmation window
        $game_system.se_play($data_system.decision_se)
        @sure_window = Window_Dialog.new(224, BlizzCFG::YesNo,
            BlizzCFG::LearnSkill)
        @learn_window.active = false
      end
    end
  end
  #----------------------------------------------------------------------------
  # update_sure
  #  This method updates the skill improve window input.
  #----------------------------------------------------------------------------
  def update_skill
    # if cancel button pressed
    if Input.trigger?(Input::B)
      # play sound and return to main command
      $game_system.se_play($data_system.cancel_se)
      @command_window.active, @skill_window.active = true, false
      @status_window.set_text(0)
      @skill_window.index = -1
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      skill = $data_skills[@skill_window.commands[@skill_window.index]]
      # if no Job Points skill or skill already maximized
      if @actor.jp == 0 || @actor.skill_max_level?(skill.id)
        # play sound
        $game_system.se_play($data_system.buzzer_se)
      else
        # play sound and create confirmation window
        $game_system.se_play($data_system.decision_se)
        @sure_window = Window_Dialog.new(224, BlizzCFG::YesNo,
            BlizzCFG::ImproveSkill)
        @skill_window.active = false
      end
    end
  end
  #----------------------------------------------------------------------------
  # update_sure
  #  This method updates the confirmation of learning input.
  #----------------------------------------------------------------------------
  def update_sure_learn
    # if cancel button pressed
    if Input.trigger?(Input::B)
      # play sound and remove confirmation window
      $game_system.se_play($data_system.cancel_se)
      @sure_window.dispose
      @learn_window.active, @sure_window = true, nil
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      # if confirmed
      if @sure_window.index == 0
        # consume Job Point
        @actor.jp -= 1
        # temporary variable
        id = @learn_window.commands[@learn_window.index].skill_id
        # if CRLS is installed and CD skill
        if $crls != nil && BlizzCFG::CD_SKILLS.include?(id)
          # learn new CD skill
          @actor.learn_cd(id)
        else
          # learn new skill
          @actor.learn_skill(id)
        end
        # update window displays
        @learn_window.refresh
        @skill_window.set_commands(@actor.skills.clone)
        if @learn_window.commands[0] == nil
          @command_window.disable_item(0)
        else
          @command_window.draw_item(0, @command_window.normal_color)
        end
        if @skill_window.commands[0] == nil
          @command_window.disable_item(1)
        else
          @command_window.draw_item(1, @command_window.normal_color)
        end
        @job_window.refresh
      end
      # remove confirmation window
      @sure_window.dispose
      @learn_window.active, @sure_window = true, nil
    end
  end
  #----------------------------------------------------------------------------
  # update_sure
  #  This method updates the confirmation of improving input.
  #----------------------------------------------------------------------------
  def update_sure_skill
    # if cancel button pressed
    if Input.trigger?(Input::B)
      # play sound and remove confirmation window
      $game_system.se_play($data_system.cancel_se)
      @sure_window.dispose
      @skill_window.active, @sure_window = true, nil
    # if confirm button pressed
    elsif Input.trigger?(Input::C)
      $game_system.se_play($data_system.decision_se)
      if @sure_window.index == 0
        skill = $data_skills[@skill_window.commands[@skill_window.index]]
        # consume Job Point
        @actor.jp -= 1
        # improve skill
        @actor.skill_level_change(@actor.skill_level(skill.id) + 1, skill.id)
        # update window displays
        [@status_window, @skill_window, @learn_window, @job_window].each {|win|
            win.refresh}
        (0..1).each {|i| @command_window.draw_item(i, Color.new(255, 255, 255))}
        @command_window.disable_item(0) if @learn_window.commands[0] == nil
        @command_window.disable_item(1) if @skill_window.commands[0] == nil
      end
      # remove confirmation window
      @sure_window.dispose
      @skill_window.active, @sure_window = true, nil
    end
  end
  
end

 

Share this post


Link to post
Share on other sites

as you have put the code in spoiler for better view

to become more organized Thank you!

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...