#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= # RO Job/Skill System by Blizzard # Version: 2.3 # Type: Ragnarok Online Job/Skill System Clone # Date: 5.11.2007 # Date 1.0b: 4.1.2008 # Date 1.01b: 4.1.2008 # Date 1.2b: 26.1.2008 # Date 1.3b: 2.6.2008 # Date 1.4b: 8.6.2008 # Date 1.5b: 6.8.2008 # Date 1.6b: 23.11.2009 # Date 2.0b: 17.2.2010 # Date 2.01b: 4.9.2010 # Date 2.1b: 22.1.2011 # Date 2.2b: 22.6.2012 # Date 2.3: 23.3.2019 #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= # # This work is licensed under BSD License 2.0: # # #---------------------------------------------------------------------------- # # # # Copyright (c) Boris "Blizzard" Mikić # # All rights reserved. # # # # Redistribution and use in source and binary forms, with or without # # modification, are permitted provided that the following conditions are met: # # # # 1. Redistributions of source code must retain the above copyright notice, # # this list of conditions and the following disclaimer. # # # # 2. Redistributions in binary form must reproduce the above copyright # # notice, this list of conditions and the following disclaimer in the # # documentation and/or other materials provided with the distribution. # # # # 3. Neither the name of the copyright holder nor the names of its # # contributors may be used to endorse or promote products derived from # # this software without specific prior written permission. # # # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # # POSSIBILITY OF SUCH DAMAGE. # # # #---------------------------------------------------------------------------- # # You may use this script for both non-commercial and commercial products # without limitations as long as you fulfill the conditions presented by the # above license. The "complete" way to give credit is to include the license # somewhere in your product (e.g. in the credits screen), but a "simple" way # is also acceptable. The "simple" way to give credit is as follows: # # RO Job/Skill System licensed under BSD License 2.0 # Copyright (c) Boris "Blizzard" Mikić # # Alternatively, if your font doesn't support diacritic characters, you may # use this variant: # # RO Job/Skill System licensed under BSD License 2.0 # Copyright (c) Boris "Blizzard" Mikic # # In general other similar variants are allowed as long as it is clear who # the creator is (e.g. "RO Job/Skill System created by Blizzard" is # acceptable). But if possible, prefer to use one of the two variants listed # above. # # If you fail to give credit and/or claim that this work was created by you, # this may result in legal action and/or payment of damages even though this # work is free of charge to use normally. # #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:= # # Special Thanks for requesting this goes to Nightfox! # # # new in 1.0b: # - fixed font problem # - now beta # # new in 1.01b: # - fixed a crash problem where enemies would be tested on skill levels # # new in 1.2b: # - actors can now learn Chaos Drive transformation skills through this # system (REQUIRES CRLS 5.0 OR HIGHER) # - classes/jobs now can have stat modifiers # # new in 1.3b: # - skills can now have other skills as requirements # # new in 1.4b: # - added option to hide skills that haven't met the prerequisites yet # - improved coding and the way data display is being refreshed # # new in 1.5b: # - fixed bug with forgetting skills # - added option to forget all skills from other classes when changing the # class # # new in 1.6b: # - now more compatible with Blizz-ABS 2.57 # # new in 2.0b: # - fixed bug where HP/SP wouldn't apply when the max HP/SP were decreased # - fixed bug with skill usage when JOB_ONLY was not active # - now more compatible with Blizz-ABS 2.7 # - improved coding # # new in 2.01b: # - fixed bug when activating JOB_ONLY # # new in 2.1b: # - fixed a few small problems with Blizz-ABS # # new in 2.2b: # - fixed a the bug where during actor parameter testing the class of the # dummy actor would change and unequip equipment # - fixed crash bug that could occur when trying to change the class again # # new in v2.3: # - added new license # - added usage and crediting instructions # # # 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.3 #============================================================================== # module BlizzCFG #------------------------------------------------------------------------------ # This module serves for configuration in my scripts and for consistency. #============================================================================== module BlizzCFG #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START Configuration #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: INIT_JP = 1 LVL1_POWER = 50 LVL1_COST = 200 LVLUP_RATE = 20 EXP_RATIO = 20 RESET_LVLS = false JOB_ONLY = false USE_LEVEL = false USE_ALL = false CLASS_SKILLS = !false HIDE_SKILLS = false RO_RIGHT = false EVASION = 'EVA' UP_COLOR = Color.new(0, 255, 0) # (R, G, B) DOWN_COLOR = Color.new(255, 0, 0) # (R, G, B) CD_SKILLS = [61] #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END Configuration #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def self.roskill_maxlevel(id) case id #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START RO Skill Database # # You can define the max level of each skill here. Use following template to # set up your configuration: # # when ID then return NUMBER # # ID - the skill ID # NUMBER - the maximum level # # Note that using values lower than 1 WILL CAUSE BUGS! Default value is 1 and # skills that are not defined here will have the default value automatically # applied. #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: when 57 then return 5 #when 61 then return 3 when 62 then return 5 when 63 then return 10 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END RO Skill Database #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: end return 1 end def self.roskill_reqs(id) case id #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START RO Skill Requirement Database # # You have the option to make skills require not only a specific level, but # other skills and their levels as well. Such a skill will not appear in the # list of skills until all requirements are met. # Use following template to set up your configuration: # # when ID then return [[SKILL_ID1, MIN_LEVEL1], [SKILL_ID2, MIN_LEVEL2], ...] # # ID - the skill ID # SKILL_ID - ID of the required skill # MIN_LEVEL - minimum required level of the required skill # # You can add as many requirements as you want, separate them with commas. #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: when 2 then return [[1, 2]] when 62 then return [[61, 1], [63, 4]] when 3 then return [[1, 3], [2, 2]] #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END RO Skill Requirement Database #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: end return [] end def self.rojob_maxlevel(id) case id #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START RO Job Database # # You can define the max level of each job here. Use following template to # set up your configuration: # # when ID then return NUMBER # # ID - the class ID # NUMBER - the maximum level # # Note that using values lower than 1 WILL CAUSE BUGS! Default value is 1 and # jobs that are not defined here will have the default value automatically # applied. #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: when 1 then return 10 when 2 then return 30 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END RO Job Database #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: end return 1 end def self.rojob_next(id) case id #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START RO Job-Connection Database # # Here you can define job change trees. When you have one job active you can # change to any other job that is defined here. It is possible to define # recursive trees where a class can be changed back as well without problems. # Use following template to set up your configuration: # # when ID then return [[MIN_LEVEL1, NEW_ID1], [MIN_LEVEL2, NEW_ID2], ...] # # ID - the current class ID # MIN_LEVEL - minimum level required to be allowed to change # NEW_ID - the ID of the new class # # You can add as many next classes as you want, separate them with commas. #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: when 1 then return [[1, 2], [15, 3]] when 2 then return [[10, 1], [15, 3], [1, 4], [1, 5], [1, 6]] when 3 then return [[1, 2], [6, 7]] when 4 then return [[1, 2]] when 5 then return [[1, 2], [8, 6], [10, 8]] when 6 then return [[1, 2], [11, 3]] when 7 then return [[1, 2], [5, 1], [5, 4]] when 8 then return [[1, 2], [5, 7]] #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END RO Job-Connection Database #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: end return [[]] end def self.job_stat_mod(id) p_maxhp = p_maxsp = p_str = p_dex = p_agi = p_int = 0 m_maxhp = m_maxsp = m_str = m_dex = m_agi = m_int = 1.0 case id #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # START Job Stat Modifier Database # # You are able to set up modifiers for actor stats that change depending on # the current job. Use following template to set up your configuration: # # when ID # p_maxhp = PLUS # p_maxsp = PLUS # p_str = PLUS # p_dex = PLUS # p_agi = PLUS # p_int = PLUS # m_maxhp = MULTI # m_maxsp = MULTI # m_str = MULTI # m_dex = MULTI # m_agi = MULTI # m_int = MULTI # # ID - the current class ID # PLUS - an integer value (default is 0) # MULTI - a decimal value (default is 1.0) # # The values that have p_ before that name are static modifiers. For example, # if you use 100, then the given stat will increase by 100 if the actor has # the given class. If you use -200, then it will decrease by 200 from the # actor's basis. # The values that have m_ before that name are dynamic modifiers. For # example, if you use 1.1, then the given stat will increase by 10% if the # actor has the given class. If you use 0.8, then it will decrease by 20% # from the actor's basis. # # Note: # # It might be a good idea to create a neutral class if you are using this # feature. If you don't set up a class here, then the default values will be # applied. Keep in mind that first all static modifiers will be applied and # afterwards the dynamic modifiers. #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: when 1 p_maxhp = 100 p_maxsp = -20 p_str = 20 p_dex = 10 p_agi = 10 p_int = -20 m_maxhp = 1.1 m_maxsp = 0.9 m_str = 1.1 m_dex = 1.1 m_agi = 1.0 m_int = 0.8 when 2 p_maxhp = -200 p_maxsp = 50 p_str = -20 p_dex = 0 p_agi = 0 p_int = 30 m_maxhp = 0.9 m_maxsp = 1.1 m_str = 0.7 m_dex = 0.9 m_agi = 1.1 m_int = 1.2 #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # END RO Job Stat Modifier Database #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: end return [p_maxhp, m_maxhp, p_maxsp, m_maxsp, p_str, m_str, p_dex, m_dex, p_agi, m_agi, p_int, m_int] end # constants YesNo = ['Yes', 'No'] AreYouSure = 'Are you sure?' Current = 'Current' JobPoints = 'Job Points' JobLevel = 'Job Level' JobEXP = 'Job EXP' EXP = 'EXP' Next = 'next' EmptyEXP = '------' None = 'None' Lv = 'Lv' SkillLevel = 'Skill Level' MaximumLevel = 'Maximum Level' Cost = 'Cost' Power = 'Power' ClassCommands = ['Select', 'Next', 'Previous', 'Exit'] ChangeClass = 'Change Class?' SkillCommands = ['Learn new Skill', 'Improve Skill', 'Next', 'Previous', 'Exit'] LearnSkill = 'Learn Skill?' ImproveSkill = 'Improve Skill?' end #============================================================================== # Game_Actor #------------------------------------------------------------------------------ # This class was enhanced with various additional variables to make this # system work properly. Also a number of methods were added to handle the new # data. #============================================================================== class Game_Actor # setting all accessible variables attr_accessor :jp #---------------------------------------------------------------------------- # override setup # Adds some hashes for additional data. #---------------------------------------------------------------------------- alias setup_skilllevels_later setup def setup(id) @skill_level, @job_level, @job_exp, @jp = {}, {}, {}, BlizzCFG::INIT_JP setup_skilllevels_later(id) @skills = [] unless BlizzCFG::JOB_ONLY end #---------------------------------------------------------------------------- # job_level # id - class ID # Safe return of any job level, current job level is default. #---------------------------------------------------------------------------- def job_level(id = @class_id) return (@job_level[id] == nil ? 1 : @job_level[id]) end #---------------------------------------------------------------------------- # job_exp # id - class ID # Safe return of any job exp, current job exp are default. #---------------------------------------------------------------------------- def job_exp(id = @class_id) return (@job_exp[id] == nil ? 0 : @job_exp[id]) end #---------------------------------------------------------------------------- # job_level_change # val - new level value # id - class ID # flag - determines whether EXP should be updated or not # This method processes change of a job level. #---------------------------------------------------------------------------- def job_level_change(val, id = @class_id, flag = true) # get level new_level = BlizzCFG.rojob_maxlevel(id) # limit level value if new_level > val new_level = val elsif new_level < 1 new_level = 1 end # get Job Points jp = new_level - self.job_level(id) # increase Job Points @jp += jp if jp > 0 # set new Job level @job_level[id] = new_level # set Job EXP if the setting flag is active @job_exp[id] = BlizzCFG::LVLUP_RATE * new_level * (new_level - 1) if flag end #---------------------------------------------------------------------------- # override exp= # val - new exp value # This method was modified to add job EXP each time real EXP are added. #---------------------------------------------------------------------------- alias exp_is_rosys_later exp= def exp=(val) # store old EXP and skills old_exp, skills = @exp, @skills.clone exp_is_rosys_later(val) # no skills can be learned, remove any learned skills @skills = skills # increase Job EXP exp = @exp - old_exp add_job_exp(exp * BlizzCFG::EXP_RATIO / 100) if exp > 0 end #---------------------------------------------------------------------------- # add_job_exp # val - new exp value # id - class ID # This method executes job exp increasing. #---------------------------------------------------------------------------- def add_job_exp(val, id = @class_id) max_level = BlizzCFG.rojob_maxlevel(id) # set new Job EXP exp1 = self.job_exp(id) + val exp2 = BlizzCFG::LVLUP_RATE * max_level * (max_level - 1) @job_exp[id] = (exp1 < exp2 ? exp1 : exp) # as long as Job level can be increased while self.job_level(id) < max_level && self.job_exp(id) >= BlizzCFG::LVLUP_RATE * self.job_level(id) * (self.job_level(id) + 1) # increase Job level job_level_change(self.job_level(id) + 1, id, false) end end #---------------------------------------------------------------------------- # job_max_level? # Checks if the Job's level is at the maximum. #---------------------------------------------------------------------------- def job_max_level? return (self.job_level >= BlizzCFG.rojob_maxlevel(@class_id)) end #---------------------------------------------------------------------------- # override base_maxhp # This method was changed to allow class stat modifiers. #---------------------------------------------------------------------------- alias base_maxhp_rosys_later base_maxhp def base_maxhp result, mods = base_maxhp_rosys_later, BlizzCFG.job_stat_mod(@class_id) return ((result + mods[0]) * mods[1]).to_i end #---------------------------------------------------------------------------- # override base_maxsp # This method was changed to allow class stat modifiers. #---------------------------------------------------------------------------- alias base_maxsp_rosys_later base_maxsp def base_maxsp result, mods = base_maxsp_rosys_later, BlizzCFG.job_stat_mod(@class_id) return ((result + mods[2]) * mods[3]).to_i end #---------------------------------------------------------------------------- # override base_str # This method was changed to allow class stat modifiers. #---------------------------------------------------------------------------- alias base_str_rosys_later base_str def base_str result, mods = base_str_rosys_later, BlizzCFG.job_stat_mod(@class_id) return ((result + mods[4]) * mods[5]).to_i end #---------------------------------------------------------------------------- # override base_dex # This method was changed to allow class stat modifiers. #---------------------------------------------------------------------------- alias base_dex_rosys_later base_dex def base_dex result, mods = base_dex_rosys_later, BlizzCFG.job_stat_mod(@class_id) return ((result + mods[6]) * mods[7]).to_i end #---------------------------------------------------------------------------- # override base_agi # This method was changed to allow class stat modifiers. #---------------------------------------------------------------------------- alias base_agi_rosys_later base_agi def base_agi result, mods = base_agi_rosys_later, BlizzCFG.job_stat_mod(@class_id) return ((result + mods[8]) * mods[9]).to_i end #---------------------------------------------------------------------------- # override base_int # This method was changed to allow class stat modifiers. #---------------------------------------------------------------------------- alias base_int_rosys_later base_int def base_int result, mods = base_int_rosys_later, BlizzCFG.job_stat_mod(@class_id) return ((result + mods[10]) * mods[11]).to_i end #---------------------------------------------------------------------------- # get_skill_sp_cost_factor # skill_id - skill ID # Returns the SP cost factor of the skill for this actor. #---------------------------------------------------------------------------- def get_skill_sp_cost_factor(skill_id) return 1 if skill_max_level?(skill_id) return ((BlizzCFG::LVL1_COST - (self.skill_level(skill_id) - 1) * (BlizzCFG::LVL1_COST - 100.0) / (BlizzCFG.roskill_maxlevel(skill_id) - 1)) / 100) end #---------------------------------------------------------------------------- # get_skill_damage_factor # skill_id - skill ID # Returns the damage factor of the skill for this actor. #---------------------------------------------------------------------------- def get_skill_damage_factor(skill_id) return 1 if skill_max_level?(skill_id) return (BlizzCFG::LVL1_POWER + (self.skill_level(skill_id) - 1) * (100.0 - BlizzCFG::LVL1_POWER) / (BlizzCFG.roskill_maxlevel(skill_id) - 1)) / 100 end #---------------------------------------------------------------------------- # skill_max_level? # skill_id - skill ID # Checks if a skill has reached the max level. #---------------------------------------------------------------------------- def skill_max_level?(skill_id) return (self.skill_level(skill_id) >= BlizzCFG.roskill_maxlevel(skill_id)) end # if the JOB_ONLY option is not being used, a couple of methods are being # parsed for skill level handling unless BlizzCFG::JOB_ONLY #---------------------------------------------------------------------------- # skill_level # id - skill ID # Safe return of a skill level for this actor. #---------------------------------------------------------------------------- def skill_level(id) return (@skill_level[id] == nil ? 1 : @skill_level[id]) end #---------------------------------------------------------------------------- # skill_level_change # val - new level value # id - skill ID # This method processes change of a skill level. #---------------------------------------------------------------------------- def skill_level_change(val, id) max_level = BlizzCFG.roskill_maxlevel(id) if val > max_level @skill_level[id] = max_level elsif max_level < 1 @skill_level[id] = 1 else @skill_level[id] = val end end #---------------------------------------------------------------------------- # override forget_skill # id - skill ID # This method additionally resets a level when a skill gets removed. #---------------------------------------------------------------------------- alias forget_skill_rosys_later forget_skill def forget_skill(id) learned = @skills.include?(id) forget_skill_rosys_later(id) # reset skill level of forgotten skill if that option is active @skill_level[id] = 1 if BlizzCFG::RESET_LVLS && learned && !@skills.include?(id) end #---------------------------------------------------------------------------- # override skill_can_use? # skill_id - skill ID # This method additionally takes into account the increased SP cost. #---------------------------------------------------------------------------- alias skill_can_use_rosys_later? skill_can_use? def skill_can_use?(skill_id) skill = $data_skills[skill_id] # if not enough SP considering skill level SP cost modification if self.sp < (skill.sp_cost * get_skill_sp_cost_factor(skill.id)).to_i # skill cannot be used return false end return skill_can_use_rosys_later?(skill_id) end end end #============================================================================== # Game_Battler #------------------------------------------------------------------------------ # This class was modified to support skill levels. #============================================================================== unless BlizzCFG::JOB_ONLY class Game_Battler #---------------------------------------------------------------------------- # override skill_effect # user - the skill performer # skill - the skill # This method was modified to support changed damage handling. #---------------------------------------------------------------------------- alias skill_effect_rosys_later skill_effect def skill_effect(user, skill) # stores old values and executes skill last_hp = self.hp last_sr = self.sr if $crls && self.is_a?(Game_Actor) result = skill_effect_rosys_later(user, skill) # if skill was a success and effect needs to be modified if result && self.damage.is_a?(Numeric) && user.is_a?(Game_Actor) && !user.skill_max_level?(skill.id) # restore values self.hp = last_hp self.sr = last_sr if $crls && self.is_a?(Game_Actor) # modifiy damage considering skill level self.damage = (self.damage * user.get_skill_damage_factor(skill.id)).to_i # apply skill effect on HP self.hp -= self.damage end return result end end #============================================================================== # Window_Skill #------------------------------------------------------------------------------ # This class was modified to display correct SP consumption if skill levels # are being used. #============================================================================== class Window_Skill < Window_Selectable #-------------------------------------------------------------------------- # override draw_item # i - index # This method was modified to print the correct SP cost. #-------------------------------------------------------------------------- alias draw_item_rosys_later draw_item def draw_item(i) draw_item_rosys_later(i) skill = @data[i] # decide color depending on the fact if currently usable if @actor.skill_can_use?(skill.id) self.contents.font.color = normal_color else self.contents.font.color = disabled_color end # remove old SP display self.contents.fill_rect(236 + i % 2 * 320, i / 2 * 32, 48, 32, Color.new(0, 0, 0, 0)) # calculate SP cost considering skill level sp_cost = (skill.sp_cost * @actor.get_skill_sp_cost_factor(skill.id)).to_i # draw SP cost self.contents.draw_text(236 + i % 2 * 320, i / 2 * 32, 48, 32, sp_cost.to_s, 2) end end #============================================================================== # Map_Battler #------------------------------------------------------------------------------ # This is a Blizz-ABS class. #============================================================================== # if Blizz-ABS is being used if $BlizzABS && BlizzABS::VERSION >= 2.7 class Map_Battler #---------------------------------------------------------------------------- # override skill_consumption # Corrects SP consumption in Blizz-ABS. #---------------------------------------------------------------------------- alias skill_consumption_rosys_later skill_consumption def skill_consumption(skill) if self.is_a?(Map_Actor) && self.valid? && !@battler.skill_max_level?(skill.id) skill = skill.clone skill.sp_cost = (skill.sp_cost * @battler.get_skill_sp_cost_factor(skill.id)).to_i if $tons_version != nil && $tons_version >= 7.4 && $game_system.HP_SKILL skill.hp_cost = (skill.hp_cost * @battler.get_skill_sp_cost_factor(skill.id)).to_i end end skill_consumption_rosys_later(skill) end end #============================================================================== # Hud #------------------------------------------------------------------------------ # This is a Blizz-ABS class. #============================================================================== class Hud < Sprite def get_skills_left # stop if skill is not hot skill or does not exist return -2 if @skill == nil || @skill == 0 # infinite usages if SP cost is zero return -1 if $data_skills[@skill].sp_cost == 0 # get SP cost sp_cost = ($data_skills[@skill].sp_cost * actor.get_skill_sp_cost_factor(@skill)).to_i # if using SP Cost Mod Status if $tons_version != nil && $tons_version >= 6.54 && $game_system.SP_COST_MOD # get modified cost sp_cost = BlizzCFG.get_cost_mod(actor.states, sp_cost) end # infinite usages if SP cost is zero return -1 if sp_cost == 0 # calculate skills left to use return (@sp / sp_cost) end end end #============================================================================== # Scene_Battle #------------------------------------------------------------------------------ # This class was modified to support correct SP consumption if skill levels # are being used. #============================================================================== class Scene_Battle #---------------------------------------------------------------------------- # override use_skill # skill - the skill to be used # Corrects SP consumption in DBS and RTAB. #---------------------------------------------------------------------------- alias make_skill_action_result_rosys_later make_skill_action_result def make_skill_action_result(battler = nil) # if RTAB is being used if battler != nil # store old SP and make result old_sp = battler.sp make_skill_action_result_rosys_later(battler) else # store old SP and make result old_sp, battler = @active_battler.sp, @active_battler make_skill_action_result_rosys_later end # if skill was really used and SP consumption needs to be modified if battler.is_a?(Game_Actor) && @phase4_step != 1 && battler.sp != @skill.sp_cost && !battler.skill_max_level?(@skill.id) # change SP considering skill level battler.sp = old_sp - (@skill.sp_cost * battler.get_skill_sp_cost_factor(@skill.id)).to_i @status_window.refresh end end end end #============================================================================== # Window_Base #------------------------------------------------------------------------------ # This class was enhanced with a few drawing utility mehods. #============================================================================== class Window_Base < Window #---------------------------------------------------------------------------- # draw_actor_battler # actor - the actor # x - x coordinate # y - y coordinate # Draws the actor's battler graphic in a window. #---------------------------------------------------------------------------- def draw_actor_battler(actor, x, y) # get bitmap and dimentions bitmap = RPG::Cache.battler(actor.battler_name, actor.battler_hue) cw, ch = bitmap.width, bitmap.height src_rect = Rect.new(0, 0, cw, ch) # transfer bitmap on window self.contents.blt(x - cw / 2, y - ch / 2, bitmap, src_rect) end #---------------------------------------------------------------------------- # draw_actor_job # actor - the actor # x - x coordinate # y - y coordinate # width - max width # Draws the actor's job data. #---------------------------------------------------------------------------- def draw_actor_job(actor, x, y, width) self.contents.font.color = system_color # draw all static system words self.contents.draw_text(x, y, width, 32, BlizzCFG::Current + ':') self.contents.draw_text(x, y + 32, width, 32, BlizzCFG::JobPoints + ':') self.contents.draw_text(x, y + 64, width, 32, BlizzCFG::JobLevel + ':') self.contents.draw_text(x, y + 96, width, 32, BlizzCFG::JobEXP + ':') self.contents.draw_text(x, y + 128, width, 32, BlizzCFG::Next + ':') self.contents.font.color = normal_color # draw all the data self.contents.draw_text(x, y, width, 32, actor.class_name, 2) self.contents.draw_text(x, y + 64, width, 32, actor.job_level.to_s, 2) self.contents.draw_text(x, y + 96, width, 32, actor.job_exp.to_s, 2) nex = BlizzCFG::LVLUP_RATE * actor.job_level * (actor.job_level + 1) if actor.job_max_level? self.contents.draw_text(x, y + 128, width, 32, BlizzCFG::EmptyEXP, 2) else self.contents.draw_text(x, y + 128, width, 32, (nex - actor.job_exp).to_s, 2) end # change color to red if no Job Points left self.contents.font.color = Color.new(255, 0, 0) if actor.jp == 0 self.contents.draw_text(x, y + 32, width, 32, actor.jp.to_s, 2) end end #============================================================================== # Window_Dialog #------------------------------------------------------------------------------ # Confirmation Dialog window class. #============================================================================== class Window_Dialog < Window_Command #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(width, commands = BlizzCFG::YesNo, caption = BlizzCFG::AreYouSure) # add another command, serves as fix commands = commands + [''] # set caption @caption = caption @cursor_width = 32 super(width, commands) # font fix if $fontface != nil self.contents.font.name = $fontface self.contents.font.size = $fontsize elsif $defaultfonttype != nil self.contents.font.name = $defaultfonttype self.contents.font.size = $defaultfontsize end # set variables self.x, self.y, self.z = 320 - self.width / 2, 200 - self.height / 2, 1500 @item_max, self.opacity = commands.size - 1, 192 commands.each {|c| w = self.contents.text_size(c).width @cursor_width = w if @cursor_width < w} @cursor_width += 32 # refresh display refresh update_cursor_rect end #---------------------------------------------------------------------------- # refresh # Added caption text. #---------------------------------------------------------------------------- def refresh super self.contents.font.color = system_color self.contents.draw_text(4, 0, self.width - 40, 32, @caption, 1) end #---------------------------------------------------------------------------- # draw_item # i - index # color - font color # Changed method to draw commands one line off. #---------------------------------------------------------------------------- def draw_item(index, color) self.contents.font.color = color rect = Rect.new(4, 32 * (index + 1), self.contents.width - 8, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) self.contents.draw_text(rect, @commands[index], 1) end #---------------------------------------------------------------------------- # update_cursor_rect # Changed method to draw cursor one line off. #---------------------------------------------------------------------------- def update_cursor_rect if @index < 0 || @item_max == 0 self.cursor_rect.empty else x = (self.contents.width - @cursor_width) / 2 self.cursor_rect.set(x, (@index + 1) * 32, @cursor_width, 32) end end end #============================================================================== # Window_ClassStatus #------------------------------------------------------------------------------ # This window displays the character status and includes data about the # current Job like Level, EXP and Job Points along with stat change if the # class is being changed. #============================================================================== class Window_ClassStatus < Window_Base # setting all accessible variables attr_accessor :actor #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(actor) super(BlizzCFG::RO_RIGHT ? 0 : 224, 0, 416, 480) @actor = actor self.contents = Bitmap.new(width - 32, height - 32) # font fix if $fontface != nil self.contents.font.name = $fontface self.contents.font.size = $fontsize elsif $defaultfonttype != nil self.contents.font.name = $defaultfonttype self.contents.font.size = $defaultfontsize end refresh end #---------------------------------------------------------------------------- # refresh # Processes all that is being drawn. #---------------------------------------------------------------------------- def refresh(id = nil) self.contents.clear # stop if actor doesn't exist return if @actor == nil actor = @actor.clone # can't use Game_Actor#class_id= because it unequips equipment actor.instance_variable_set('@class_id', id) if id != nil # draw actor data draw_actor_battler(@actor, 280, 128) draw_actor_name(@actor, 4, 0) draw_actor_level(@actor, 4, 32) draw_actor_state(@actor, 4, 64) draw_actor_hp(@actor, 4, 160, 160) draw_actor_sp(@actor, 4, 192, 160) draw_actor_hp_mod(@actor, 4, 160, actor, 160) draw_actor_sp_mod(@actor, 4, 192, actor, 160) draw_actor_job(@actor, 188, 288, 192) (0..6).each {|i| draw_actor_parameter(@actor, 4, 224 + 32 * i, i) draw_actor_parameter_mod(@actor, 4, 224 + 32 * i, i, actor)} self.contents.font.color = system_color self.contents.draw_text(4, 96, 80, 32, BlizzCFG::EXP) self.contents.draw_text(4, 128, 80, 32, BlizzCFG::Next) self.contents.font.color = normal_color self.contents.draw_text(4, 96, 156, 32, @actor.exp_s, 2) self.contents.draw_text(4, 128, 156, 32, @actor.next_rest_exp_s, 2) end #-------------------------------------------------------------------------- # draw_actor_hp_mod # actor - the actor # x - x-coordinate # y - y-coordinate # other - the actor before # width - maximal allowed width # This method erases the max HP value to redraw it in the right color. #-------------------------------------------------------------------------- def draw_actor_hp_mod(actor, x, y, other, width = 144) # stop if width exceeds max return if width - 32 < 108 # decide color if other.maxhp > actor.maxhp self.contents.font.color = BlizzCFG::UP_COLOR elsif other.maxhp < actor.maxhp self.contents.font.color = BlizzCFG::DOWN_COLOR else return end # delete old display self.contents.fill_rect(x + width - 48, y, 48, 32, Color.new(0, 0, 0, 0)) # draw self.contents.draw_text(x + width - 48, y, 48, 32, other.maxhp.to_s) end #-------------------------------------------------------------------------- # draw_actor_sp_mod # actor - the actor # x - x-coordinate # y - y-coordinate # other - the actor before # width - maximal allowed width # This method erases the max HP value to redraw it in the right color. #-------------------------------------------------------------------------- def draw_actor_sp_mod(actor, x, y, other, width = 144) # stop if width exceeds max return if width - 32 < 108 # decide color if other.maxsp > actor.maxsp self.contents.font.color = BlizzCFG::UP_COLOR elsif other.maxsp < actor.maxsp self.contents.font.color = BlizzCFG::DOWN_COLOR else return end # delete old display self.contents.fill_rect(x + width - 48, y, 48, 32, Color.new(0, 0, 0, 0)) # draw self.contents.draw_text(x + width - 48, y, 48, 32, other.maxsp.to_s) end #-------------------------------------------------------------------------- # draw_actor_parameter_mod # actor - the actor # x - x-coordinate # y - y-coordinate # other - the actor before # type - which stat # This method erases a stat value to redraw it in the right color. #-------------------------------------------------------------------------- def draw_actor_parameter_mod(actor, x, y, type, other) # decide parameter case type when 3 then str, v1, v2 = $data_system.words.str, actor.str, other.str when 4 then dex, v1, v2 = $data_system.words.dex, actor.dex, other.dex when 5 then agi, v1, v2 = $data_system.words.agi, actor.agi, other.agi when 6 then int, v1, v2 = $data_system.words.int, actor.int, other.int else return end # decide color if v2 > v1 self.contents.font.color = BlizzCFG::UP_COLOR elsif v2 < v1 self.contents.font.color = BlizzCFG::DOWN_COLOR else return end # delete old display self.contents.fill_rect(x + 120, y, 36, 32, Color.new(0, 0, 0, 0)) # draw self.contents.draw_text(x + 120, y, 36, 32, v2.to_s, 2) end end #============================================================================== # Window_Class #------------------------------------------------------------------------------ # This window is a slight modification of the Window_Command window to avoid # recoding. #============================================================================== class Window_Class < Window_Command #---------------------------------------------------------------------------- # draw_item # i - index # color - font color # Changed to draw class/job and level requirement. #---------------------------------------------------------------------------- def draw_item(i, color) self.contents.font.color = color rect = Rect.new(4, 32 * i, self.contents.width - 8, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) self.contents.draw_text(rect, @commands[i][0]) self.contents.draw_text(rect, @commands[i][1], 2) end end #============================================================================== # Window_SkillLearn #------------------------------------------------------------------------------ # This window displays all skills that can be still learned. #============================================================================== class Window_SkillLearn < Window_Command # setting all accessible variables attr_reader :commands #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(width, actor) @actor = actor super(width, refresh_skills) self.z, self.height, self.index = 500, 224, -1 self.x, self.active = BlizzCFG::RO_RIGHT ? 320 : 0, false end #---------------------------------------------------------------------------- # refresh_skills # This method sets up the skill list again. #---------------------------------------------------------------------------- def refresh_skills skills = $data_classes[@actor.class_id].learnings.clone # if using the option to hide skills that don't meet the requirements if BlizzCFG::HIDE_SKILLS # temporary variable lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level) # get all learnable skills that weren't learned already skills = skills.find_all {|learn| @actor.job_level >= learn.level && BlizzCFG.roskill_reqs(learn.skill_id).all? {|r| @actor.skills.include?(r[0]) && @actor.skill_level(r[0]) >= r[1]}} end # filter out all skills that weren't learned already skills = skills.find_all {|learn| !@actor.skills.include?(learn.skill_id)} return (skills.size == 0 ? [nil] : skills) end #---------------------------------------------------------------------------- # refresh # This method was modifies to draw "None" is no skills are available and # refreshes the skill list upon redrawing. #---------------------------------------------------------------------------- def refresh @commands = refresh_skills @item_max = @commands.size if @commands[0] == nil self.contents.clear self.contents.font.color = disabled_color self.contents.draw_text(4, 0, self.contents.width - 8, 32, BlizzCFG::None) else super end end #---------------------------------------------------------------------------- # draw_item # i - index # color - font color # Draws a specific skill and the level requirement to learn it. #---------------------------------------------------------------------------- def draw_item(i, color = nil) lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level) # decide color depending on which level is used if !BlizzCFG::HIDE_SKILLS && (lvl < @commands[i].level || BlizzCFG.roskill_reqs(@commands[i].skill_id).any? {|r| !@actor.skills.include?(r[0]) || @actor.skill_level(r[0]) < r[1]}) self.contents.font.color = disabled_color else self.contents.font.color = normal_color end # get rectangle rect = Rect.new(32, 32 * i, self.contents.width - 36, 32) # get icon bitmap bitmap = RPG::Cache.icon($data_skills[@commands[i].skill_id].icon_name) opacity = self.contents.font.color == normal_color ? 255 : 128 # draw bitmap self.contents.blt(4, 4 + 32 * i, bitmap, Rect.new(0, 0, 24, 24), opacity) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) # draw name and requirement if not using the hiding option self.contents.draw_text(rect, $data_skills[@commands[i].skill_id].name) unless BlizzCFG::HIDE_SKILLS self.contents.draw_text(rect, "(#{BlizzCFG::Lv} #{@commands[i].level})", 2) end end #---------------------------------------------------------------------------- # update_help # Updates the skill status display. #---------------------------------------------------------------------------- def update_help @help_window.set_text(@commands[index] == nil ? 0 : @commands[index].skill_id) end end #============================================================================== # Window_SkillImprove #------------------------------------------------------------------------------ # This window displays skills that are already learned. #============================================================================== class Window_SkillImprove < Window_Command # setting all accessible variables attr_accessor :commands #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(width, actor) @actor, skills = actor, actor.skills skills = [nil] if skills.size == 0 super(width, skills) self.z, self.height, self.index = 500, 224, -1 self.x, self.active = BlizzCFG::RO_RIGHT ? 0 : 320, false end #---------------------------------------------------------------------------- # set_commands # commands - new commands # Sets a new list of skills and updates the display. #---------------------------------------------------------------------------- def set_commands(commands) commands = [nil] if commands.size == 0 @commands, @item_max = commands, commands.size self.contents.dispose self.contents = Bitmap.new(width - 32, @item_max * 32) refresh end #---------------------------------------------------------------------------- # refresh # Changed to draw "None" if no skills are available. #---------------------------------------------------------------------------- def refresh if @commands[0] == nil self.contents.clear self.contents.font.color = disabled_color self.contents.draw_text(4, 0, self.contents.width - 8, 32, BlizzCFG::None) else super end end #---------------------------------------------------------------------------- # draw_item # i - index # color - font color # Draws a specific skill with SP cost, considering the changed SO cost due # to the skill level. #---------------------------------------------------------------------------- def draw_item(i, color = nil) skill = $data_skills[@commands[i]] # decide color whether skill can still be improved if @actor.skill_max_level?(skill.id) self.contents.font.color = disabled_color else self.contents.font.color = color end # get rectangle rect = Rect.new(32, 32 * i, self.contents.width - 36, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) # get icon bitmap bitmap = RPG::Cache.icon(skill.icon_name) opacity = self.contents.font.color == normal_color ? 255 : 128 # draw bitmap self.contents.blt(4, 4 + 32 * i, bitmap, Rect.new(0, 0, 24, 24), opacity) self.contents.draw_text(rect, skill.name) # calculate SP cost considering skill level sp_cost = (skill.sp_cost * @actor.get_skill_sp_cost_factor(skill.id)).to_i # draw SP cost self.contents.draw_text(rect, sp_cost.to_s, 2) end #---------------------------------------------------------------------------- # update_help # Updates the skill status display. #---------------------------------------------------------------------------- def update_help @help_window.set_text(@commands[index] == nil ? 0 : @commands[index]) end end #============================================================================== # Window_SkillLevel #------------------------------------------------------------------------------ # This window displays the current skill's data like Level, Power Percentage, # modified SP Cost, etc. #============================================================================== class Window_SkillLevel < Window_Base #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(actor) super(BlizzCFG::RO_RIGHT ? 0 : 416, 0, 224, 192) @actor, self.contents = actor, Bitmap.new(width - 32, height - 32) # font fix if $fontface != nil self.contents.font.name = $fontface self.contents.font.size = $fontsize elsif $defaultfonttype != nil self.contents.font.name = $defaultfonttype self.contents.font.size = $defaultfontsize end @help_window = Window_Help.new end #---------------------------------------------------------------------------- # refresh # Helping method for easier code overview that redraws the display no matter # what. #---------------------------------------------------------------------------- def refresh return if @skill == nil id, @skill = @skill.id, nil set_text(id) end #---------------------------------------------------------------------------- # set_text # id - skill ID # This method draws the currently selected skill's data and stores it so the # display only gets redrawn each time it changes. #---------------------------------------------------------------------------- def set_text(id) # stop if same skill as before return if @skill == $data_skills[id] self.contents.clear @skill = $data_skills[id] # if skill doesn't exist if @skill == nil # emtpy description window and stop @help_window.set_text('') return end # get icon bitmap and draw it bitmap = RPG::Cache.icon(@skill.icon_name) self.contents.blt(4, 4, bitmap, Rect.new(0, 0, 24, 24)) self.contents.draw_text(32, 0, 156, 32, @skill.name) # calculate SP cost considering skill level sp_cost = (@skill.sp_cost * @actor.get_skill_sp_cost_factor(@skill.id)).to_i # calculate damage multiplier considering skill level power = (100 * @actor.get_skill_damage_factor(@skill.id)).to_i self.contents.font.color = system_color # draw all static words self.contents.draw_text(4, 32, 184, 32, BlizzCFG::SkillLevel + ':') self.contents.draw_text(4, 64, 184, 32, BlizzCFG::MaximumLevel + ':') self.contents.draw_text(4, 96, 184, 32, BlizzCFG::Cost + ':') self.contents.draw_text(4, 128, 184, 32, BlizzCFG::Power + ':') self.contents.draw_text(4, 64, 184, 32, BlizzCFG.roskill_maxlevel(@skill.id).to_s, 2) self.contents.font.color = normal_color # draw all the data self.contents.draw_text(4, 32, 184, 32, @actor.skill_level(@skill.id).to_s, 2) sp_cost = "#{sp_cost} #{$data_system.words.sp}" self.contents.draw_text(4, 96, 184, 32, sp_cost, 2) self.contents.draw_text(4, 128, 184, 32, "#{power}%", 2) # set help window text to skill description @help_window.set_text(@skill.description, 1) end #---------------------------------------------------------------------------- # dispose # This method was enhanced to dispose the skill description window. #---------------------------------------------------------------------------- def dispose @help_window.dispose super end end #============================================================================== # Window_JobLevel #------------------------------------------------------------------------------ # This window displays job data. #============================================================================== class Window_JobLevel < Window_Base #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(actor) super(BlizzCFG::RO_RIGHT ? 416 : 0, 0, 224, 192) @actor, self.contents = actor, Bitmap.new(width - 32, height - 32) # font fix if $fontface != nil self.contents.font.name = $fontface self.contents.font.size = $fontsize elsif $defaultfonttype != nil self.contents.font.name = $defaultfonttype self.contents.font.size = $defaultfontsize end refresh end #---------------------------------------------------------------------------- # refresh # This method draws the job data. #---------------------------------------------------------------------------- def refresh self.contents.clear draw_actor_job(@actor, 4, 0, 184) end end #============================================================================== # Scene_ClassChange #------------------------------------------------------------------------------ # This scene processes the class/job change system. #============================================================================== class Scene_ClassChange #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(index = 0, scene = Scene_Map) @actor, @scene = $game_party.actors[index], scene end #---------------------------------------------------------------------------- # main # Main processing method. #---------------------------------------------------------------------------- def main # create main command window @command_window = Window_Command.new(224, BlizzCFG::ClassCommands) @command_window.x = BlizzCFG::RO_RIGHT ? 416 : 0 # create status window @status_window = Window_ClassStatus.new(@actor) @old_index = 0 make_class_window Graphics.transition loop do Graphics.update Input.update update break if $scene != self end Graphics.freeze # delete all windows @command_window.dispose @status_window.dispose @class_window.dispose end #---------------------------------------------------------------------------- # make_class_window # This method helps to make the code easier to overview. #---------------------------------------------------------------------------- def make_class_window # delete old window if there is one @class_window.dispose unless @class_window == nil || @class_window.disposed? # get configuration and initialize data @configs = BlizzCFG.rojob_next(@actor.class_id) commands, lvl = [], (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level) # if no configs if @configs[0].size == 0 # set to "None" commands = [[BlizzCFG::None, '']] else # add command data @configs.each {|c| commands.push([$data_classes[c[1]].name, "(#{BlizzCFG::Lv} #{c[0]})"])} end # create window with given data @class_window = Window_Class.new(224, commands) @class_window.x, @class_window.y = BlizzCFG::RO_RIGHT ? 416 : 0, 160 @class_window.height, @class_window.index = 320, -1 # if no configuration if @configs[0].size == 0 # set text color to disabled @class_window.disable_item(0) @command_window.disable_item(0) else # disable each new class/job that does not fulfill the requirement @configs.each_index {|i| @class_window.disable_item(i) if lvl < @configs[i][0]} @command_window.refresh end end #---------------------------------------------------------------------------- # update # This is the main update method which calls the appropriate method # depending on which window is currently active. #---------------------------------------------------------------------------- def update if @command_window.active @command_window.update update_command elsif @sure_window != nil @sure_window.update update_sure elsif @class_window.active @class_window.update update_classchange end end #---------------------------------------------------------------------------- # update_comand # This method updates the command window input. #---------------------------------------------------------------------------- def update_command # if cancel button pressed if Input.trigger?(Input::B) # play sound and return to previous scene $game_system.se_play($data_system.cancel_se) $scene = @scene.new # if confirm button pressed elsif Input.trigger?(Input::C) size = $game_party.actors.size # depending on chosen option activate jobchange, change actor or leave case @command_window.index when 0 if @configs[0].size == 0 $game_system.se_play($data_system.buzzer_se) return end $game_system.se_play($data_system.decision_se) @command_window.active, @class_window.active = false, true @class_window.index = @old_index @status_window.refresh(@configs[@class_window.index][1]) when 1 then $scene = self.class.new((@actor.index + 1) % size, @scene) when 2 then $scene = self.class.new((@actor.index + size - 1) % size, @scene) when 3 then $scene = @scene.new end $game_system.se_play($data_system.decision_se) end end #---------------------------------------------------------------------------- # update_classchange # This method updates the class change window input. #---------------------------------------------------------------------------- def update_classchange # if cancel button pressed if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) @command_window.active = true @old_index = @class_window.index @class_window.active, @class_window.index = false, -1 @status_window.refresh # if confirm button pressed elsif Input.trigger?(Input::C) lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level) # if requirements are not fulfilled if lvl < @configs[@class_window.index][0] $game_system.se_play($data_system.buzzer_se) else $game_system.se_play($data_system.decision_se) # create confirmation window @sure_window = Window_Dialog.new(224, BlizzCFG::YesNo, BlizzCFG::ChangeClass) @sure_window.z, @class_window.active = 500, false end # if up/down is being pressed elsif Input.trigger?(Input::UP) || Input.trigger?(Input::DOWN) # apply status window change @status_window.refresh(@configs[@class_window.index][1]) end end #---------------------------------------------------------------------------- # update_sure # This method updates the confirmation window input. #---------------------------------------------------------------------------- def update_sure # if cancel button pressed if Input.trigger?(Input::B) # play sound and remove confirmation window $game_system.se_play($data_system.cancel_se) @sure_window.dispose @class_window.active, @sure_window = true, nil # if confirm button pressed elsif Input.trigger?(Input::C) $game_system.se_play($data_system.decision_se) # either accept or decline and remove confirmation window case @sure_window.index when 0 id = @actor.class_id @actor.class_id = @configs[@class_window.index][1] @actor.hp, @actor.sp = @actor.hp, @actor.sp @status_window.refresh if !BlizzCFG::JOB_ONLY && BlizzCFG::CLASS_SKILLS && @actor.class_id != id && $data_classes[id] != nil # remove all skills $data_classes[id].learnings.each {|i| @actor.forget_skill(i.skill_id)} end make_class_window @sure_window.dispose @command_window.active, @sure_window = true, nil @old_index = 0 when 1 @sure_window.dispose @class_window.active, @sure_window = true, nil end end end end #============================================================================== # Scene_SkillChange #------------------------------------------------------------------------------ # This scene processes the learning and improving (leveling up) of RO skills. #============================================================================== class Scene_SkillChange #---------------------------------------------------------------------------- # Initialization #---------------------------------------------------------------------------- def initialize(index = 0, scene = Scene_Map) @actor, @scene = $game_party.actors[index], scene end #---------------------------------------------------------------------------- # main # This is the main processing method. #---------------------------------------------------------------------------- def main # create main command window @command_window = Window_Command.new(192, BlizzCFG::SkillCommands) # create other windows @learn_window = Window_SkillLearn.new(320, @actor) @skill_window = Window_SkillImprove.new(320, @actor) @status_window = Window_SkillLevel.new(@actor) @job_window = Window_JobLevel.new(@actor) # set window positions @command_window.y = @status_window.y = @job_window.y = 64 @command_window.x, @learn_window.y, @skill_window.y = 224, 256, 256 @learn_window.x, @skill_window.x = 320, 0 if BlizzCFG::RO_RIGHT @learn_window.help_window = @skill_window.help_window = @status_window # skill status window must be clear @status_window.set_text(0) # disable command if no skills in the given category @command_window.disable_item(0) if @learn_window.commands[0] == nil @command_window.disable_item(1) if @skill_window.commands[0] == nil Graphics.transition loop do Graphics.update Input.update update break if $scene != self end Graphics.freeze # remove all windows [@command_window, @learn_window, @skill_window, @status_window, @job_window].each {|win|win.dispose} end #---------------------------------------------------------------------------- # update # This is the main update method which calls the appropriate method # depending on which window is currently active. #---------------------------------------------------------------------------- def update if @command_window.active @command_window.update update_command elsif @sure_window != nil @sure_window.update # update the correct confirmation @learn_window.index >= 0 ? update_sure_learn : update_sure_skill elsif @learn_window.active @learn_window.update update_learn elsif @skill_window.active @skill_window.update update_skill end end #---------------------------------------------------------------------------- # update_sure # This method updates the command window input. #---------------------------------------------------------------------------- def update_command # if cancel button pressed if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) $scene = @scene.new # if confirm button pressed elsif Input.trigger?(Input::C) size = $game_party.actors.size # choose next menu, change actor or leave case @command_window.index when 0 # if no skills in this category if @learn_window.commands[0] == nil # play sound and stop $game_system.se_play($data_system.buzzer_se) return end # play sound and activate other window $game_system.se_play($data_system.decision_se) @command_window.active, @learn_window.active = false, true @learn_window.index = 0 when 1 # if no skills in this category if @skill_window.commands[0] == nil # play sound and stop $game_system.se_play($data_system.buzzer_se) return end # play sound and activate other window $game_system.se_play($data_system.decision_se) @command_window.active, @skill_window.active = false, true @skill_window.index = 0 when 2 then $scene = self.class.new((@actor.index + 1) % size, @scene) when 3 then $scene = self.class.new((@actor.index + size - 1) % size, @scene) when 4 then $scene = @scene.new end $game_system.se_play($data_system.decision_se) end end #---------------------------------------------------------------------------- # update_sure # This method updates the skill learn window input. #---------------------------------------------------------------------------- def update_learn # if cancel button pressed if Input.trigger?(Input::B) # play sound and return to main command $game_system.se_play($data_system.cancel_se) @command_window.active, @learn_window.active = true, false @status_window.set_text(0) @learn_window.index = -1 # if confirm button pressed elsif Input.trigger?(Input::C) lvl = (BlizzCFG::USE_LEVEL ? @actor.level : @actor.job_level) # temporary variable learn = @learn_window.commands[@learn_window.index] # if skill doesn't exist, cannot be learned, no Job Points or reqs not fulfilled if learn == nil || @actor.jp == 0 || lvl < learn.level || BlizzCFG.roskill_reqs(learn.skill_id).any? {|r| !@actor.skills.include?(r[0]) || @actor.skill_level(r[0]) < r[1]} # play sound $game_system.se_play($data_system.buzzer_se) else # play sound and create confirmation window $game_system.se_play($data_system.decision_se) @sure_window = Window_Dialog.new(224, BlizzCFG::YesNo, BlizzCFG::LearnSkill) @learn_window.active = false end end end #---------------------------------------------------------------------------- # update_sure # This method updates the skill improve window input. #---------------------------------------------------------------------------- def update_skill # if cancel button pressed if Input.trigger?(Input::B) # play sound and return to main command $game_system.se_play($data_system.cancel_se) @command_window.active, @skill_window.active = true, false @status_window.set_text(0) @skill_window.index = -1 # if confirm button pressed elsif Input.trigger?(Input::C) skill = $data_skills[@skill_window.commands[@skill_window.index]] # if no Job Points skill or skill already maximized if @actor.jp == 0 || @actor.skill_max_level?(skill.id) # play sound $game_system.se_play($data_system.buzzer_se) else # play sound and create confirmation window $game_system.se_play($data_system.decision_se) @sure_window = Window_Dialog.new(224, BlizzCFG::YesNo, BlizzCFG::ImproveSkill) @skill_window.active = false end end end #---------------------------------------------------------------------------- # update_sure # This method updates the confirmation of learning input. #---------------------------------------------------------------------------- def update_sure_learn # if cancel button pressed if Input.trigger?(Input::B) # play sound and remove confirmation window $game_system.se_play($data_system.cancel_se) @sure_window.dispose @learn_window.active, @sure_window = true, nil # if confirm button pressed elsif Input.trigger?(Input::C) $game_system.se_play($data_system.decision_se) # if confirmed if @sure_window.index == 0 # consume Job Point @actor.jp -= 1 # temporary variable id = @learn_window.commands[@learn_window.index].skill_id # if CRLS is installed and CD skill if $crls != nil && BlizzCFG::CD_SKILLS.include?(id) # learn new CD skill @actor.learn_cd(id) else # learn new skill @actor.learn_skill(id) end # update window displays @learn_window.refresh @skill_window.set_commands(@actor.skills.clone) if @learn_window.commands[0] == nil @command_window.disable_item(0) else @command_window.draw_item(0, @command_window.normal_color) end if @skill_window.commands[0] == nil @command_window.disable_item(1) else @command_window.draw_item(1, @command_window.normal_color) end @job_window.refresh end # remove confirmation window @sure_window.dispose @learn_window.active, @sure_window = true, nil end end #---------------------------------------------------------------------------- # update_sure # This method updates the confirmation of improving input. #---------------------------------------------------------------------------- def update_sure_skill # if cancel button pressed if Input.trigger?(Input::B) # play sound and remove confirmation window $game_system.se_play($data_system.cancel_se) @sure_window.dispose @skill_window.active, @sure_window = true, nil # if confirm button pressed elsif Input.trigger?(Input::C) $game_system.se_play($data_system.decision_se) if @sure_window.index == 0 skill = $data_skills[@skill_window.commands[@skill_window.index]] # consume Job Point @actor.jp -= 1 # improve skill @actor.skill_level_change(@actor.skill_level(skill.id) + 1, skill.id) # update window displays [@status_window, @skill_window, @learn_window, @job_window].each {|win| win.refresh} (0..1).each {|i| @command_window.draw_item(i, Color.new(255, 255, 255))} @command_window.disable_item(0) if @learn_window.commands[0] == nil @command_window.disable_item(1) if @skill_window.commands[0] == nil end # remove confirmation window @sure_window.dispose @skill_window.active, @sure_window = true, nil end end end