#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# RO Job/Skill System by Blizzard
# Version: 2.01b
# 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
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# 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
#
#
# 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.01
#==============================================================================
# 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 = 50
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 50
when 2 then return 50
when 3 then return 50
when 4 then return 50
when 5 then return 50
when 6 then return 50
when 7 then return 50
when 8 then return 50
when 9 then return 50
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# 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 [[10, 2]]
when 2 then return [[1, 1], [10, 3]]
when 3 then return [[1, 2], [10, 4]]
when 4 then return [[1, 3], [10, 5]]
when 5 then return [[1, 4], [10, 6]]
when 6 then return [[1, 5], [10, 7]]
when 7 then return [[1, 6], [10, 8]]
when 8 then return [[1, 7], [10, 9]]
when 9 then return [[1, 8]]
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# 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 = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.0
m_agi = 1.0
m_int = 1.0
when 2
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.1
m_maxsp = 1.0
m_str = 1.1
m_dex = 1.0
m_agi = 1.0
m_int = 0.9
when 3
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.2
m_maxsp = 1.1
m_str = 1.0
m_dex = 0.9
m_agi = 1.1
m_int = 0.9
when 4
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.2
m_agi = 0.9
m_int = 1.1
when 5
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.0
m_agi = 1.0
m_int = 1.0
when 6
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.0
m_agi = 1.0
m_int = 1.0
when 7
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.0
m_agi = 1.0
m_int = 1.0
when 8
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.0
m_agi = 1.0
m_int = 1.0
when 9
p_maxhp = 0
p_maxsp = 0
p_str = 0
p_dex = 0
p_agi = 0
p_int = 0
m_maxhp = 1.0
m_maxsp = 1.0
m_str = 1.0
m_dex = 1.0
m_agi = 1.0
m_int = 1.0
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# 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 = 'Class Points'
JobLevel = 'Class Level'
JobEXP = 'Class EXP'
EXP = 'EXP'
Next = 'Next'
EmptyEXP = '------'
None = 'None'
Lv = 'Lv'
SkillLevel = 'Skill Level'
MaximumLevel = 'Maximum Level'
Cost = 'Cost'
Power = 'Power'
ClassCommands = ['Select', 'Skills', 'Skill Level Up', 'Exit']
ChangeClass = 'Change Class?'
SkillCommands = ['Learn new Skill', 'Improve Skill', '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) && !@battler.skill_max_level?(skill.id)
skill = skill.clone
skill.sp_cost = (skill.sp_cost *
@actor.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 *
@actor.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 *
actor.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
actor.class_id = id if id != nil
# draw actor data
draw_actor_battler(actor, 200, 128, opacity = 150)
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 actor.maxhp > other.maxhp
self.contents.font.color = BlizzCFG::UP_COLOR
elsif actor.maxhp < other.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, actor.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 actor.maxsp > other.maxsp
self.contents.font.color = BlizzCFG::UP_COLOR
elsif actor.maxsp < other.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, actor.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 v1 > v2
self.contents.font.color = BlizzCFG::UP_COLOR
elsif v1 < v2
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, v1.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_Menu.new(3)
# 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 = Scene_Skill.new
when 2 then $scene = Scene_SkillChange.new
when 3 then $scene = Scene_Menu.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
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_Menu.new(5)
# 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 = Scene_Menu.new(5)
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