Suikoden Dueling SystemVersion: 0.9IntroductionThis script mimics the dueling system in the Suidoken games. Basically, it is like a slightly enhanced version of Rock Paper Scissors.
Features- Solo battles
- Strategy is somewhat required
- easy to use
- Simulates the dueling system of Suikoden
ScreenshotsDemoNo Demo necessary, I shouldn't think.
ScriptPlace above main
[/list]
#==============================================================================
# Suikoden Dueling System (SDS) v 0.9 (Bug Testing Edition)
# Author: modern algebra
# Date: June 2, 2007
# Thanks: Ikzai and dollmage, for the request and specifications
#------------------------------------------------------------------------------
# Instructions:
#
# Place in a new script above Main
#
# It is very easy to use, just place this in a call script:
#
# $scene = Scene_Suikoden_Duel.new (XXX)
#
# where XXX is the ID of the enemy you wish to duel. Keep in mind that unlike
# the event command to run a battle, everything below this command in the event
# will not run.
#==============================================================================
# ** Sprite_SuikodenBattler
#------------------------------------------------------------------------------
# This class is used to display the battlers and controls animation. Basically
# just a shortened version of Sprite_Battler
#==============================================================================
class Sprite_SuikodenBattler < RPG::Sprite
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :battler # battler
#--------------------------------------------------------------------------
# * Object Initialization
# viewport : viewport
# battler : battler (Game_Battler)
#--------------------------------------------------------------------------
def initialize(viewport, battler = nil)
super(viewport)
@battler = battler
@battler_visible = false
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
def dispose
if self.bitmap != nil
self.bitmap.dispose
end
super
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# If battler is nil
if @battler == nil
self.bitmap = nil
loop_animation(nil)
return
end
# If file name or hue are different than current ones
if @battler.battler_name != @battler_name or @battler.battler_hue != @battler_hue
# Get and set bitmap
@battler_name = @battler.battler_name
@battler_hue = @battler.battler_hue
self.bitmap = RPG::Cache.battler(@battler_name, @battler_hue)
@width = bitmap.width
@height = bitmap.height
self.ox = @width / 2
self.oy = @height
end
end
end
#==============================================================================
# ** Window_SuikodenHelp
#------------------------------------------------------------------------------
# This class displays the actions taken by the enemy and the actor
#==============================================================================
class Window_SuikodenHelp < Window_Base
def initialize (actor_choice, enemy_choice)
super(200, 0, 240, 96)
self.contents = Bitmap.new(width - 32, height - 32)
@display = [actor_choice, enemy_choice]
self.z=200
self.opacity = 160
refresh
end
def refresh
self.contents.draw_text(0,0,120,32, $game_party.actors[0].name + ":")
self.contents.draw_text(0,32,120,32, $data_enemies[$duel_enemy_id].name + ":")
for i in 0...2
case @display[i]
when 0
self.contents.draw_text(120,i*32,80,32, "Attack")
when 1
self.contents.draw_text(120,i*32,80,32, "Wild Attack")
when 2
self.contents.draw_text(120,i*32,80,32, "Defend")
end
end
end
def dispose
if self.contents != nil
self.contents.clear
end
super
end
end
#==============================================================================
# ** Window_SuikodenBattleStatus
#------------------------------------------------------------------------------
# This window displays the status of all party members on the battle screen.
# Basically a carbon copy of Window_BattleStatus, with a few minor modifications
#==============================================================================
class Window_SuikodenBattleStatus < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 320, 640, 160)
self.contents = Bitmap.new(width - 32, height - 32)
@level_up_flags = [false]
refresh
end
#--------------------------------------------------------------------------
# * Set Level Up Flag
# actor_index : actor index
#--------------------------------------------------------------------------
def level_up(actor_index)
@level_up_flags[actor_index] = true
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
actor = $game_party.actors[0]
actor_x = 244
draw_actor_name(actor, actor_x, 0)
draw_actor_hp(actor, actor_x, 32, 120)
draw_actor_sp(actor, actor_x, 64, 120)
if @level_up_flags[0]
self.contents.font.color = normal_color
self.contents.draw_text(actor_x, 96, 120, 32, "LEVEL UP!")
else
draw_actor_state(actor, actor_x, 96)
end
end
def dispose
if self.contents != nil
self.contents.clear
end
super
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Slightly lower opacity level during main phase
if $game_temp.battle_main_phase
self.contents_opacity -= 4 if self.contents_opacity > 191
else
self.contents_opacity += 4 if self.contents_opacity < 255
end
end
end
#==============================================================================
# ** Window_Damage
#------------------------------------------------------------------------------
# This class displays damage
#==============================================================================
class Window_Damage < Window_Base
def initialize (damage, decision1, decision2)
super (240, 100, 160, 64)
self.contents = Bitmap.new(width - 32, height - 32)
@damage = damage
@decision = [decision1, decision2]
self.z=500
self.opacity = 0
refresh
end
def refresh
self.contents.font.color = Color.new(255, 75, 75, 255)
case @decision[0]
when 0
case @decision[1]
when 0
self.contents.draw_text (0,0,160,32,@damage.to_s)
when 1
self.contents.draw_text (0,0,160,32,@damage.to_s)
when 2
end
when 1
case @decision[1]
when 0
self.contents.draw_text (0,0,160,32,"Attack Nullified!")
when 1
self.contents.draw_text (0,0,160,32,@damage.to_s)
when 2
self.contents.draw_text (0,0,160,32,@damage.to_s)
end
when 2
case @decision[1]
when 0
self.contents.draw_text (0,0,160,32, @damage.to_s)
when 1
self.contents.draw_text (0,0,160,32,"Dodge and Counter!")
when 2
end
end
end
def dispose
if self.contents != nil
self.contents.clear
end
super
end
end
#==============================================================================
# ** Scene_Suikoden_Duel
#------------------------------------------------------------------------------
# The main processing scene for the battle system
#==============================================================================
class Scene_Suikoden_Duel
def initialize (enemy)
$duel_enemy_id = enemy
@enemy_hp = $data_enemies[enemy].maxhp
@wait = 0
@wait3 = 0
@viewport_actor = Viewport.new(240,240,160,240)
@viewport_enemy = Viewport.new(240,60,160,240)
end
def main
$game_temp.battleback_name = $game_map.battleback_name
$game_temp.in_battle = true
s1 = "Attack"
s2 = "Wild Attack"
s3 = "Defend"
@actor_command_window = Window_Command.new(160, [s1, s2, s3])
@actor_command_window.x = 240
@actor_command_window.y = 160
@actor_command_window.z = 260
@actor_command_window.back_opacity = 160
@actor_command_window.active = false
@actor_command_window.visible = false
if @status_window == nil
@status_window = Window_SuikodenBattleStatus.new
@status_window.z=255
end
if @actor_window == nil
@actor_window = Sprite_SuikodenBattler.new(@viewport1, $game_party.actors[0])
@enemy_window = Sprite_SuikodenBattler.new(@viewport1, $data_enemies[$duel_enemy_id])
end
@battleback = Sprite.new(Viewport.new(0,0,640, 480))
if @battleback.bitmap != nil
@battleback.bitmap.clear
end
@battleback.bitmap = RPG::Cache.battleback($game_map.battleback_name)
@battleback.z=0
# Initialize wait count
@wait_count = 0
# Execute transition
if $data_system.battle_transition == ""
Graphics.transition(20)
else
Graphics.transition(40, "Graphics/Transitions/" +
$data_system.battle_transition)
end
# Main loop
loop do
@actor_window.battler = $game_party.actors[0]
@actor_window.update
@actor_window.x = 320
@actor_window.y = 430
@actor_window.z = 255
@enemy_window.battler = $data_enemies[$duel_enemy_id]
@enemy_window.update
@enemy_window.x = 320
@enemy_window.y = 210
@enemy_window.z = 100
if @turn_off_command != true
@actor_command_window.active = true
@actor_command_window.visible = true
end
# Update game screen
Graphics.update
# Update input information
Input.update
# update_battle_phase
if @battle_over != true
if @wait == 0
duel_phase_update
else
attack_calculations
end
else
update_battle_win
end
# Abort loop if screen is changed
if $scene != self
break
end
end
# Refresh map
$game_map.refresh
# Prepare for transition
Graphics.freeze
# Dispose of windows
windows = [@status_window, @actor_window, @enemy_window, @result_window,
@battleback, @help_window, @actor_damage_window, @enemy_damage_window, @actor_command_window]
for i in 0...windows.size
windows[i].dispose
end
end
def duel_phase_update
@actor_command_window.update
if Input.trigger?(Input::C)
# Branch by command window cursor position
case @actor_command_window.index
when 0 # attack
# Play decision SE
$game_system.se_play($data_system.decision_se)
@actor_decision = @actor_command_window.index
duel_compare
when 1 # wild attack
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Set actor choice
@actor_decision = @actor_command_window.index
duel_compare
when 2 # defend
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to status screen
@actor_decision = @actor_command_window.index
duel_compare
end
end
end
def duel_compare
@actor_command_window.active = false
@actor_command_window.visible = false
@turn_off_command = true
@enemy_decision = rand(100)
if @enemy_decision < 50
@enemy_decision = 0
elsif @enemy_decision < 75
@enemy_decision = 1
else
@enemy_decision = 2
end
case @actor_decision
when 0
case @enemy_decision
when 0
@actor_damage_modifier = 1
@enemy_damage_modifier = 1
@enemy_accuracy = true
@actor_accuracy = true
when 1
@actor_damage_modifier = 0
@enemy_damage_modifier = 1.5
@enemy_accuracy = true
when 2
@actor_damage_modifier = 0.5
@enemy_damage_modifier = 0
@actor_accuracy = true
@enemy_accuracy = false
end
when 1
case @enemy_decision
when 0
@actor_damage_modifier = 1.5
@enemy_damage_modifier = 0
@actor_accuracy = true
@enemy_accuracy = false
when 1
@actor_damage_modifier = 1.5
@enemy_damage_modifier = 1.5
@actor_accuracy = true
@enemy_accuracy = true
when 2
@actor_damage_modifier = 0
@enemy_damage_modifier = 1.5
@actor_accuracy = false
@enemy_accuracy = true
end
when 2
case @enemy_decision
when 0
@actor_damage_modifier = 0
@enemy_damage_modifier = 0.5
@enemy_accuracy = true
@actor_accuracy = false
when 1
@actor_damage_modifier = 1.5
@enemy_damage_modifier = 0
@enemy_accuracy = false
@actor_accuracy = true
when 2
@actor_damage_modifier = 0
@enemy_damage_modifier = 0
@enemy_accuracy = false
@actor_accuracy = false
end
end
attack_calculations
end
def attack_calculations
if @wait == 0
@help_window = Window_SuikodenHelp.new (@actor_decision,@enemy_decision)
actor = $game_actors[$game_party.actors[0].id]
enemy = $data_enemies[$duel_enemy_id]
@actor_damage = (@actor_damage_modifier*(actor.atk - (enemy.pdef/2) - 10 + rand(actor.str / 10))).round
if @actor_damage < 0
@actor_damage = 0
end
enemy_damage = (@enemy_damage_modifier*(enemy.atk - (actor.pdef/2)- 10 + rand(enemy.str / 10))).round
if enemy_damage < 0
enemy_damage = 0
end
@enemy_hp -= @actor_damage
$game_actors[$game_party.actors[0].id].hp -= enemy_damage
@wait = 80
animation_enemy = $data_enemies[$duel_enemy_id].animation2_id
@actor_damage_window = Window_Damage.new (enemy_damage, @actor_decision, @enemy_decision)
@actor_damage_window.y = 280
@status_window.refresh
unless @enemy_damage_modifier == 0
@actor_window.animation ($data_animations[animation_enemy], @enemy_accuracy)
end
return
elsif @wait !=1
@wait-=1
if (@wait%3) == 0
if @wait >= 40
@actor_damage_window.y -= 1
else
@enemy_damage_window.y -= 1
end
end
if @wait == 40
@enemy_damage_window = Window_Damage.new (@actor_damage, @enemy_decision, @actor_decision)
@actor_damage_window.visible = false
unless @actor_damage_modifier == 0
animation_actor = $data_weapons[$game_actors[$game_party.actors[0].id].weapon_id].animation2_id
@enemy_window.animation ($data_animations[animation_actor], @actor_accuracy)
end
end
return
else
@wait = 0
@enemy_damage_window.visible = false
@help_window.visible = false
if $game_actors[$game_party.actors[0].id].hp <=0
@actor_window.collapse
$game_temp.gameover = true
elsif @enemy_hp <=0
@enemy_window.collapse
battle_win
else
@turn_off_command = false
return
end
end
end
def battle_win
enemy = $data_enemies[$duel_enemy_id]
exp = enemy.exp
gold = enemy.gold
# Determine if treasure appears
if rand(100) < enemy.treasure_prob
if enemy.item_id > 0
treasures.push($data_items[enemy.item_id])
end
if enemy.weapon_id > 0
treasures.push($data_weapons[enemy.weapon_id])
end
if enemy.armor_id > 0
treasures.push($data_armors[enemy.armor_id])
end
end
# Treasure is limited to a maximum of 6 items
treasures = []
# Obtaining EXP
for i in 0...$game_party.actors.size
actor = $game_party.actors[i]
if actor.cant_get_exp? == false
last_level = actor.level
actor.exp += exp
if actor.level > last_level
@status_window.level_up(i)
end
end
end
# Obtaining gold
$game_party.gain_gold(gold)
# Obtaining treasure
for item in treasures
case item
when RPG::Item
$game_party.gain_item(item.id, 1)
when RPG::Weapon
$game_party.gain_weapon(item.id, 1)
when RPG::Armor
$game_party.gain_armor(item.id, 1)
end
end
# Make battle result window
@result_window = Window_BattleResult.new(exp, gold, treasures)
@result_window.z = 2000
$game_system.me_play($data_system.battle_end_me)
@battle_over = true
@battle_end_wait_count = 100
update_battle_win
end
def update_battle_win
@result_window.refresh
if @battle_end_wait_count > 0
@battle_end_wait_count -= 1
else
@result_window.visible = true
if Input.trigger?(Input::C) or Input.trigger?(Input::B)
$scene = Scene_Map.new
end
end
end
end
InstructionsLocated in script
CompatibilityNo known compatibility issues. There shouldn’t be any, since it does not overwrite any classes.
Credits and Thanks- Credit: modern algebra
- Thanks: Ikzai and dollmage
Author's NotesFirst script I wrote entirely from scratch. Well, I borrowed a few classes, but the rest was from scratch
. Notice how I separate many methods needlessly. Anyway, enjoy. This is only v. 0.9 because I haver never played Suikoden before, and so I do not know if I missed some of the functionality of it or not. Please give me suggestions for improvement.
Planned future versions: make it display in the same style as ccoa's side-view battle system.