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
Screenshots(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg115.imageshack.us%2Fimg115%2F3672%2Fduelscreen1ky8.jpg&hash=ddc7c56da6467bad5a7b723aad3df40876972128)
(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg101.imageshack.us%2Fimg101%2F1659%2Fduelscreen2hn6.jpg&hash=27abd34122372da360642b994391a21d4297d72b)
DemoNo 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 :P. 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.
wow you finally did it =) :tpg:
oh yeah on the wild attack you should make the enemy flash or something that would be cool ^_^ when a hit land. good job dude =)
cant wa8 till this is side view. style :D, or you could incorporate this coding like a enchancement to ccoas or minkoff cbs.
(sorry bout the multiple modify)
Wait, so are you using Minkoff's or ccoa's?
How difficult would this to be to merge with a TBS system? Such as Nick's Fire Emblem CBS?
I'm not a major fan of the default battle system look.
@dollmage - animation shows for every hit that does damage already. The screenshot was just taken at a bad time.
@Shaifs - depends on the TBS I guess, but it would add a lot of unnecessary complications to the system, like range weapons and skills and stuff. Unless you mean that instead of the attack, skills, range, etc... options you normally have with TBSes when you target an enemy, it just has the three options of this system. It would just be a matter of switching the attack algorithm for the AI and the selection algorithm for the player, and the difficulty would depend on how deeply enmeshed those are in the system. I would say that a regular TBS is better than this type of thing anyway though :-X
If you really want it, then I might be able to do it, but it'll be a while. I have a few other scripts to do before even modifying this one to be SVBS style, not to mention I am going on a vacation for two weeks soon, and I won't be doing any RM during that time. So, if you really want it, the best you can expect from me is about a month or two from now, and you'd probably have to remind me. You could also ask the creator of the TBS to make it, and it'd probably be easier for him. But, if I remember correctly, the TBS is not finished, and so he probably has his hands full. Your best bet if you want it sooner than I can make it is to post a request for someone to merge the two. If you do make a request topic, remember to post both scripts and give exact specifications for what you want. And you would probably be more likely to get a response if you post it here, at CA, and at .org. Another option is Blizzard at chaosproject.co.nr. He's both a really good scripter, and generous, so he also might be able to take the request.
this is the TBS I'm talking about
http://www.creationasylum.net/index.php?showtopic=14331
and if you played Yggdrasil Union they have joint attacks.
For example
- O
XO
O = Player
X = Opponent
- = Empty space
The two player characters who are alligned next to one another could do a joint physical attack. Is something like that too complex to use with this script?
Hmm, yeah. I was just testing out Nick's TBS system, and wondering the same thing. (It's a really well done battle system, that I'm seriously considering.) Any chance you could make the two compatible?
Either way, this is awesome. Thank you so much!
if he aliases whatever classes he modifies, then it should be compatable with mink/ccoa's side views
as for nick's TBS, I dunno, it might require a merge
nice script BTW modern
great job, thumbs up :)
Technically, it is compatible already, in that it shouldn't screw anything up. But it won't be side-view, since I wrote my own sprite class for this (well, not really, I just took out a bunch of stuff from the original Sprite_Battler). When I do the edit, I believe that all I will have to do is grab her sprite class and maybe modify it a little bit. The edit shouldn't be any harder than that, unless her animation is in a different class. I haven't looked at her script yet, but once I do I'll get a better idea of what needs to be done.
thanks oh and i have her rtab version well not realy made by her coz she didnt finish it
someone upgraded it and name it ccoas cbs. ex
Hi
im having a problem with this script
when using cogwheel
Yes, well they are two different and battle systems and, in terms of gameplay, completely incompatible. That being said, I am not sure why they are incompatible in terms of scripts - it probably has to do with Game_Battler. But, cogwheel has a thousand incarnations, and I can't diagnose the problem precisely without knowing which one of those you are using. In any case, this is a very old script and I'd prefer not to work on it. If you really want it, please link me to the battle system you are using, or at the very least tell me what the error message is (in fact, do both).
ok thanks
and i already fixed it
i used plug and play cogwheel