All pastes #1964190 Raw Edit

Gamma FFVJob System for RMVX

public text v1 · immutable
#1964190 ·published 2010-10-16 18:17 UTC
rendered paste body
# Gammastar's FFVJOB System (although in actuality it may be more similar to
# FF Tactics Advance... Whatever.)
#
# In order to ensure compatibility, this MUST go as close to Main as possible,
# at the very least below battle system.
#
# Also I currently do not think it will be compatible with custom menu's. If it
# is, it's a miracle.

module GAMMA_FFVJOB_SYSTEM
  # Names of all the jobs in the game.
  JOBS = [
    "Paladin",     #0
    "Warrior",     #1
    "Priest",      #2
    "Magician",    #3
    "Knight",      #4
    "Dark Knight", #5
    "Theif",       #6
    "Grappler",    #7
    "Scatman"      #8
  ]
  
  # Main Jobs of each actor. X is actor ID, Y is name of job.
  STARTING_JOBS = {
   #X    #Y
    9 => "Paladin"
  }
  
  INHERENT_COMMANDS = {
    #DO NOT TOUCH THIS
  }
  
  # Inherent abilities are those that are gained automatically upon
  # equipping a particular class. For now they are just defiend, not
  # assigned to their jobs.
  INHERENT_ABILITIES = {
    "Sword Mastery"    => "Allows equipping swords.",
    "Spear Mastery"    => "Allows equipping spears.",
    "Dagger Mastery"   => "Allows equipping daggers.",
    "Bow Mastery"      => "Allows equipping bows.",
    "Axe Mastery"      => "Allows equipping axes.",
    "Weapons Mastery"  => "Allows equipping all weapons.",
    "SPI Bonus"        => "+20 SPI.", 
    "ATK Bonus"        => "+20 ATK.", 
    "DEF Bonus"        => "+20 DEF.",
    "AGI Bonus"        => "+20 AGI.",
    "Loot Bonus"       => "Gain more loot from enemy drops.",
    "Arcane Knowledge" => "Does something or another.",
    "Divine Favor"     => "You get the point.",
    "Brute Force"      => "Blah blah blah",
    "Acoustic Glory"   => "I'm the Scatman!",
  }
  
  # Here you assign inherent abilities to jobs. Note that jobs can share
  # inherent abilites, like paladin and warrior both having sword mastery.
  JOB_INHERENTS = {
    "Paladin"     => ["Sword Mastery", "Spear Mastery", "DEF Bonus", "Divine Favor"],
    "Warrior"     => ["Sword Mastery", "Axe Mastery", "ATK Bonus", "Brute Force"],
    "Priest"      => ["Dagger Mastery", "Bow Mastery", "SPI Bonus", "Divine Favor"],
    "Magician"    => ["Dagger Mastery", "Bow Mastery", "SPI Bonus", "Arcane Knowledge"],
    "Knight"      => ["Sword Mastery", "Spear Mastery", "ATK Bonus"],
    "Dark Knight" => ["Sword Mastery", "Axe Mastery", "ATK Bonus"],
    "Theif"       => ["Dagger Mastery", "ATK Bonus", "AGI Bonus", "Loot Bonus"],
    "Grappler"    => ["ATK Bonus", "DEF Bonus", "AGI Bonus"],
    "Scatman"     => ["Weapons Mastery", "ATK Bonus", "Acoustic Glory"],
  }
  
  # This relates to earning job levels and the stat bonuses associated
  # with that. It breaks down like this:
  #   X: Stat ID (1 - ATK, 2 - DEF, 3 - SPI, 4 - AGI, 5 - MAXHP, 6 - MAXMP)
  #   Y: Base stat bonus given by job
  #   Z: Bonus added on per level in job.
  # NOTE: An actor's main job will give full stat bonuses; his sub-job
  #       will give half of the values seen here; secondary active jobs
  #       give no stat bonuses.
  JOB_STATS = {       #X1    Y1    Z1   X2 Y2 Z2 etc.
    "Paladin"     => [[1,    10,   2], [2, 5, 1], [5, 10, 5]],
    "Warrior"     => [[1,    15,   3], [2, 7, 1], [5, 16, 6]],
    "Priest"      => [[3,    13,   2], [2, 4, 1], [6, 12, 4]],
    "Magician"    => [[3,    15,   2], [2, 3, 1], [6, 17, 5]],
    "Knight"      => [[2,    15,   3], [1, 8, 2], [5, 13, 5]],
    "Dark Knight" => [[1,    13,   3], [3, 6, 2], [5, 15, 5]],
    "Theif"       => [[4,    15,   2], [2, 5, 1], [5, 6,  3]],
    "Grappler"    => [[2,    13,   2], [4, 6, 1], [5, 8,  4]],
    "Scatman"     => [[1,    30,   10],[2, 30, 10],[3, 30, 10],[4, 30, 10]]
  }
  
  # Don't worry about this right now.
  JOB_LEVELS = [10, 35]
  
  # Or this.
  EXPEND_JP = false
  
  # This is what will appear when a subclass is not chosen.
  EMPTY_SUBCLASS_NAME = "None"
  
  # The ID's of the jobs that are unlocked at start.
  UNLOCKED_JOBS = [0, 1, 2, 3]
  
  # Configuration option for using different sprites for different (main) jobs.
  USE_SPECIAL_SPRITES = true
  
  # These particular inherent abilities have passive effects, and as such, are
  # linked with states in the database by ID.
  PASSIVE_STATES = {  #state id 
    "Sword Mastery"   => 18,
    "Spear Mastery"   => 19,
    "Dagger Mastery"  => 20,
    "Bow Mastery"     => 21,
    "Axe Mastery"     => 22,
    "Weapons Mastery" => 23,
  }
  
  # These are the suffixes that will go on the spritesheets. For example:
  #   $john.png is the base sprite for John.
  #   $john-paladin.png is the Paladin sprite for John.
  #   etc.
  JOB_SPRITE_SUFFIXES = [
    "-paladin",
    "-warrior",
    "-priest",
    "-magician",
    "-knight",
    "-dknight",
    "-theif",
    "-grappler",
    "-scatman",
  ]  
  
  # This is getting into the Abilities system. These are equippable from the
  # Abilities menu and usable from the battle menu.
  #   X is the level at which the ability is learned (use 0 for ONE inherent ability per class)
  #   Y is the skill linked with the ability. Set to -1 for a skill menu of the SAME NAME as the ability
  ABILITIES = {                       #Class name   #X #Y   #Description
    "Divine Arts"                 => ["Paladin",     0, -1, "The Paladin's white magic."],
    "Power Up!"                   => ["Warrior",     0, 0, "Raise your power level!"],
    "Heal Bonus"                  => ["Priest",      0, 0, "Healing does more."],
    "Magic Trick"                 => ["Magician",    0, 0, "Rabbit out of hat?"],
    "Nonspecific Party-wide Buff" => ["Knight",      0, 0, "Gives positive effects to the entire party."],
    "Batman Power!"               => ["Dark Knight", 0, 0, "Why so serious?"],
    "Steal Itemz"                 => ["Theif",       0, 0, "Youz a takin their stuffz"],
    "Ima beat the crap outa you"  => ["Grappler",    0, 0, "Meow!"],
    "Scat"                        => ["Scatman",     0, 0, "Skibbidy boopmbapbeepmbopm bibbidybobbidydujidedo do"],
    "Holy Something"              => ["Paladin",     2, 84, "Does something holy-ish."],
    "Warrior Ability 1"           => ["Warrior",     2, 0, "Punctuation inconsistency!"],
  }
  
  # This is for Abilities in which a -1 was put into the skill slot, indicating
  # a list of abilities. Place the skill ID's of the skills you want in the menu
  # in an array, like this.
  ABILITY_MENUS = {
    "Divine Arts" => [33, 34, 35, 38, 39, 40, 52, 59]
  }
  
  # The default number of ability slots per job.
  DEFAULT_JOB_ABILITY_SLOTS = 2
  
  # Special cases for special jobs. Scatman has 3 ability slots.
  SPECIAL_JOB_ABILITY_SLOTS = {
    "Scatman" => 3
  }
  
  # This is for equipment. The left side is the equip type, the right is the states
  # that allow an actor to equip weapons of that type.
  # 1 = Swords, 2 = Spears, 3 = Daggers, 4 = Bows,  5 = Axes
  # Notice how 23 is in all of them, indicating a Weapons Mastery state.
  EQUIP_PASSIVES = {
    1 => [18, 23],
    2 => [19, 23],
    3 => [20, 23],
    4 => [21, 23],
    5 => [22, 23],
  }
  
  # I honestly don't remember what this is for. ... :D
  PASSIVE_EFFECTS = {
    "Paladin" => [
          ["Sword Mastery", 3],
          ["Spear Mastery", 3],
          ["DEF Bonus",     4],
          ["Divine Favor",  6],
          ],
    "Warrior" => [
          ["Sword Mastery", 3],
          ["Axe Mastery",   3],
          ["ATK Bonus",     4],
          ["Brute Force",   6],
          ],         
  }
  
  # Special tags, do not modify.
  FOR_JOB = /<(?:FOR_JOB|for job):[ ](.*)>/i
  
  UNLOCK_JOB = /<(?:UNLOCK_JOB|unlock job):[ ](.*)>/i
  
  EQUIP_TYPE = /<(?:EQUIP_TYPE|g equip type):[ ](.*)>/i
end

# Here begins the good stuff :D I'll put comments around here eventually...
class RPG::Skill < RPG::UsableItem
  attr_reader :limit_to_job
  def create_ffvjob_cache
    self.note.split(/[\r\n]+/).each { |line|
      case line
      when GAMMA_FFVJOB_SYSTEM::FOR_JOB
        @limit_to_job = $1.to_s
      end      
    }
  end
end

class RPG::Weapon < RPG::BaseItem
  attr_reader :g_equip_type
  def create_ffvjob_cache
    self.note.split(/[\r\n]+/).each { |line|
      case line
      when GAMMA_FFVJOB_SYSTEM::EQUIP_TYPE
        @g_equip_type = $1.to_i
      end      
    }
  end
end

class RPG::Item < RPG::UsableItem
  attr_reader :job_unlock
  def create_ffvjob_cache
    self.note.split(/[\r\n]+/).each { |line|
      case line
      when GAMMA_FFVJOB_SYSTEM::UNLOCK_JOB
        @job_unlock = $1.to_i
      end      
    }
  end
end

class Scene_Title < Scene_Base
  alias gamma_ffvjob_title_ld load_database
  def load_database
    gamma_ffvjob_title_ld
    load_ffvjob_cache
    do_that_other_stuff
  end
  
  def load_ffvjob_cache
    groups = [$data_skills, $data_weapons, $data_items]
    for group in groups
      for obj in group
        next if obj == nil
        obj.create_ffvjob_cache
      end
    end
  end
  
  def do_that_other_stuff
    for ability in GAMMA_FFVJOB_SYSTEM::ABILITIES.values
      if ability[1] == 0
        a = {ability[0] => GAMMA_FFVJOB_SYSTEM::ABILITIES.corresponding_key(ability)}
        GAMMA_FFVJOB_SYSTEM::INHERENT_COMMANDS.merge!(a)
      end
    end
  end
end

class Game_Actor < Game_Battler
  attr_accessor :learned_abilities
  attr_accessor :abilities
  attr_accessor :jp_hash
  attr_accessor :starting_job
  attr_accessor :job
  attr_accessor :sub_job
  attr_accessor :second_active
  attr_accessor :inh_abs
  attr_accessor :passive_effects
  attr_reader   :base_sprite
  attr_reader   :plus_atk
  attr_reader   :plus_def
  attr_reader   :plus_spi
  attr_reader   :plus_agi
  
  alias gamma_ffvjobs_actor_setup setup
  def setup(actor_id)
    gamma_ffvjobs_actor_setup(actor_id)
    actor = $data_actors[actor_id]
    @starting_job = GAMMA_FFVJOB_SYSTEM::STARTING_JOBS[actor_id]
    @job = @starting_job
    @sub_job = GAMMA_FFVJOB_SYSTEM::EMPTY_SUBCLASS_NAME
    @second_active = GAMMA_FFVJOB_SYSTEM::EMPTY_SUBCLASS_NAME
    
    jobs = [@job, @sub_job, @second_active]
    for ability in GAMMA_FFVJOB_SYSTEM::ABILITIES.values
      if jobs.include?(ability[0]) and ability[2] != -1
        next if $data_skills[ability[2]] == nil
        learn_skill(ability[2])
      end
    end    
    
    @learned_abilities = []
    @passive_effects = []
    @jp_hash = {}
    for i in 0..GAMMA_FFVJOB_SYSTEM::JOBS.size
      temp_jph = {GAMMA_FFVJOB_SYSTEM::JOBS[i] => [1, 0]}
      @jp_hash.merge!(temp_jph)
    end    
    @base_sprite = self.character_name
    set_graphic(self.character_name + "-paladin", self.character_index, self.face_name, self.face_index)
    reset_plus_stats
    setup_abilities
    update_inherent_abilities
    self.hp = self.maxhp
    self.mp = self.maxmp
  end
  
  def reset_plus_stats
    @plus_atk = 0
    @plus_def = 0
    @plus_spi = 0
    @plus_agi = 0
  end
  
  def change_job(type, new_job)
    case type
    when 0
      @job = new_job
      setup_abilities
      change_sprite_suffix(GAMMA_FFVJOB_SYSTEM::JOB_SPRITE_SUFFIXES[GAMMA_FFVJOB_SYSTEM::JOBS.index(@job)])
    when 1
      @sub_job = new_job
    when 2
      @second_active = new_job
    end
    jobs = [@job, @sub_job, @second_active]
    for ability in GAMMA_FFVJOB_SYSTEM::ABILITIES.values
      if jobs.include?(ability[0]) and $data_skills[ability[2]] != nil
        learn_skill(ability[2]) unless skills.include?($data_skills[ability[2]])
      end
    end
  end
  
  def can_change_job?(new_job)
    return false if !GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.include?(GAMMA_FFVJOB_SYSTEM::JOBS.index(new_job))
    return false if @job == new_job
    return false if @sub_job == new_job
    return false if @second_active == new_job
    return true
  end
  
  def reset_jobs
    @job = @starting_job
    @sub_job = GAMMA_FFVJOB_SYSTEM::EMPTY_SUBCLASS_NAME
    @second_active = GAMMA_FFVJOB_SYSTEM::EMPTY_SUBCLASS_NAME
    change_sprite_suffix(GAMMA_FFVJOB_SYSTEM::SPRITE_SUFFIXES[GAMMA_FFVJOB_SYSTEM::JOBS.index(@job)])
  end
  
  def set_stat_arrays
    @main_stats = GAMMA_FFVJOB_SYSTEM::JOB_STATS[@job]
    @sub_stats = GAMMA_FFVJOB_SYSTEM::JOB_STATS[@sub_job] if @sub_job != "None"
  end
  
  def level_job(job_id, ignore_exp = false)
    if ignore_exp == false
      return unless @jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][1] == calc_exp_next_job(job_id)
    end
    @jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][0] += 1
    @jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][1] = 0
    for ability in GAMMA_FFVJOB_SYSTEM::ABILITIES.values
      if ability[0] == @job and ability[1] == @jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][0]
        learn_ability(ability)
      end      
    end
    if GAMMA_FFVJOB_SYSTEM::PASSIVE_EFFECTS[@job][1] == @jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][0]
      @passive_effects.push(GAMMA_FFVJOB_SYSTEM::PASSIVE_EFFECTS[@job][0])
    end
  end
  
  def learn_ability(ability)
    @learned_abilities.push(GAMMA_FFVJOB_SYSTEM::ABILITIES.keys[GAMMA_FFVJOB_SYSTEM::ABILITIES.values.index(ability)])
    if $data_skills[ability[2]] != nil
      learn_skill(ability[2])
    end
  end
  
  def calc_exp_next_job(job_id)
    a = GAMMA_FFVJOB_SYSTEM::JOB_LEVELS[0]*@jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][0]
    b = GAMMA_FFVJOB_SYSTEM::JOB_LEVELS[1]*@jp_hash[GAMMA_FFVJOB_SYSTEM::JOBS[job_id]][0]
    a += (b/100).ceil
    return a
  end
  
  alias gamma_ffvjob_actor_eq equippable?
  def equippable?(item)
    if item.is_a?(RPG::Weapon)
      a = item.g_equip_type if item.g_equip_type != nil
      b = GAMMA_FFVJOB_SYSTEM::EQUIP_PASSIVES[a]
      for i in 0..b.size
        next if b[i] == nil
        c = true if self.states.include?($data_states[b[i]])
      end
      return true if c == true
      return false
    end
    gamma_ffvjob_actor_eq(item)
  end
  
  def setup_abilities
    @abilities = []
    if GAMMA_FFVJOB_SYSTEM::SPECIAL_JOB_ABILITY_SLOTS[@job] != nil
      max = GAMMA_FFVJOB_SYSTEM::SPECIAL_JOB_ABILITY_SLOTS[@job]
    else
      max = GAMMA_FFVJOB_SYSTEM::DEFAULT_JOB_ABILITY_SLOTS
    end
    for i in 1..max
      @abilities.push("[None]")
    end
  end
  
  def update_inherent_abilities
    @inh_abs = []
    j_inh_abs = GAMMA_FFVJOB_SYSTEM::JOB_INHERENTS[@job]
    s_inh_abs = GAMMA_FFVJOB_SYSTEM::JOB_INHERENTS[@sub_job]
    for inh_ab in j_inh_abs
      @inh_abs.push(inh_ab)
    end
    if @sub_job != GAMMA_FFVJOB_SYSTEM::EMPTY_SUBCLASS_NAME
      for inh_ab in s_inh_abs
        @inh_abs.push(inh_ab) if !@inh_abs.include?(inh_ab)
      end
    end
    for inh_ab in GAMMA_FFVJOB_SYSTEM::INHERENT_ABILITIES.keys
      remove_state(GAMMA_FFVJOB_SYSTEM::PASSIVE_STATES[inh_ab])
    end
    for inh_ab in @inh_abs
      if GAMMA_FFVJOB_SYSTEM::PASSIVE_STATES.keys.include?(inh_ab)
        add_state(GAMMA_FFVJOB_SYSTEM::PASSIVE_STATES[inh_ab])
      end
    end
  end
  
  def change_sprite_suffix(sprite_suffix)
    return if GAMMA_FFVJOB_SYSTEM::USE_SPECIAL_SPRITES == false
    set_graphic(@base_sprite + sprite_suffix, self.character_index, self.face_name, self.face_index)
    $game_player.refresh
  end
  
  def change_sprite(sprite_name)
    return if GAMMA_FFVJOB_SYSTEM::USE_SPECIAL_SPRITES == false
    set_graphic(sprite_name, self.character_index, self.face_name, self.face_index)
    $game_player.refresh
  end
  
  def base_atk
    set_stat_arrays
    n = actor.parameters[2, @level]
    for item in equips.compact do n += item.atk end    
    for stat_mod in @main_stats
      if stat_mod[0] == 1
        n += stat_mod[1]
        n += (stat_mod[2]*self.level) 
      end
    end
    return n if @sub_job == "None"
    for stat_mod in @sub_stats
      if stat_mod[0] == 1
        n += (stat_mod[1]/2).ceil
      end
    end
    return n
  end
  
  def base_def
    set_stat_arrays
    n = actor.parameters[3, @level]
    for item in equips.compact do n += item.def end    
    for stat_mod in @main_stats
      if stat_mod[0] == 2
        n += stat_mod[1]
        n += (stat_mod[2]*self.level) 
      end
    end
    return n if @sub_job == "None"
    for stat_mod in @sub_stats
      if stat_mod[0] == 2
        n += (stat_mod[1]/2).ceil
      end
    end
    return n
  end
  
  def base_spi
    set_stat_arrays
    n = actor.parameters[4, @level]
    for item in equips.compact do n += item.spi end    
    for stat_mod in @main_stats
      if stat_mod[0] == 3
        n += stat_mod[1]
        n += (stat_mod[2]*self.level) 
      end
    end
    return n if @sub_job == "None"
    for stat_mod in @sub_stats
      if stat_mod[0] == 3
        n += (stat_mod[1]/2).ceil
      end
    end
    return n
  end
  
  def base_agi
    set_stat_arrays
    n = actor.parameters[4, @level]
    for item in equips.compact do n += item.agi end    
    for stat_mod in @main_stats
      if stat_mod[0] == 4
        n += stat_mod[1]
        n += (stat_mod[2]*self.level) 
      end
    end
    return n if @sub_job == "None"
    for stat_mod in @sub_stats
      if stat_mod[0] == 4
        n += (stat_mod[1]/2).ceil
      end
    end
    return n
  end
  
  def base_maxhp
    return true_base_maxhp if @job == nil
    set_stat_arrays
    n = actor.parameters[0, @level]
    for stat_mod in @main_stats
      if stat_mod[0] == 5
        n += stat_mod[1]
        n += (stat_mod[2]*self.level) 
      end
    end
    @hp = n if @hp > n
    return n if @sub_job == "None"
    for stat_mod in @sub_stats
      if stat_mod[0] == 5
        n += (stat_mod[1]/2).ceil
      end
    end
    @hp = n if @hp > n
    return n
  end
  
  def base_maxmp
    return true_base_maxmp if @job == nil    
    set_stat_arrays
    n = actor.parameters[1, @level]
    for stat_mod in @main_stats
      if stat_mod[0] == 6
        n += stat_mod[1]
        n += (stat_mod[2]*self.level) 
      end
    end
    @mp = n if @mp > n
    return n if @sub_job == "None"
    for stat_mod in @sub_stats
      if stat_mod[0] == 6
        n += (stat_mod[1]/2).ceil
      end
    end
    @mp = n if @mp > n
    return n
  end
  
  def skills
    result = []
    for i in @skills
      s = $data_skills[i]
      @jobs = [@job, @sub_job, @second_active]
      if s.limit_to_job != nil
        next if !@jobs.include?(s.limit_to_job)
      end
      result.push($data_skills[i])
    end
    return result
  end
  
  def true_base_atk
    n = actor.parameters[2, @level]
    for item in equips.compact do n += item.atk end
    return n
  end

  def true_base_def
    n = actor.parameters[3, @level]
    for item in equips.compact do n += item.def end
    return n
  end

  def true_base_spi 
    n = actor.parameters[4, @level]
    for item in equips.compact do n += item.spi end
    return n
  end
    
  def true_base_agi
    n = actor.parameters[5, @level]
    for item in equips.compact do n += item.agi end
    return n
  end
  
  def true_base_maxhp
    return actor.parameters[0, @level]
  end

  def true_base_maxmp
    return actor.parameters[1, @level]
  end
end

class Scene_Jobs < Scene_Base
  def initialize(actor_index, main_index = 0)
    @actor_index = actor_index
    @main_index = main_index
    @real_actor = $game_party.members[@actor_index]
    @current_actor = @real_actor.clone
    @old_sprite = @current_actor.character_name
    @job_index = GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.index(GAMMA_FFVJOB_SYSTEM::JOBS.index(@current_actor.job))
    @subjob_index = GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.index(GAMMA_FFVJOB_SYSTEM::JOBS.index(@current_actor.sub_job)) if @current_actor.sub_job != "None"
    @sa_index = GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.index(GAMMA_FFVJOB_SYSTEM::JOBS.index(@current_actor.second_active)) if @current_actor.second_active != "None"
  end
  
  def start
    super
    create_menu_background
    create_windows
    @main_window.active = true
    @main_window.index = @main_index
    @inherents_window.active = false
    @inherents_window.index = -1
  end
  
  def terminate
    super
    dispose_menu_background
    @main_window.dispose
    @stats_window.dispose
    @info_window.dispose
    @inherents_window.dispose
    @job_change_window.dispose
  end
  
  def create_windows
    @stats_window = Window_JobStats.new(0, 0, @current_actor)
    @stats_window.x = 544 - @stats_window.width
    @info_window = Window_Base.new(0, 200, 544, 75)
    create_main_window
    create_inherents_window
    create_job_change_window
    create_info_contents
  end
  
  def create_main_window
    s1 = "Class: " + @current_actor.job
    s2 = "Sub-Class: " + @current_actor.sub_job
    s3 = "Secondary Active: " + @current_actor.second_active
    s4 = "Passive 1: "
    s5 = "Passive 2: "
    s6 = "Passive 3: "
    s7 = "Inherent Abilities"
    @main_window = Window_Command.new(335, [s1, s2, s3, s4, s5, s6, s7])
  end
  
  def create_inherents_window
    @current_actor.update_inherent_abilities
    @inherents_window = Window_Command.new(544, @current_actor.inh_abs, 3) 
    @inherents_window.y = 275
    @inherents_window.height = 141
  end
  
  def create_job_change_window
    @available_jobs = []
    for i in 0..(GAMMA_FFVJOB_SYSTEM::JOBS.size - 1)
      next unless GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.include?(i)
      @available_jobs.push(GAMMA_FFVJOB_SYSTEM::JOBS[i])
    end
    @job_change_window = Window_Command.new(169, @available_jobs)
    @job_change_window.x = 166
    @job_change_window.height = 200
    @job_change_window.opacity = 255
    @job_change_window.visible = false
    @job_change_window.active = false
  end
  
  def update    
    @main_window.update
    @job_change_window.update
    @stats_window.update
    @info_window.update
    @inherents_window.update
    if @inherents_window.active
      change_info_contents(@current_actor.inh_abs[@inherents_window.index])
    else
      create_info_contents
    end
    update_cmd_selection
  end
  
  def create_info_contents
    @info_window.contents.clear
    @info_window.contents.draw_text(0, 0, 300, 24, "Inherent Abilities:")
  end
  
  def change_info_contents(inherent_ability)
    return if !GAMMA_FFVJOB_SYSTEM::INHERENT_ABILITIES.include?(inherent_ability)
    @info_window.contents.clear
    @info_window.contents.draw_text(0, 0, 300, 24, inherent_ability + ":")
    @info_window.contents.draw_text(0, 20, 300, 24, GAMMA_FFVJOB_SYSTEM::INHERENT_ABILITIES[inherent_ability])
  end
  
  def next_actor
    @actor_index += 1
    @actor_index %= $game_party.members.size
    $scene = Scene_Jobs.new(@actor_index, @main_window.index)
  end
  
  def prev_actor
    @actor_index += $game_party.members.size - 1
    @actor_index %= $game_party.members.size
    $scene = Scene_Jobs.new(@actor_index, @main_window.index)
  end
  
  def update_actor_sprite
    if @job_change_window.active and @main_window.index == 0
      @current_actor.change_sprite_suffix(GAMMA_FFVJOB_SYSTEM::JOB_SPRITE_SUFFIXES[GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS[@job_change_window.index]])
      @stats_window.refresh
      
    end
  end
  
  def update_cmd_selection
    if Input.trigger?(Input::B)
      Sound.play_cancel
      if @main_window.active
        $scene = Scene_Menu.new(0, 0)
      elsif @job_change_window.active
        @job_change_window.active = false
        @job_change_window.visible = false
        @main_window.active = true
        @job_index = @job_change_window.index if @main_window.index == 0
        @subjob_index = @job_change_window.index if @main_window.index == 1
        @sa_index = @job_change_window.index if @main_window.index == 2
        @current_actor.change_sprite(@old_sprite)
        @stats_window.refresh        
      elsif @inherents_window.active
        @inherents_window.active = false
        @inherents_window.index = -1
        @main_window.active = true
      end
    elsif Input.trigger?(Input::C)
      Sound.play_decision
      if @main_window.active
        case @main_window.index
        when 0, 1, 2
          @old_sprite = @current_actor.character_name
          @job_change_window.visible = true
          @job_change_window.active = true
          case @main_window.index
          when 0
            @job_change_window.index = @job_index
          when 1
            @job_change_window.index = @subjob_index if @subjob_index != nil
          when 2
            @job_change_window.index = @sa_index if @sa_index != nil
          end        
          update_actor_sprite
          @main_window.active = false
        when 3, 4, 5
        when 6
          @main_window.active = false
          @inherents_window.index = 0
          @inherents_window.active = true
        end      
      elsif @job_change_window.active
        type = @main_window.index
        new_job = GAMMA_FFVJOB_SYSTEM::JOBS[GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS[@job_change_window.index]]
        if @real_actor.can_change_job?(new_job)
          @real_actor.change_job(type, new_job)
          if @main_window.index == 0
            @real_actor.change_sprite_suffix(GAMMA_FFVJOB_SYSTEM::JOB_SPRITE_SUFFIXES[GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS[@job_change_window.index]])            
          end
          case @main_window.index
          when 0
            Sound.play_use_item if @job_change_window.index != @job_index
          when 1
            Sound.play_use_item if @job_change_window.index != @subjob_index
          when 2
            Sound.play_use_item if @job_change_window.index != @sa_index
          end        
          $scene = Scene_Jobs.new(@actor_index, @main_window.index)
        else
          Sound.play_buzzer
        end
      end
    elsif Input.trigger?(Input::LEFT)
      if @main_window.active
        Sound.play_cursor
        prev_actor
      end
    elsif Input.trigger?(Input::RIGHT)
       if @main_window.active 
        Sound.play_cursor
        next_actor
      end
    elsif Input.trigger?(Input::UP)
      if @job_change_window.active and @main_window.index == 0
        update_actor_sprite
      end
    elsif Input.trigger?(Input::DOWN)
      if @job_change_window.active and @main_window.index == 0
        update_actor_sprite
      end
    end
  end
end

class Scene_Abilities < Scene_Base
  def initialize(actor_index, main_index = 0)
    @actor_index = actor_index
    @current_actor = $game_party.members[actor_index]
    @main_index = main_index
  end
  
  def start
    super
    create_menu_background
    create_windows
    @main_window.active = true
    @main_window.index = @main_index
    @abilities_window.active = false
    @abilities_window.index = -1
  end
  
  def terminate
    super
    dispose_menu_background
    @main_window.dispose
    @actor_window.dispose
    @info_window.dispose
    @extra_window.dispose
    @abilities_window.dispose
  end
  
  def create_windows    
    @main_window = Window_Command.new(180, @current_actor.abilities)
    @abilities = ["[None]", GAMMA_FFVJOB_SYSTEM::INHERENT_COMMANDS[@current_actor.job]]
    for ability in @current_actor.learned_abilities
      next if ability == nil
      @abilities.push(ability)
    end
    create_actor_window
    @abilities_window = Window_Command.new(544-@main_window.width, @abilities, 2)
    @extra_window = Window_Base.new(0, @actor_window.height, @main_window.width, 60)
    @extra_window.contents.draw_text(0, 0, 150, 24, "Abilities")
    @main_window.y = (@actor_window.height + @extra_window.height)
    @main_window.height = 125
    @abilities_window.x = (544 - @abilities_window.width)
    @abilities_window.y = @extra_window.y
    @abilities_window.height = (@extra_window.height + @main_window.height)
    @blah = Window_Base.new(0, (@main_window.y+@main_window.height), 544, 1)
    @info_window = Window_Base.new(0, (@main_window.y+@main_window.height), 544, (416-@blah.y))
    @blah.dispose
  end
  
  def create_actor_window
    @actor_window = Window_Base.new(0, 0, 544, 125)
    @actor_window.contents.draw_text(0, 0, 150, 24, @current_actor.name)
    @actor_window.draw_actor_graphic(@current_actor, 16, 64)
    @actor_window.contents.draw_text(0, 67, 150, 24, "Can Equip:")
    @actor_window.draw_actor_equippable_thingies(@current_actor, 100, 67, 240)
    @actor_window.contents.draw_text(40, 24, 200, 24, @current_actor.job)
    @actor_window.contents.draw_text(40, 45, 100, 24, "Lv")
    @actor_window.contents.draw_text(64, 45, 100, 24, @current_actor.jp_hash[@current_actor.job][0])
    @actor_window.contents.draw_text(400, 67, 150, 24, "Abilities:")
    @actor_window.contents.draw_text(480, 67, 100, 24, (@abilities.size-1))
  end
  
  def update
    @main_window.update
    @abilities_window.update
    if @abilities_window.active and @abilities_window.index != 0
      change_info_contents(@abilities[@abilities_window.index])
    else
      @info_window.contents.clear
    end
    update_selection
  end
  
  def change_info_contents(ability)
    @info_window.contents.clear
    @info_window.contents.draw_text(0, 0, 200, 24, ability+":")
    @info_window.contents.draw_text(0, 32, 544, 24, GAMMA_FFVJOB_SYSTEM::ABILITIES[ability][3])
  end
  
  def next_actor
    @actor_index += 1
    @actor_index %= $game_party.members.size
    $scene = Scene_Abilities.new(@actor_index, @main_window.index)
  end
  
  def prev_actor
    @actor_index += $game_party.members.size - 1
    @actor_index %= $game_party.members.size
    $scene = Scene_Abilities.new(@actor_index, @main_window.index)
  end
  
  def update_selection
    if Input.trigger?(Input::B)
      Sound.play_cancel
      if @main_window.active
        $scene = Scene_Menu.new(0, 1)
      else
        @abilities_window.active = false
        @abilities_window.index = -1
        @main_window.active = true
      end
    elsif Input.trigger?(Input::C)
      Sound.play_decision
      if @main_window.active
        @main_window.active = false
        @abilities_window.active = true
        @abilities_window.index = 0
      elsif @abilities_window.active
        new_ability = @abilities[@abilities_window.index]
        if !@current_actor.abilities.include?(new_ability) or @abilities_window.index == 0
          @current_actor.abilities[@main_window.index] = new_ability
          @main_window.refresh
          @abilities_window.active = false
          @abilities_window.index = -1
          @main_window.active = true
        else 
          Sound.play_buzzer
        end         
      end
    elsif Input.trigger?(Input::LEFT)
      if @main_window.active
        Sound.play_cursor
        prev_actor
      end
    elsif Input.trigger?(Input::RIGHT)
      if @main_window.active
        Sound.play_cursor
        next_actor
      end
    end
  end
end

class Scene_Menu < Scene_Base
  alias gamma_ffvjob_menu_init initialize
  def initialize(menu_index = 0, job_index = nil)
    gamma_ffvjob_menu_init
    @job_index = job_index
    @g_menu_index = menu_index
  end
  
  alias gamma_ffvjob_menu_start start
  def start
    gamma_ffvjob_menu_start
    if @job_index != nil
      @command_window.index = -1
      @command_window.active = false      
      @job_command_window.index = @job_index
      @job_command_window.active = true      
    else
      @command_window.index = @g_menu_index
    end
  end
  
  alias gamma_ffvjob_menu_ccw create_command_window
  def create_command_window
    gamma_ffvjob_menu_ccw
    create_job_command_window
    @command_window.y = 80
  end
  
  def create_job_command_window
    @job_command_window = Window_Command.new(@command_window.width, ["Job", "Abilities"])
    @job_command_window.index = -1
    @job_command_window.active = false
  end
  
  alias gamma_ffvjob_menu_update update
  def update
    gamma_ffvjob_menu_update
    @job_command_window.update
    if @job_command_window.active
      update_command_selection
    end
  end
  
  alias gamma_ffvjob_menu_ucs update_command_selection
  def update_command_selection
    gamma_ffvjob_menu_ucs
    if Input.trigger?(Input::UP)
      if @job_command_window.index == 1 and @job_command_window.active
        @job_command_window.index = -1
        @job_command_window.active = false
        @command_window.active = true
        @command_window.index = @command_window.commands.size-1
      elsif @command_window.index == @command_window.commands.size-1 and @command_window.active
        @job_command_window.index = 1
        @job_command_window.active = true
        @command_window.active = false
        @command_window.index = -1
      end
    elsif Input.trigger?(Input::DOWN)
      if @job_command_window.index == 0 and @job_command_window.active        
        @job_command_window.index = -1
        @job_command_window.active = false
        @command_window.index = 0
        @command_window.active = true
      elsif @command_window.index == 0 and @command_window.active        
        @job_command_window.index = 0
        @job_command_window.active = true
        @command_window.index = -1      
        @command_window.active = false
      end
    elsif Input.trigger?(Input::C) and @job_command_window.index != -1
      start_actor_selection
    end
    Input.update
  end
  
  alias gamma_ffvjob_menu_sas start_actor_selection
  def start_actor_selection
    gamma_ffvjob_menu_sas
    @job_command_window.active = false if @job_command_window.active == true
  end
  
  alias gamma_ffvjob_menu_uas update_actor_selection
  def update_actor_selection
    gamma_ffvjob_menu_uas
    if Input.trigger?(Input::C)
      case @job_command_window.index
      when 0
        $scene = Scene_Jobs.new(@status_window.index)
      when 1
        $scene = Scene_Abilities.new(@status_window.index)
      end
    end
  end
  
  def end_actor_selection
    @command_window.active = true unless @job_command_window.index != -1
    @job_command_window.active = true if @job_command_window.index != -1
    @status_window.active = false
    @status_window.index = -1
    Input.update
  end
  
  alias gamma_ffvjob_menu_term terminate
  def terminate
    gamma_ffvjob_menu_term
    @job_command_window.dispose
  end
end

class Scene_Battle < Scene_Base
  def update_actor_command_selection
    if Input.trigger?(Input::B)
      Sound.play_cancel
      prior_actor
    elsif Input.trigger?(Input::C)
      case @actor_command_window.index
      when 0
        Sound.play_decision
        @active_battler.action.set_attack
        start_target_enemy_selection
      when @actor_command_window.commands.size-1
        Sound.play_decision
        start_item_selection
      else
        Sound.play_decision
        ability = GAMMA_FFVJOB_SYSTEM::ABILITIES[@active_battler.abilities[@actor_command_window.index-1]]
        @skill = $data_skills[ability[2]]
        if @skill != nil and ability[2] != -1
          @active_battler.last_skill_id = @skill.id
#~         if @active_battler.skill_can_use?(@skill)
          skill_stuff
#~         else
#~           Sound.play_buzzer
#~         end
        else
          start_skill_selection_gamma(@active_battler.abilities[@actor_command_window.index-1])
        end
      end
    end
  end
  
  def skill_stuff
    @active_battler.action.set_skill(@skill.id)
    @active_battler.action.kind = 1
    if @skill.need_selection?
      if @skill.for_opponent?
        start_target_enemy_selection
      else
        start_target_actor_selection
      end
    else
      end_skill_selection
      next_actor
    end
  end
  
  def start_skill_selection_gamma(ability_menu)
    @help_window = Window_Help.new
    @skill_window = Window_Skill_Gamma.new(0, 56, 544, 232, @active_battler, ability_menu)
    @skill_window.help_window = @help_window
    @actor_command_window.active = false
  end
  
end

class Window_JobStats < Window_Base
  def initialize(x, y, actor)
    super(x, y, 209, 200)
    @actor = actor
    self.x = x
    self.y = y
    refresh
  end   
  
  def refresh
    self.contents.clear
    draw_actor_name(@actor, 0, 0)
    draw_actor_graphic(@actor, 16, 64)
    draw_parameters(75, 24, @actor)
  end
  
  def draw_parameters(x, y, actor)
    self.contents.font.color = normal_color
    i = 1
    while i < 5
      case i
      when 1
        name = Vocab::atk
        value = (actor.base_atk - actor.true_base_atk)
      when 2
        name = Vocab::def
        value = (actor.base_def - actor.true_base_def)
      when 3
        name = Vocab::spi
        value = (actor.base_spi - actor.true_base_spi)
      when 4
        name = Vocab::agi
        value = (actor.base_agi - actor.true_base_agi)
      end
      self.contents.draw_text(x + 4, y*i, 80, WLH, name)
      self.contents.draw_text(x + 50, y*i, 20, WLH, "+", 1)
      self.contents.draw_text(x + 64, y*i, 30, WLH, value, 2)
      i += 1
    end
    i = 1
    while i < 3
      case i
      when 1
        name = Vocab::hp
        value = (actor.base_maxhp - actor.true_base_maxhp)
      when 2
        name = Vocab::mp
        value = (actor.base_maxmp - actor.true_base_maxmp)
      end
      self.contents.draw_text(0, (y*i + 48), 80, WLH, name)
      self.contents.draw_text(x - 45, (y*i + 48), 20, WLH, "+", 1)
      self.contents.draw_text(x - 30, (y*i + 48), 30, WLH, value, 2)
      i += 1
    end
  end
end

class Window_ActorCommand < Window_Command
  def setup(actor)
    @commands = [Vocab::attack]
    for ability in actor.abilities
      next if ability == "[None]"
      @commands.push(ability)
    end
    @commands.push(Vocab::item)
    @item_max = 4
    refresh
    self.index = 0
  end
end

class Window_Base
  def draw_actor_class(actor, x, y)
    self.contents.font.color = normal_color
    self.contents.draw_text(x, y, 108, WLH, actor.job)
  end
  
  def draw_actor_state(actor, x, y, width = 96)
    count = 0
    for state in actor.states
      next if GAMMA_FFVJOB_SYSTEM::PASSIVE_STATES.values.include?(state.id)
      draw_icon(state.icon_index, x + 24 * count, y)
      count += 1
      break if (24 * count > width - 24)
    end
  end
  
  def draw_actor_equippable_thingies(actor, x, y, width = 96)
    count = 0
    for state in actor.states
      next if !GAMMA_FFVJOB_SYSTEM::PASSIVE_STATES.values.include?(state.id)
      draw_icon(state.icon_index, x + 24 * count, y)
      count += 1
      break if (24 * count > width - 24)
    end
  end
end

class Game_Party < Game_Unit
  def unlock_job(job_id)
    return if GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.include?(job_id)
    return if job_id > (GAMMA_FFVJOB_SYSTEM::JOBS.size - 1)
    GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.push(job_id)
    GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.sort! do |a, b|
      a <=> b
    end
  end
  
  def lock_job(job_id)
    return if !GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.include?(job_id)
    return if job_id > (GAMMA_FFVJOB_SYSTEM::JOBS.size - 1)
    GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.delete_at(GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.index(job_id))
    GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS.sort! do |a, b|
      a <=> b
    end
    for actor in $game_party.members
      if actor.job == GAMMA_FFVJOB_SYSTEM::JOBS[job_id]
        actor.job = actor.starting_job
        actor.change_sprite_suffix(GAMMA_FFVJOB_SYSTEM::JOB_SPRITE_SUFFIXES[GAMMA_FFVJOB_SYSTEM::UNLOCKED_JOBS[GAMMA_FFVJOB_SYSTEM::JOBS.index(actor.job)]]) if GAMMA_FFVJOB_SYSTEM::USE_SPECIAL_SPRITES
        
      end
    end
  end

  alias gamma_ffvjob_party_gi gain_item
  def gain_item(item, n, include_equip = false)
    if item.job_unlock != nil and item.consumable == false
      if n > 0
        unlock_job(item.job_unlock)
      else
        lock_job(item.job_unlock)
      end 
    end
    gamma_ffvjob_party_gi(item, n, include_equip = false)
  end
  
  alias gamma_ffvjob_party_li lose_item
  def lose_item(item, n, include_equip = false)
    if item.job_unlock != nil and item.consumable == false
      lock_job(item.job_unlock)
    end
    gamma_ffvjob_party_li(item, n, include_equip = false)
  end
end

class Scene_Item < Scene_Base
  alias gamma_ffvjob_item_uin use_item_nontarget
  def use_item_nontarget    
    if @item.job_unlock != nil
      $game_party.unlock_job(@item.job_unlock)
    end
    gamma_ffvjob_item_uin
  end
end

class Game_Interpreter
  def unlock_job(job_id)
    $game_party.unlock_job(job_id)
  end
  
  def lock_job(job_id)
    $game_party.lock_job(job_id)
  end
  
  def change_job(actor_id, job)
    actor = $game_actors[actor_id]
    actor.change_job(0, job) if actor.can_change_job?(job)
  end
  
  def change_subjob(actor_id, job)
    actor = $game_actors[actor_id]
    actor.change_job(1, job) if actor.can_change_job?(job)
  end
  
  def change_second(actor_id, job)
    actor = $game_actors[actor_id]
    actor.change_job(2, job) if actor.can_change_job?(job)
  end
end

#==============================================================================
# ** Window_Skill_Gamma
#------------------------------------------------------------------------------
#  A duplicate of Window_Skill that only shows specific skills.
#==============================================================================

class Window_Skill_Gamma < Window_Selectable
  def initialize(x, y, width, height, actor, ability_menu)
    super(x, y, width, height)
    @actor = actor
    @ability_menu = GAMMA_FFVJOB_SYSTEM::ABILITY_MENUS[ability_menu]
    @column_max = 2
    self.index = 0
    refresh
  end

  def skill
    return @data[self.index]
  end

  def refresh
    @data = []
    for skill in @actor.skills
      @data.push(skill) if @ability_menu.include?($data_skills.index(skill))
      if skill.id == @actor.last_skill_id
        self.index = @data.size - 1
      end
    end
    @item_max = @data.size
    create_contents
    for i in 0...@item_max
      draw_item(i)
    end
  end

  def draw_item(index)
    rect = item_rect(index)
    self.contents.clear_rect(rect)
    skill = @data[index]
    if skill != nil
      rect.width -= 4
      enabled = @actor.skill_can_use?(skill)
      draw_item_name(skill, rect.x, rect.y, enabled)
      self.contents.draw_text(rect, @actor.calc_mp_cost(skill), 2)
    end
  end

  def update_help
    @help_window.set_text(skill == nil ? "" : skill.description)
  end
end


class Hash
  def corresponding_key(value)
    return self.keys[self.values.index(value)]
  end
end