this script aint mine,so don't give me credit,all credit goes to legacyblade at
http://forum.chaos-project.com#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Legacy Class Change by Legacyblade
# Version: 1.67
# Type: Class Changing Script
# Date 3-06-2009
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# This work is protected by the following license:
# #----------------------------------------------------------------------------
# #
# # Creative Commons - Attribution-Share Alike 3.0 Unported
# # ( http://creativecommons.org/licenses/by-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).
# #
# #
# # 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.
# #
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
#
# Compatibility:
#
# The script was coded to be 100% compatible with most, if not all scripts. I
# can't think of ANY script that wouldn't be compatible, but I will list those
# that I tested for compatibility.
#
# Blizz ABS is 100% compatible, and all other ABS scripts should be as well, due to how
# the class rank is added.
#
# CCoa's UMS is 100% compatible.
#
# The SDK 2.3 seemed to be compatible. Everything worked fine even with the SDK
# in the project.
#
# I'll keep testing scripts, and adding to this list.
#
# Incompatibility:
#
# No known incompatibility (if you run into an incompatibility, please tell me,
# so I can make a patch)
#
# Known Issues:
#
# none ^_^
#
# Features:
#
# -> Define Special Classes that are unlocked for an actor only by a script
# call (in case the player needs to pay for special training to unlock said
# class).
#
# -> Define how many times an actor must level up while using a certain
# class/classes to unlock another class. (you can make the “Alchemist”
# class require 3 levels as a mage, and 3 levels as a cleric). The system
# is so versatile, that you can even require levels in Special Classes!
#
# -> Define descriptions for each class that will be displayed in the class
# change window. (supports multiple lines of description!)
#
# -> Class Specific Skills. This allows you to set skills as class specific.
# Class specific skills are only availible when an actor is a class that
# the skill is specific to. You can even set a skill specific to multiple
# classes (so the Paladin can use heal if he learned it as a cleric, so the
# Gladiater can use "tackle" if he learned it as a lancer, etc.)
#
# -> Linked Actor system. This allows you to define actors that, when they
# change their class, change the class of actors that are "linked" to them.
#
# -> Class Graphic system. You have the ability to cause both an actor's
# charset AND their battler to change based on their current class.
#
# -> Easily configurable settings that can affect every aspect of the system.
#
# -> Completely lagfree!
#
# -> Compatible with ANY CMS (provided you make a slight modification to
# integrate the class change. This amounts to one line of code)
#
#
# Version History:
#
# For every minor update or bugfix, I will increase the version by .01
# For every new feature, I will increase the version be .1
# For every 10 feature updates, I will update the version by 1
#
# v1.00b:
# -> Legacy Class Change released!
#
# v1.01b:
# -> Fixed a bug in class selection, that would set the actor's class_id to the
# index of the cursor, rather than the actual selected class_id.
#
# v1.02b:
# -> Fixed a few miscellaneous lines of code that could, under certain circumstances, cause errors
#
# v1.10b:
# -> Added the option to change an actor's graphic when the class changes.
#
# v1.11b:
# -> Fixed a bug that kept the class list from scrolling
#
# v.1.20:
# -> Left the beta stage.
# -> Enhanced the level handeling. Now the skills are assigned based on class
# level, rather than the actor's overall level.
#
# v.1.67:
# -> Added the option to make multi-line descriptions! (no more trying to cram
# the description into a single line!
# -> Added the "linked actor" feature.
# -> Added the "special classes" feature.
# -> Added the Class Specific Skills feature.
# -> Recoded the scene slightly to support any party size.
# -> Changed when the Class List updates, for graphical nicety.
# -> Increased compatibility with StormTronics CMS (by Blizzard). Now it only
# takes a small edit to StorTronics to seamlessly integrate the Class Change
# system. (I reworked the code so that there is an "on_cancel" method).
# -> Optimized code
# -> Fixed a slight bug with class descriptions.
# -> Fixed a typo that would cause a player to level up when they're supposed
# to level down.
# -> Rewrote comments, and reordered code for readability.
#
#
# Planned Features:
#
# -> Add the option to display classes that other members of the party have
# learned, but the current actor has not. These locked, yet visible classes
# would also show the required level of each class needed to unlock the class
# rather than a class description. (almost finished, just needs some debugging)
#
# Useless facts:
#
# This was the first time I've ever successfully made a script. I learned a lot
# about everything I worked with, and can't wait to learn more about RGSS and
# programming in general. I hope you enjoy this, because it took a lot of effort
#
# Special Thanks:
#
# - Blizzard for all his help. Without him, I couldn't have made it. Not
# only did he help me fix the errors, he also gave me lectures on various
# aspects of programming. This caused me to make LESS errors, and grow
# in my programming skill. Thanks Blizz, this script wouldn't be here
# today if you hadn't been there in that MIRC room, XD
#
# - GubiD for when blizzard wasn't around in MIRC to answer my questions.
# he helped me with a few errors that I had no idea how to fix (many of
# them were some of the most n00bish errors too -_-). Thanks GubiD
# couldn't have done it without ya!
#
# - Sephirothtds for making TDS Class Change System incompatible with
# the Blizz-ABS. If you'd made it compatible, I would have gone with your
# script, and never figured out how to make one myself . Your script's
# incompatibility with Blizz-ABS sparked my urge to learn to scrip. Thanks.
#
# - Juan, who offered a few pointers.
#
# - To all those who put up with me in the CP chat room when I'm ranting
# about my newest error.
#
# - To all the members of eminweb.com for nagging me enough to do my
# administrative duty, which eventually cured me of my infamous laziness
#
# - StarrodKirby86 for requesting the class graphic system, it made this
# script have a feature not many class changing systems have.
#
# - To the members of Chaos Project who offered feedback, and requested
# features. Without your ideas, this would be a much simpler, more boring
# system.
#
# Author Notes:
# PLEASE, make sure you've configured the script correctly before you report
# whatever error you're running into. IN PARTICULAR, check your class_requirements
# configuration. EVERYONE who's used the script reports an error that comes from
# an improper configuration of class_requirements.
#
# BUT, if you DO (or at least think you do) have correct configuration, and you
# run into a bug, PLEASE report it to me. Also, if you want a feature added,
# request it (preferably in the Legacy Class Change thread on eminweb.com),
# and I'll try to add it.
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# START CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
module LBConf
# If this is set to true, then changing an actor's class will also change its
# graphic.
CLASS_GRAPHIC_CHANGE = true
# Put the ID of classes you want as "Special Classes" in this array(seperate
# entries with a comma). Special Classes will be unselectable unless an actor
# "learns" the class. (this is done by executing the following script call)
#
# $game_actors[actor_id].learn_special_class(class_id)
# or
# $game_party.actors[position].learn_special_class(class_id)
#
# "position" refers to the position an actor is in the party. 0 is the first
# party member (the one you see walking around the map), 1 is the seccond, and
# so on.
SPECIAL_CLASS = []
# If an actor has a class specific skill, they will forget it when they change
# to a class that the skill is not specific to. They will, however, relearn the
# skill when they switch back to a class that the skill IS specific to.
#
# If you want to use class specific skills, you'll need to define which skills
# are specific to a certain class. Use the following format
#
# when X then return[a,b,c...]
#
# where X is a class ID, and a,b,c (and whatever else you put in that array) are
# the IDs of skills you want to be specific to that class (remember to seperate
# them with commas). You can have skills specific to multiple classes (both the
# cleric, and the paladin can use "heal" if they've learned it.)
#
# If you don't want to use the class specific skill system, don't define any class
# specific skills.
def self.class_spells(class_id)
case class_id
end
return []
end
# If you have CLASS_GRAPHIC_CHANGE set to true, you'll need to setup what graphic
# each class will need. use the following format
#
# when class_id then return 'text you want appended'
#
# an example (in this situation) is simpler than an explanation, so here you go
#
# when 1 then return '_fighter'
#
# If the actor's charset is named "arshes" and battler is called "ArshesBattler",
# then when the actor is using class 1 (fighter by default), the charset will be
# named "arshes_fighter" and the battler will be named "ArshesBattler_fighter".
# if you don't want a class to have it's own graphic (or haven't made one yet),
# just don't define it below.
def self.class_graphic(class_id)
case class_id
end
return ''
end
# This next section is where you define the description for each class.
# use the following template for each class
#
# when class_id then return ['line1','line2','line3]
#
# Although you won't get an error if you have more than three lines of
# description, the window is only big enough to fit three lines. Also, if you
# can't think up a description for a class, don't define one, and the script
# will assign it the default class description. (a blank line by default)
#
# To change the default description (for whatever reason) look for return ['']
# near the bottom of this section.
def self.class_descriptions(class_id)
case class_id
end
# if you want a default class description for those not defined, replace the
# below array with a description like those above.
return ['']
end
# This is where you set the requirement for each class. Use the following format
#
# when class_id then return [0,class1's required level,class2's required level,...]
#
# where class_id is the ID of the class that you want to have a requirement,
# 0 is a dummy entry, and"class1's required level, etc. are how many levels needed
# in that class to unlock the class
#
# REMEMBER TO SET THIS UP FOR YOUR OWN PROJECT! IF YOU HAVE MORE ENTRIES IN THE
# ARRAY THAN CLASSES IN THE DATABASE (and the dummy 0 at the beginning, of course)\
# YOU WILL GET AN ERROR!
def self.class_requirements(class_id)
case class_id
#to make a class have no requirements (unlocked by default), just don't
#define requirements for it.
end
return [0]
end
# here is where you set up which actors are "linked". When an actor is "linked"
# to another actor, whenever the actor changes their class, the other's class
# will change to match it. Set it up in the following format.
#
# when X then return[a,b,c...]
#
# where X is the ID of the actor in question, and "a,b,c..." are the ID's
# of the actors linked to this actor, and are separated by commas. With this setup
# when actor X changes his class, it will also change actor a, b, and c's class.
# To make it so actor a changes the classes of the other actors, you'll have to
# set the link up for each actor involved. (if you want Arshes to be "linked" to
# his dark form, you'd do this.
#
# when 1 then return[2]
# when 2 then return[1]
#
# where 1 is the ID of Arshes, and 2 is the ID of Arshes' dark form.
def self.linked_actors(actor_id)
case actor_id
#when 1 then return[2]
#when 2 then return[1]
#uncomment the above lines to link Arshes and Basil
end
return []
end
end
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# END CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
class Game_Actor < Game_Battler
attr_accessor :class_levels
attr_accessor :unlocked_class
attr_accessor :unlocked_specials
attr_accessor :learned_class_skills
attr_accessor :character_name
attr_accessor :default_charset_name
attr_accessor :battler_name
attr_accessor :default_battler_name
# modify the actor setup for Legacy Class Change
alias class_rank_level_LB setup
def setup(actor_id)
class_rank_level_LB(actor_id)
# set up the initial default graphics (used by the graphic change system)
@default_charset_name = @character_name
@default_battler_name = @battler_name
# set up the class arrays used by the class changing system.
@unlocked_class = []
@unlocked_specials = []
# initialize the array that holds the class specific skills an actor has learned
@learned_class_skills = []
# set up the class_levels
@class_levels = Array.new($data_classes.size)
@class_levels.each_index {|i|
if i == $data_actors[actor_id].class_id
@class_levels[i] = 1
else
@class_levels[i] = 0
end}
# initialize unlocked classes.
(1...$data_classes.size).each{|class_id|
unlock_class(class_id)}
end
# method used to check if an actor meets the requirements for a class, and if he
# does, it will unlock the class for that actor
def unlock_class(class_id)
if !@unlocked_class.include?(class_id)
if !LBConf::SPECIAL_CLASS.include?(class_id)
requirement = LBConf.class_requirements(class_id)
result = true
requirement.each_index {|i|
if @class_levels[i] < requirement[i]
result = false
break
end}
else
result = false
if unlocked_specials.include?(class_id)
result = true
end
end
if result
@unlocked_class.push(class_id)
@unlocked_class.sort!
end
end
end
# method used to unlock a special class for an actor.
def learn_special_class(class_id)
if !@unlocked_specials.include?(class_id)
@unlocked_specials.push(class_id)
@unlocked_specials.sort!
end
end
# method used to lock a special class for an actor.
def forget_special_class(class_id)
@unlocked_specials.delete(class_id)
@unlocked_class.delete(class_id)
@unlocked_specials.sort!
@unlocked_class.sort!
end
# modifies how levelups are assigned, so as to add to a class' level upon level
# up.
def exp=(exp)
@exp = [[exp, 9999999].min, 0].max
# Level up
while @exp >= @exp_list[@level+1] && @exp_list[@level+1] > 0
@level += 1
@class_levels[class_id] += 1
# modifies how skills are assigned, so that it's based on class level, rather
# than overall level.
$data_classes[@class_id].learnings.each {|j|
if j.level == @class_levels[@class_id]
learn_skill(j.skill_id)
if LBConf.class_spells(@class_id).include?(j.skill_id)
@learned_class_skills.push(j.skill_id)
@learned_class_skills.sort!
end
end
}
end
# Level down
while @exp < @exp_list[@level]
@level -= 1
end
# Correction if exceeding current max HP and max SP
@hp = [@hp, self.maxhp].min
@sp = [@sp, self.maxsp].min
end
end
#==============================================================================
# ** Class_Change_Scene
#------------------------------------------------------------------------------
# Here's where the actual Class Changing Scene code starts!
# Without this, you would just have some useless additions to the default
# system!!! That wouldn't be much of a script, would it?
#==============================================================================
class Class_Change_Scene
def initialize
# update the unlocked_level array for each actor
$game_party.actors.each{|actor|
(1...$data_classes.size).each{|class_id|
actor.unlock_class(class_id)}}
#create the windows
@actor_list = Window_Actor_List.new
@class_list = Window_Class_List.new
@class_description = Window_Class_Description.new
#set window focus to the actor list
@actor_list.last_index = 0
@actor_list.index = 0
@actor_list.active = true
@last_class = 0
end
def main
#enter the scene's loop
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
# dispose of the windows created in the scene
Graphics.freeze
@actor_list.dispose
@class_list.dispose
@class_description.dispose
end
def update
@actor_list.update
@class_list.update
@class_description.update
# if focus is on the actor list, run the actor list's update method
if @actor_list.active
update_actor_list
return
end
# if focus is on the class list, run the actor list's update method
if @class_list.active
update_class_list
return
end
end
# This is the update method that will run when the actor list is the active window
def update_actor_list
# When the player moves the cursor over a new actor in the party, change the
# text in the class list to whatever classes the highlighted actor has
# unlocked.
if @actor_list.index != @actor_list.last_index
@class_list.class_list = $game_party.actors[@actor_list.index].unlocked_class
@class_list.actor = $game_party.actors[@actor_list.index].id
@class_list.refresh
@actor_list.last_index = @actor_list.index
end
# When the user presses the Cancel button, exit the entire menu
if Input.trigger?(Input::B)
on_cancel
end
# When the user presses the action button, activate the class list!
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
#switch window focus to the class list
@actor_list.active = false
@class_list.index = 0
@class_list.active = true
#set the current class description, and draw the class description.
@class_list.actor = $game_party.actors[@actor_list.index].id
@class_description.actor = $game_party.actors[@actor_list.index].id
@class_description.current_class = (@class_list.index + 1)
@class_description.refresh
return
end
end
# This is the update method that will run when the class list is the active window
def update_class_list
# When the player moves the cursor over a new class in the list, change the
# text in the description window to the description of whatever class is
# highlighted.
if @class_list.current_class != @last_class
@last_class = @class_list.current_class
@class_description.current_class = (@class_list.current_class)
@class_description.refresh
end
# When the user presses the Cancel button, return focus to the actor list
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@class_description.current_class = 0
@class_description.refresh
@class_list.index = 0
@class_list.index = -1
@class_list.active = false
@actor_list.active = true
return
end
# When the user presses the action button, change the actor's class and
# and graphic, then return focus to the actor list.
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
#change the actor's class
actor_class_change(@class_list.actor, @class_list.current_class)
#refresh, and return focus to the actor list
@class_description.current_class = 0
@class_description.refresh
@actor_list.refresh
@class_list.index = -1
@class_list.active = false
@actor_list.active = true
return
end
end
#--------------------------------------------------------------------------
# * Change graphic
# method used to change the actor's graphics due to a class change.
#--------------------------------------------------------------------------
def actor_graphics_change(actor_id)
#change the actor's charset
$game_actors[actor_id].character_name = ($game_actors[actor_id].default_charset_name +
LBConf.class_graphic($game_actors[actor_id].class_id))
#change the actor's battler
$game_actors[actor_id].battler_name = ($game_actors[actor_id].default_battler_name +
LBConf.class_graphic($game_actors[actor_id].class_id))
end
#--------------------------------------------------------------------------
# * Change class
# method used to change the actor's class, and the class of those linked
# to the actor.
#--------------------------------------------------------------------------
def actor_class_change(actor_id, class_id)
#setup which actors' class needs to be changed.
changed_actors = LBConf.linked_actors(actor_id)
changed_actors.push actor_id
#memorize which class specific skills the actor has learned for the current
#class, then make the actor forget them
LBConf.class_spells($game_actors[actor_id].class_id).each{|skill_id|
$game_actors[actor_id].forget_skill(skill_id)}
#change the actor(s) class.
changed_actors.each{|actorz|
$game_actors[actorz].class_id = class_id
#remember any class specific spells the actor has forgotten forthe class
#they're changing to.
$game_actors[actorz].learned_class_skills.each{|skill_id|
if LBConf.class_spells($game_actors[actorz].class_id).include?(skill_id)
$game_actors[actorz].learn_skill(skill_id)
end}
#if graphic changing is enabled, change the actor's graphic.
if LBConf::CLASS_GRAPHIC_CHANGE == true
actor_graphics_change(actorz)
end}
end
# this is the method that is called to exit the menu. I did it this way for
# improved compatibility with StormTronics CMS (by Blizzard)
def on_cancel
$game_system.se_play($data_system.cancel_se)
$game_player.refresh
$scene = Scene_Map.new
return
end
end
class Window_Actor_List < Window_Selectable
attr_accessor :last_index
def initialize
super(160, 0, 480, 352)
self.contents = Bitmap.new(width - 32, height - 32)
refresh
self.active = false
@last_index = -1
self.index = -1
end
def top_row
# Divide y-coordinate of window contents transfer origin by 1 row
# height of 80
return self.oy / 80
end
def top_row=(row)
# Multiply 1 corrected row height by 80 for y-coordinate of window contents
# transfer origin
self.oy = [[row, 0].max, row_max - 1].min * 80
end
def page_row_max
# Subtract a frame height of 32 from the window height, and divide it by
# 1 row height of 80
return (self.height - 32) / 80
end
def refresh
self.contents.clear
@item_max = $game_party.actors.size
for i in 0...$game_party.actors.size
x = 64
y = i * 80
actor = $game_party.actors[i]
draw_actor_graphic(actor, x - 40, y + 55)
draw_actor_name(actor, x, y)
draw_actor_level(actor, x + 144, y)
self.contents.draw_text(x, y + 32, width - 32, 32, ($data_classes[$game_party.actors[i].class_id].name + ' rank: ' + $game_party.actors[i].class_levels[$game_party.actors[i].class_id].to_s))
end
end
def update_cursor_rect
# If cursor position is less than 0
if @index < 0
self.cursor_rect.empty
return
end
# Get current row
row = @index / @column_max
# If current row is before top row
if row < self.top_row
# Scroll so that current row becomes top row
self.top_row = row
end
# If current row is more to back than back row
if row > self.top_row + (self.page_row_max - 1)
# Scroll so that current row becomes back row
self.top_row = row - (self.page_row_max - 1)
end
# Calculate cursor width
cursor_width = self.width / @column_max - 32
# Calculate cursor coordinates
x = @index % @column_max * (cursor_width + 32)
y = @index / @column_max * 80 - self.oy
# Update cursor rectangle
self.cursor_rect.set(x, y, cursor_width, 80)
end
end
class Window_Class_List < Window_Selectable
attr_accessor :actor
attr_accessor :class_list
attr_accessor :item_max
attr_reader :current_class
def initialize
super(0, 0, 160, 352)
@actor = 1
@class_list = $game_actors[@actor].unlocked_class
@item_max = @class_list.length
self.contents = Bitmap.new(width - 32, @item_max * 32)
refresh
@index = -1
@active = false
@current_class = 1
end
def refresh
self.contents.clear
@item_max = @class_list.size
self.contents = Bitmap.new(width - 32, @item_max * 32)
i = 0
@class_list.each{|class_id|
self.contents.draw_text(10, i, width - 32, 32, $data_classes[class_id].name)
i += 32 }
end
alias update_cursor_LB update_cursor_rect
def update_cursor_rect
update_cursor_LB
if @index >= 0
@current_class = @class_list[@index]
end
end
end
class Window_Class_Description < Window_Base
attr_accessor :current_class
attr_accessor :actor
def initialize
super(0, 352, 640, 128)
@current_class = 0
@actor = 0
self.contents = Bitmap.new(width - 32, height - 32)
end
def refresh
self.contents.clear
draw_description(@current_class)
end
def draw_description(class_id)
offset = 0
description = LBConf.class_descriptions(class_id)
description.each_index{|class_descrip|
self.contents.draw_text(0, (0 + offset *32), width - 32, 32, description[class_descrip])
offset = offset + 1}
end
end