Modern Algebra's Advanced Skill Options (MAASO)
Version: 2.0
Author: modern algebra
Date: June 5, 2007
Version History
- Version 2.0 Made use of the Paragraph Formatter. As well, aliased all methods rather then overwriting. Shortened code. Removed the potential to do 0 damage. Now the power of the skill varies arithmetically with the SP devoted to it.
- Version 1.1 Optimized a portion of the code, as well as reducing the number of global variables. Also fixed my initial oversight and now you can still cast a spell if you have less SP left then the max SP of a spell, with the roof being your current amount of SP
- Version 1.0 Original; included basic sp devotion determines damage
Description
This is somewhat similar to Betrayal at Krondor, but since everybody besides me is lame and hasn't played that amazing game, so a quick explanation is in order. This script allows the user to choose how much SP he would like to expend on the skill, and that determines how much damage the skill does. It modifies every skill stat that modifies damage (except for enemy MDEF and PDEF), by the percentage of the SP being used to the max SP cost of the skill. My suggestion is to make skills very powerful and SP rare, so that dedicating maybe half of the max to a skill can still do a decent amount of damage more than a regular attack. As well, any skill with a power of 0 or a common event attached to it is neglected by this, and so the choosing screen will not run. Any skills that modify status (Poison, Sharp, etc...) should have the power set to 0 since the script does not effect the length of a status effect. Maybe if there's a v. 2.5 then I will add that)
Features
- Allows the user to choose how much SP to dedicate to a skill, and thus allows him to modify how much damage or healing it does
- Skills with a power of 0 are neglected, as well as skills with a common event attached to it, so skills which only modify states have a fixed SP cost. If yoy want a skill to always have fixed SP cost
- Adds some strategy to skill use
- lots of minor, infuriating bugs (actually, none that I know of, but I suspect they are just hiding from me)
- enemies always use max SP for max damage
ScreenshotsInstructions Place this script right above main. This script also requires the
Paragraph FormatterScript
#==============================================================================
# Modern Algebra's Advanced Skill Options (MAASO)
# Version 2.0
# Author: modern algebra
# Date: August 29, 2007
#------------------------------------------------------------------------------
# Description:
# This script is loosely based off the Betrayal at Krondor Spell System, with
# a few differences. Basically, it allows the player to determine the power of
# his skills by choosing how much SP he will use to use the skill. Basically,
# it multiplies the damage by the percentage of the max SP the player uses.
# So, if the player devotes 20 SP to a skill that can take 100 SP, the skill
# will only do 20% of the regular damage.
#------------------------------------------------------------------------------
# Compatibility:
# The way this script works is to multiply the 'power' stats of a skill
# (power, atk_f, pdef_f, mdef_f) by the percentage. Thus, for some custom
# battle formulas, this will not work in the same way. As well, while the
# script does not overwrite any methods, it does assume some things about some
# of the methods, and as such may not work with heavily modified versions of
# Scene_Battle.
#------------------------------------------------------------------------------
# Instructions:
# Place this script above main in the script editor
#==============================================================================
#==============================================================================
# ** Game Battler (MAASO modifications)
#------------------------------------------------------------------------------
# This class deals with battlers. It's used as a superclass for the Game_Actor
# and Game_Enemy classes.
# MAASO aliases:
# :skill_can_use?
#==============================================================================
class Game_Battler
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :damage_multiplier
#--------------------------------------------------------------------------
# Aliases skill_can_use? method in order to change it so that having less than
# maximum sp cost does not disable the skill
#--------------------------------------------------------------------------
alias maaso_disable_sp_requirement skill_can_use?
def skill_can_use? (skill_id)
skill = $data_skills[skill_id]
# Disable the skill if you have no SP and the skill requires some SP
if self.sp == 0 && skill.sp_cost != 0
return false
end
# Disable the skill if it haas a set SP cost and you do not have enough SP
if (skill.power == 0 || skill.common_event_id != 0) && self.sp < skill.sp_cost
return false
end
# Save the sp cost of the skill
save_sp = $data_skills[skill_id].sp_cost
# Temporarily reduce sp cost to 0 to fool the method this is aliasing
$data_skills[skill_id].sp_cost = 0
# Run original
disable = maaso_disable_sp_requirement (skill_id)
# Restore the sp cost of the skill
$data_skills[skill_id].sp_cost = save_sp
return disable
end
end
#==============================================================================
# ** Window_SkillData
#------------------------------------------------------------------------------
# Displays the Skill Description, the max power, the damage and the SP
#==============================================================================
class Window_SkillData < Window_Base
#-------------------------------------------------------------------------
# * Object Initialization
#-------------------------------------------------------------------------
def initialize
super(300, 140, 320, 260)
self.contents = Bitmap.new(width - 32, height - 32)
self.opacity = 235
self.visible = false
self.z=190
end
#-------------------------------------------------------------------------
# * Refresh
#-------------------------------------------------------------------------
def refresh (skill, amount)
self.contents.clear
self.contents.font.color = system_color
# Draw Skill Name
self.contents.draw_text (0,0,288,32, skill.name,1)
self.contents.font.color = normal_color
self.contents.font.size = 18
# Draw Description using the Paragraph Formatter
self.contents.draw_paragraph (0, 32, 288, 96, skill.description)
self.contents.font.color = system_color
self.contents.font.size = 22
# Draw Signifier Texts
self.contents.draw_text (0,2*26 + 64,160,32, "Skill Power:")
self.contents.draw_text (0,2*26 + 96,160,32, "Max " +$data_system.words.sp+ " Cost:")
self.contents.draw_text (0,2*26 + 128,160,32, "Current Power:")
self.contents.font.color = normal_color
max_power = skill.power.to_f / skill.sp_cost.to_f
max_power = (max_power*100).round.to_f / 100.0
# Draw Stats
self.contents.draw_text (0, 2*26 + 64, 248, 32, max_power.to_s + " * " +$data_system.words.sp, 2)
self.contents.draw_text (0, 2*26 + 96, 248, 32, skill.sp_cost.to_s, 2)
self.contents.draw_text (0, 2*26 + 128, 248, 32, (max_power*amount).to_f.to_s, 2)
end
end
#==============================================================================
# ** Window Input SP
#------------------------------------------------------------------------------
# A window used to allow the user to choose the amount of SP they devote to
# the skill
#==============================================================================
class Window_InputSP < Window_Selectable
#-------------------------------------------------------------------------
# * Public Instance Variables
#-------------------------------------------------------------------------
attr_accessor :amount
#-------------------------------------------------------------------------
# * Object Initialization
#-------------------------------------------------------------------------
def initialize
super(220, 370, 100, 80)
@amount = 1
self.contents = Bitmap.new(width - 32, height - 32)
@number_size = self.contents.text_size ('1')
self.z=300
self.opacity = 235
self.active = false
self.visible = false
end
#-------------------------------------------------------------------------
# * Refresh
#-------------------------------------------------------------------------
def refresh
self.contents.clear
@number_size = self.contents.text_size(@amount.to_s)
self.contents.draw_text (34 - @number_size.width/2, 6,@number_size.width,32,@amount.to_s)
end
#--------------------------------------------------------------------------
# * Cursor Rectangle Update
#--------------------------------------------------------------------------
def update_cursor_rect
@index = self.index
if @index < 0
self.cursor_rect.empty
else
self.cursor_rect.set(32-@number_size.width/2,8,@number_size.width+4,@number_size.height+4)
end
end
#-------------------------------------------------------------------------
# * Frame Update
#-------------------------------------------------------------------------
def update (maximum)
if Input.repeat? (Input::DOWN) # Subtract by 10
$game_system.se_play($data_system.cursor_se)
# Ensures that @amount never goes below 1
@amount = [@amount - 10, 1].max
refresh
update_cursor_rect
elsif Input.repeat? (Input::UP) # Add by 10
$game_system.se_play($data_system.cursor_se)
# Ensures that @amount never goes above the maximum
@amount = [@amount + 10, maximum].min
refresh
update_cursor_rect
elsif Input.repeat? (Input::RIGHT) # Add by 1
$game_system.se_play($data_system.cursor_se)
# Ensures that @amount never goes above the maximum
@amount = [@amount + 1, maximum].min
refresh
update_cursor_rect
elsif Input.repeat? (Input::LEFT) # Subtract by 1
$game_system.se_play($data_system.cursor_se)
# Ensures that @amount never goes below 1
@amount = [@amount - 1, 1].max
refresh
update_cursor_rect
end
end
end
#==============================================================================
# ** Scene Skill (MAASO modifiactions)
#------------------------------------------------------------------------------
# This class performs skill screen processing.
# MAASO aliases:
# :initialize
# :main
# :update
# :update_skill
# :update_target
#==============================================================================
class Scene_Skill
#-------------------------------------------------------------------------
# * Alias Initialize to initialize wait variable
#-------------------------------------------------------------------------
alias maaso_variable_initialization initialize
def initialize (index)
maaso_variable_initialization (index)
@multiplier = 1.0
@wait = 0
end
#-------------------------------------------------------------------------
# * Alias Main to initialize MAASO windows
#-------------------------------------------------------------------------
alias maaso_new_windows_main main
def main
# Initialize the MAASO windows
@data_window = Window_SkillData.new
@power_window = Window_InputSP.new
# Regular main method
maaso_new_windows_main
# Dispose of the MAASO windows
@data_window.dispose
@power_window.dispose
end
#-------------------------------------------------------------------------
# * Alias Update for SP selection and Wait
#-------------------------------------------------------------------------
alias maaso_update_sp_selection update
def update
# If wait called for
if @wait > 0
if @wait == 1
@target_window.visible = false
@skill_window.active = true
end
@wait -= 1 # Reduce by 1
return
end
# If power window is active: call update_power
if @power_window.active
update_power
return
end
update_maaso_stuff
end
#-------------------------------------------------------------------------
# * Alias Skill Update for MAASO
#-------------------------------------------------------------------------
alias maaso_skill_power_modification update_skill
def update_skill
# If C button was pressed
if Input.trigger?(Input::C)
@skill = @skill_window.skill
# If unable to use
if @skill == nil or not @actor.skill_can_use?(@skill.id)
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
@multiplier = 1.0
if @skill.power != 0 && @skill.common_event_id == 0
# Play Desicion SE
$game_system.se_play ($data_system.decision_se)
# Refresh and open power and data windows
@power_window.index = 0
@power_window.amount = @skill.sp_cost
@power_window.refresh
@power_window.update_cursor_rect
@power_window.visible = true
@data_window.refresh (@skill, 1)
@data_window.visible = true
# Turn off skill window
@skill_window.active = false
# Turn on power window
@power_window.active = true
return
end
end
maaso_skill_power_modification
end
#-------------------------------------------------------------------------
# * Alias Target Update for MAASO
#-------------------------------------------------------------------------
alias maaso_modify_target_update update_target
def update_target
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Erase target window
@target_window.visible = false
@target_window.active = false
@power_window.active = true
@power_window.visible = true
@data_window.visible = true
return
end
# If C button was pressed
if Input.trigger?(Input::C)
@target_window.active = false
@wait = 15
# Store exact values of the stats
skill_stats = [@skill.sp_cost, @skill.power, @skill.atk_f, @skill.pdef_f, @skill.mdef_f]
# Modify the skill stats
@skill.sp_cost = (@skill.sp_cost * @multiplier).to_i
@skill.power = (@skill.power * @multiplier).to_i
@skill.atk_f = (@skill.atk_f * @multiplier).to_i
@skill.pdef_f = (@skill.pdef_f * @multiplier).to_i
@skill.mdef_f = (@skill.mdef_f * @multiplier).to_i
end
maaso_modify_target_update
if skill_stats != nil
@target_window.active = false
@wait = 15
# Restore original stats
@skill.sp_cost = skill_stats[0]
@skill.power = skill_stats[1]
@skill.atk_f = skill_stats[2]
@skill.pdef_f = skill_stats[3]
@skill.mdef_f = skill_stats[4]
@multiplier = 1.0
@skill_window.refresh
end
end
#-------------------------------------------------------------------------
# * Frame Update (when power_window is active)
#-------------------------------------------------------------------------
def update_power
@power_window.update ([@skill.sp_cost, @actor.sp].min)
if Input.dir4 != 0
@data_window.refresh (@skill, @power_window.amount)
end
# If B button was pressed
if Input.trigger?(Input::B)
$game_system.se_play ($data_system.cancel_se)
@power_window.active = false
@power_window.visible = false
@data_window.visible = false
@skill_window.active = true
end
# If C button was pressed
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
choice_sp_cost = @power_window.amount
@multiplier = choice_sp_cost.to_f / @skill.sp_cost
# Turn off choose_power and turn on choose target
@power_window.active = false
@power_window.visible = false
@data_window.visible = false
# Set target_window according to the skill's scope
if @skill.scope >= 3
if @skill.scope == 4 || @skill.scope == 6
@target_window.index = -1
elsif @skill.scope == 7
@target_window.index = @actor_index - 10
else
@target_window.index = 0
end
end
@target_window.visible = true
@target_window.active = true
@target_window.x = (@skill_window.index + 1) % 2 * 304
end
end
end
#==============================================================================
# ** Scene Battle
#------------------------------------------------------------------------------
# This class performs battle screen processing
# MAASO aliases:
# :main
# :end_skill_select
# :update_phase3
# :update_phase3_skill_select
# :make_skill_action_result
#==============================================================================
class Scene_Battle
#--------------------------------------------------------------------------
# Alias main and dispose of windows if they still exist
#--------------------------------------------------------------------------
alias maaso_windows_disposal_main main
def main
maaso_windows_disposal_main
if @power_window != nil
@power_window.dispose
@data_window.dispose
end
end
#--------------------------------------------------------------------------
# Alias end_skill_select and dispose of the power and data windows
#--------------------------------------------------------------------------
alias maaso_dispose_new_windows_end_skill_select end_skill_select
def end_skill_select
maaso_dispose_new_windows_end_skill_select
end_power_select
end
#--------------------------------------------------------------------------
# Alias update_phase3 and add in a condition for @power_window
#--------------------------------------------------------------------------
alias maaso_phase3_update update_phase3
def update_phase3
if @power_window != nil
update_power
return
else
counter = 0
end
maaso_phase3_update
end
#-------------------------------------------------------------------------
# * Frame Update (when power_window is active)
#-------------------------------------------------------------------------
def update_power
@power_window.update ([@skill.sp_cost, @active_battler.sp].min)
if Input.dir4 != 0
@data_window.refresh (@skill, @power_window.amount)
end
# If B button was pressed
if Input.trigger?(Input::B)
$game_system.se_play ($data_system.cancel_se)
@data_window.visible = false
end_power_select
end
# If C button was pressed
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
choice_sp_cost = @power_window.amount
@active_battler.damage_multiplier = choice_sp_cost.to_f / @skill.sp_cost
# Turn off choose_power and turn on choose target
@power_window.active = false
@power_window.visible = false
@data_window.visible = false
# Set action
@active_battler.current_action.skill_id = @skill.id
@skill_window.visible = false
# Set target_window according to the skill's scope
if @skill.scope == 1
# Start enemy selection
start_enemy_select
@power_window.dispose
@power_window = nil
@data_window.dispose
@data_window = nil
# If effect scope is single ally
elsif @skill.scope == 3 or @skill.scope == 5
# Start actor selection
start_actor_select
@power_window.dispose
@power_window = nil
@data_window.dispose
@data_window = nil
# If effect scope is not single
else
# End skill selection
end_skill_select
# Go to command input for next actor
phase3_next_actor
end
end
end
#-------------------------------------------------------------------------
# * End Power Select
#-------------------------------------------------------------------------
def end_power_select
if @power_window != nil
# Dispose and delete the power and data windows
@power_window.dispose
@data_window.dispose
@power_window = nil
@data_window = nil
end
end
#--------------------------------------------------------------------------
# Aliases skill_select to accomadate for MAASO
#--------------------------------------------------------------------------
alias maaso_phase3_skill_selection_update update_phase3_skill_select
def update_phase3_skill_select
# If C button was pressed
if Input.trigger?(Input::C)
@skill = @skill_window.skill
# Play decision SE
$game_system.se_play($data_system.decision_se)
@data_window = Window_SkillData.new
@power_window = Window_InputSP.new
if @skill.power != 0 && @skill.common_event_id == 0
@power_window.visible = true
@power_window.active = true
@data_window.refresh (@skill, 1)
@data_window.visible = true
@power_window.refresh
@power_window.index = 0
else
@power_window.active = false
@power_window.visible = false
@data_window.visible = false
end
end
unless @power_window != nil
maaso_phase3_skill_selection_update
end
return
end
#--------------------------------------------------------------------------
# Alias make_skill_action_result to appropriately shift the skill stats
#--------------------------------------------------------------------------
alias maaso_skill_result make_skill_action_result
def make_skill_action_result
# Get skill
@skill = $data_skills[@active_battler.current_action.skill_id]
# Get multiplier
multiplier = @active_battler.damage_multiplier
multiplier = 0.001 if multiplier.nil?
# Store exact values of the stats
@save_skill_stats = [@skill.sp_cost, @skill.power, @skill.atk_f, @skill.pdef_f, @skill.mdef_f]
# Modify the skill stats
@skill.sp_cost = (@skill.sp_cost * multiplier).to_i
@skill.power = (@skill.power * multiplier).to_i
@skill.atk_f = (@skill.atk_f * multiplier).to_i
@skill.pdef_f = (@skill.pdef_f * multiplier).to_i
@skill.mdef_f = (@skill.mdef_f * multiplier).to_i
maaso_skill_result
@active_battler.damage_multiplier = 1.0
end
#--------------------------------------------------------------------------
# Alias update_phase4_step6 to restore the skill stats to their original
# values. It's not done in make_skill_action_result, so that this
# script will be compatible with MA Skill Effects
#--------------------------------------------------------------------------
alias maaso_step6 update_phase4_step6
def update_phase4_step6
# If a skill was used
if @save_skill_stats != nil
# Restore Stats
@skill.sp_cost = @save_skill_stats[0]
@skill.power = @save_skill_stats[1]
@skill.atk_f = @save_skill_stats[2]
@skill.pdef_f = @save_skill_stats[3]
@skill.mdef_f = @save_skill_stats[4]
# Clear @save_skill_stats
@save_skill_stats = nil
end
# Run original method
maaso_step6
end
end
Credit
Thanks
- Betrayal at Krondor, for being awesome
Support
I will support this script both here at
www.rmrk.net and at
www.rmrevolution.rmrk.net. It actually isn't as long as it looks. Most of the classes I modified, as it was just not possible to alias them for various reasons. But half the script is just the default stuff modified a little bit. I put my name in the title because I notice other scripters seem to be doing it. Bandwagon. Actually, I think there might be other scripts titled the same that don't do the same thing, and so that's why. It was to be Advanced Skill Script, but I didn't like the acronym. Anyways, Enjoy
Known Compatibility Issues
The script will likely not work with exotic CBSes, or with battle formulas that differ significantly from the default.
Demo
See Attached