Vancian Spellcasting
By Pidey
Version .8
Introduction:
This is a system designed to place a special restriction on spellcasters. This system causes the player to have to decide beforehand what spells he wants.
Features:
Screenshots:
http://img258.imageshack.us/img258/5351/vancianlx5.th.png[/img]
Script:
Instructions:
Simply drop the scripts above main in your game, then near the top of the Misc_Vancian part of the script, modify the one line to mark characters to use the vancian system. Then use $scene = Scene_Vancian.new(character's party position) to enter the preparation screen
Demo:
http://hosted.filefront.com/lordpidey Download Vancian.zip (note that this requires RTP)
http://www.mediafire.com/?ce9c0itcczd
Notes:
This script probably could work with RMVX with a little work. However I do not own a copy of RMVX.
By Pidey
Version .8
Introduction:
This is a system designed to place a special restriction on spellcasters. This system causes the player to have to decide beforehand what spells he wants.
Features:
- Forces players to prepare spells before they are cast.
- Ability to mark some characters as vancian, while others remain spontaneous.
- Allows a character to "specialize" in a specific spell for increased effect.
Screenshots:
http://img258.imageshack.us/img258/5351/vancianlx5.th.png[/img]
Script:
Code:
#==============================================================================
# ** Window_Vancian
#------------------------------------------------------------------------------
# This window displays usable skills on the Vancian preparation menu
#Vancian version .8
# Written by Pidey
#==============================================================================
class Window_Vancian < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
# actor : actor
#--------------------------------------------------------------------------
def initialize(actor)
super(0, 128, 640, 352)
@actor = actor
@column_max = 2
refresh
self.index = 0
end
#--------------------------------------------------------------------------
# * Acquiring Skill
#--------------------------------------------------------------------------
def skill
return @data[self.index]
end
def showIndex
return self.index
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
for i in 0...@actor.skills.size
skill = $data_skills[@actor.skills[i]]
if skill != nil
@data.push(skill)
end
end
# If item count is not 0, make a bit map and draw all items
@item_max = @data.size
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
self.contents.font.name = $fontface
self.contents.font.size = $fontsize
for i in 0...@item_max
draw_item(i)
end
end
end
#--------------------------------------------------------------------------
# * Draw Item
# index : item number
#--------------------------------------------------------------------------
def draw_item(index)
skill = @data[index]
if @actor.skill_has_sp?(skill.id)
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
x = 4 + index % 2 * 320
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(skill.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 180, 32, skill.name, 0)
self.contents.draw_text(x + 190, y, 32, 32, skill.sp_cost.to_s, 2)
self.contents.draw_text(x + 226, y, 32, 32, @actor.vancian[skill.id].to_s, 2) #this displays how many times the spell is prepared.
end
#--------------------------------------------------------------------------
# * Help Text Update
#--------------------------------------------------------------------------
def update_help
@help_window.set_text(self.skill == nil ? "" : self.skill.description)
end
end
Code:
#==============================================================================
# ** Window_Vancian_aid
#------------------------------------------------------------------------------
# This window gives options during the vancian preparation.
#Vancian version .8
# Written by Pidey
#==============================================================================
class Window_Vancian_aid < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 0, 336, 480)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = $fontsize
self.z += 10
@item_max = 4
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
for i in 0...$game_party.actors.size
x = 4
y = i * 116
self.contents.draw_text(4, 0, 324, 68, "Set as Default")
self.contents.draw_text(4, 116, 224, 48, "Clear one of spell")
self.contents.draw_text(4, 232, 224, 48, "Clear all of spell")
self.contents.draw_text(4, 348, 224, 48, "Clear all memory")
actor = $game_party.actors[i]
end
end
#--------------------------------------------------------------------------
# * Cursor Rectangle Update
#--------------------------------------------------------------------------
def update_cursor_rect
# Cursor position -1 = all choices, -2 or lower = independent choice
# (meaning the user's own choice)
if @index <= -2
self.cursor_rect.set(0, (@index + 10) * 116, self.width - 32, 96)
elsif @index == -1
self.cursor_rect.set(0, 0, self.width - 32, @item_max * 116 - 20)
else
self.cursor_rect.set(0, @index * 116, self.width - 32, 96)
end
end
end
Code:
#-----------------------------------------------------------------
#Vancian
#-----------------------------------------------------------------
#This class is used to hold a character's Vancian Memory,
#As well as several important functions to the Vancian's working.
#Vancian version .8
# Written by Pidey
class Vancian
#this class holds a character's vancian memory.
def initialize
@current_memory = []
@prefered_memory = []
incriment = 1
while $data_skills[incriment] != nil #this fills the memory with zeroes, so there aren't any nil
@prefered_memory[incriment] = 0
@current_memory[incriment] = 0
incriment += 1
end
end
def ensure_prefered_capacity #use this to catch errors in the event of maximum SP lowering.
if prefered_memory_cost <= $game_actors[@char].max_sp
return true
else
return false
end
end
def set_as_default #this copies the current memory into prefered memory for later retrieval.
incriment = 1
while $data_skills[incriment] != nil
@prefered_memory[incriment] = @current_memory[incriment]
incriment += 1
end
end
def prefered_memory_cost #this returns the total SP cost of prefered spells
incriment = 1
total = 0
while $data_skills[incriment] != nil
total += $data_skills[incriment].sp_cost * @prefered_memory[incriment]
incriment += 1
end
return total
end
def current_total #this returns the total SP cost of all currently memorized spells
incriment = 1
total = 0
while $data_skills[incriment] != nil
total += $data_skills[incriment].sp_cost * @current_memory[incriment]
incriment += 1
end
return total
end
def set_prefered #sets memory as prefered, and returns total cost
incriment = 1
total = 0
while $data_skills[incriment] != nil
@current_memory[incriment] = @prefered_memory[incriment]
total+= $data_skills[incriment].sp_cost * @current_memory[incriment]
incriment +=1
end
return total
end
def [](line_number)
return @current_memory[line_number]
end
def []=(switch_id, value)
if switch_id <= 5000
@current_memory[switch_id] = value
end
end
def clear_memory #warning! Clears memory WITHOUT restoring maxMP.
incriment = 1
while $data_skills[incriment] != nil
@current_memory[incriment] = 0
incriment += 1
end
end
end
Code:
#==============================================================================
# ** Scene_Vancian
#------------------------------------------------------------------------------
# This Class is the Vancian preparation screen
#Vancian version .8
# Written by Pidey
#==============================================================================
class Scene_Vancian
def initialize(char)
@char = char
if not $game_party.actors[@char].is_vancian
$scene = Scene_Menu.new(6)
return
else
@memory = $game_party.actors[@char].vancian
end
end
def main
@actor = $game_party.actors[@char]
@help_window = Window_Help.new
@status_window = Window_SkillStatus.new(@actor)
@vancian_window = Window_Vancian.new(@actor)
@vancian_window.help_window = @help_window
@aid_window = Window_Vancian_aid.new
@aid_window.visible = false
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
Graphics.freeze
@help_window.dispose
@status_window.dispose
@vancian_window.dispose
end
def update
# Update windows
@help_window.update
@status_window.update
@vancian_window.update
# If skill window is active: call update_skill
if @vancian_window.active
update_vancian
return
end
# If skill target is active: call update_target
if @aid_window.active
update_aid
return
end
end
def update_vancian
unless $game_party.actors[@char].is_vancian
$scene = Scene_Menu.new(6)
end
# Pressing B returns to menu
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Menu.new(6)
return
end
if Input.trigger?(Input::A)
$game_system.se_play($data_system.cursor_se)
@vancian_window.active = false
temp = @vancian_window.index
@aid_window.x = (temp +1) % 2 * 304
@aid_window.visible = true
@aid_window.active = true
@aid_window.index = 0
end
# If C button was pressed
if Input.trigger?(Input::C)
# Get currently selected data on the skill window
@skill = @vancian_window.skill
# If unable to use
if @skill == nil or @actor.sp <@skill.sp_cost
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# Play decision SE
$game_system.se_play($data_system.decision_se)
@memory[@skill.id] +=1
@actor.sp -= @skill.sp_cost #Preparing a vancian spell lowers SP
@actor.maxsp -= @skill.sp_cost
@vancian_window.refresh
@status_window.refresh
return
end
end
def update_aid
@aid_window.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@vancian_window.active = true
@aid_window.visible = false
@aid_window.active = false
return
end
if Input.trigger?(Input::C) #REMOVE
case @aid_window.index
when 0 #set as default
@actor.vancian.set_as_default
$game_system.se_play($data_system.decision_se)
when 1 #clear one of spell
if @actor.vancian[@vancian_window.skill.id] > 0
@actor.vancian[@vancian_window.skill.id] -=1
@actor.maxsp += @vancian_window.skill.sp_cost
@actor.sp += @vancian_window.skill.sp_cost / 4
$game_system.se_play($data_system.decision_se)
else
$game_system.se_play($data_system.cancel_se)
end
when 2 #clear all of spell
if @actor.vancian[@vancian_window.skill.id] > 0
total = @vancian_window.skill.sp_cost * @actor.vancian[@vancian_window.skill.id]
@actor.maxsp += total
@actor.sp += total / 3
$game_system.se_play($data_system.decision_se)
@actor.vancian[@vancian_window.skill.id] = 0
else
$game_system.se_play($data_system.cancel_se)
end
when 3 #clear all memory
total = @actor.vancian.current_total
@actor.maxsp += total
@actor.sp = @actor.sp + total /2
@actor.vancian.clear_memory
$game_system.se_play($data_system.decision_se)
end
@vancian_window.refresh
@status_window.refresh
end
end
end
Code:
# This contains misc things needed for vancian spellcasting.
#Vancian version .8
# Written by Pidey
class Game_Actor < Game_Battler
alias old_setup setup
def setup(actor_id)
@vancian = Vancian.new
if actor_id == 7 or actor_id == 8 #Specify who is vancian here!
@is_vancian = true
else
@is_vancian = false
end
old_setup(actor_id)
end
end
class Game_Battler
attr_reader :is_vancian
attr_reader :vancian
alias recover_all_old recover_all
def recover_all
if is_vancian == true
@maxsp_plus += vancian.current_total
@maxsp_plus = [[@maxsp_plus, -9999].max, 9999].min
vancian.clear_memory
end
@hp = maxhp
@sp = maxsp
if is_vancian == true
if vancian.prefered_memory_cost <= maxsp
t = vancian.set_prefered
@maxsp_plus -= t
@maxsp_plus = [[@maxsp_plus, -9999].max, 9999].min
@sp -= t
end
end
for i in @states.clone
remove_state(i)
end
end
alias skill_can_use_old? skill_can_use?
def skill_can_use?(skill_id)
# If there's not enough SP, or preparation the skill cannot be used.
if self.is_vancian == true
if self.vancian[skill_id] == 0
return false
end
else
if $data_skills[skill_id].sp_cost > self.sp
return false
end
end
# Unusable if incapacitated
if dead?
return false
end
# If silent, only physical skills can be used
if $data_skills[skill_id].atk_f == 0 and self.restriction == 1
return false
end
# Get usable time
occasion = $data_skills[skill_id].occasion
# If in battle
if $game_temp.in_battle
# Usable with [Normal] and [Only Battle]
return (occasion == 0 or occasion == 1)
# If not in battle
else
# Usable with [Normal] and [Only Menu]
return (occasion == 0 or occasion == 2)
end
end
def skill_has_sp?(skill_id)
if $data_skills[skill_id].sp_cost > self.sp
return false
end
return true
end
alias skill_effect_old skill_effect
def skill_effect(user, skill)
self.critical = false
if ((skill.scope == 3 or skill.scope == 4) and self.hp == 0) or
((skill.scope == 5 or skill.scope == 6) and self.hp >= 1)
return false
end
effective = false
effective |= skill.common_event_id > 0
hit = skill.hit
if skill.atk_f > 0
hit *= user.hit / 100
end
hit_result = (rand(100) < hit)
effective |= hit < 100
if hit_result == true
power = skill.power + user.atk * skill.atk_f / 100
if power > 0
power -= self.pdef * skill.pdef_f / 200
power -= self.mdef * skill.mdef_f / 200
power = [power, 0].max
end
rate = 20
rate += (user.str * skill.str_f / 100)
rate += (user.dex * skill.dex_f / 100)
rate += (user.agi * skill.agi_f / 100)
rate += (user.int * skill.int_f / 100)
if user.is_vancian == true #Increases the power of a spell for preparing it repeatedly.
vancian_boost = user.vancian[skill.id] * 0.05 +1
vancian_boost = vancian_boost ** 1.15
else
vancian_boost = 1
end
self.damage = (power * rate / 20) * vancian_boost
self.damage *= elements_correct(skill.element_set)
self.damage /= 100
if self.damage > 0
if self.guarding?
self.damage /= 2
end
end
self.damage = self.damage.round
if skill.variance > 0 and self.damage.abs > 0
amp = [self.damage.abs * skill.variance / 100, 1].max
self.damage += rand(amp+1) + rand(amp+1) - amp
end
eva = 8 * self.agi / user.dex + self.eva
hit = self.damage < 0 ? 100 : 100 - eva * skill.eva_f / 100
hit = self.cant_evade? ? 100 : hit
hit_result = (rand(100) < hit)
effective |= hit < 100
end
if hit_result == true
if skill.power != 0 and skill.atk_f > 0
remove_states_shock
effective = true
end
last_hp = self.hp
self.hp -= self.damage
effective |= self.hp != last_hp
@state_changed = false
effective |= states_plus(skill.plus_state_set)
effective |= states_minus(skill.minus_state_set)
if skill.power == 0
self.damage = ""
unless @state_changed
self.damage = "Miss"
end
end
else
self.damage = "Miss"
end
unless $game_temp.in_battle
self.damage = nil
end
return effective
end
end
class Window_Skill < Window_Selectable
alias draw_item_old draw_item
def draw_item(index)
skill = @data[index]
if @actor.skill_can_use?(skill.id)
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
x = 4 + index % 2 * (288 + 32)
y = index / 2 * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(skill.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
if @actor.is_vancian == true
self.contents.draw_text(x + 28, y, 180, 32, skill.name, 0)
self.contents.draw_text(x + 190, y, 32, 32, skill.sp_cost.to_s, 2)
self.contents.draw_text(x + 226, y, 32, 32, @actor.vancian[skill.id].to_s, 2)
else
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
end
end
end
class Scene_Battle
alias make_skill_action_result_old make_skill_action_result
def make_skill_action_result
@skill = $data_skills[@active_battler.current_action.skill_id]
unless @active_battler.current_action.forcing
unless @active_battler.skill_can_use?(@skill.id)
$game_temp.forcing_battler = nil
@phase4_step = 1
return
end
end
if @active_battler.is_vancian == true
@active_battler.vancian[@skill.id] -= 1
@active_battler.maxsp += @skill.sp_cost
else
@active_battler.sp-= @skill.sp_cost
end
@status_window.refresh
@help_window.set_text(@skill.name, 1)
@animation1_id = @skill.animation1_id
@animation2_id = @skill.animation2_id
@common_event_id = @skill.common_event_id
set_target_battlers(@skill.scope)
for target in @target_battlers
target.skill_effect(@active_battler, @skill)
end
end
end
Instructions:
Simply drop the scripts above main in your game, then near the top of the Misc_Vancian part of the script, modify the one line to mark characters to use the vancian system. Then use $scene = Scene_Vancian.new(character's party position) to enter the preparation screen
Demo:
http://hosted.filefront.com/lordpidey Download Vancian.zip (note that this requires RTP)
http://www.mediafire.com/?ce9c0itcczd
Notes:
This script probably could work with RMVX with a little work. However I do not own a copy of RMVX.