The RPG Maker Resource Kit

RMRK RPG Maker Creation => XP => XP Scripts Database => Topic started by: modern algebra on June 03, 2007, 04:51:09 PM

Title: Suikoden Dueling System v. 0.9
Post by: modern algebra on June 03, 2007, 04:51:09 PM
Suikoden Dueling System
Version: 0.9

Introduction

This script mimics the dueling system in the Suidoken games. Basically, it is like a slightly enhanced version of Rock Paper Scissors.

Features


Screenshots

(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg115.imageshack.us%2Fimg115%2F3672%2Fduelscreen1ky8.jpg&hash=8fd7fd27274b33ba7dba700cbfaac76ac0f569c7)

(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg101.imageshack.us%2Fimg101%2F1659%2Fduelscreen2hn6.jpg&hash=d41cd043039cb311e365bcbdc4449e1f3a6851f0)

Demo

No Demo necessary, I shouldn't think.

Script

Place above main
[/list]
Code: [Select]
#==============================================================================
#  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

Instructions

Located in script

Compatibility

No known compatibility issues. There shouldn’t be any, since it does not overwrite any classes.

Credits and Thanks


Author's Notes

First 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.
Title: Re: Suikoden Dueling System v. 0.9
Post by: dollmage on June 04, 2007, 01:24:12 PM
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)
Title: Re: Suikoden Dueling System v. 0.9
Post by: modern algebra on June 04, 2007, 03:28:41 PM
Wait, so are you using Minkoff's or ccoa's?
Title: Re: Suikoden Dueling System v. 0.9
Post by: Shaifs on June 04, 2007, 03:46:48 PM
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.
Title: Re: Suikoden Dueling System v. 0.9
Post by: modern algebra on June 04, 2007, 04:48:46 PM
@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.
Title: Re: Suikoden Dueling System v. 0.9
Post by: Shaifs on June 04, 2007, 05:30:03 PM
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?
Title: Re: Suikoden Dueling System v. 0.9
Post by: Ikzai on June 04, 2007, 05:40:02 PM
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!
Title: Re: Suikoden Dueling System v. 0.9
Post by: tSwitch on June 05, 2007, 02:36:58 AM
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 :)
Title: Re: Suikoden Dueling System v. 0.9
Post by: modern algebra on June 05, 2007, 03:05:33 AM
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.
Title: Re: Suikoden Dueling System v. 0.9
Post by: dollmage on June 05, 2007, 03:24:48 PM
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
Title: Re: Suikoden Dueling System v. 0.9
Post by: denzel on June 06, 2008, 04:28:03 PM
Hi
im having a problem with this script
when using cogwheel
Title: Re: Suikoden Dueling System v. 0.9
Post by: modern algebra on June 07, 2008, 01:18:15 AM
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).
Title: Re: Suikoden Dueling System v. 0.9
Post by: denzel on June 07, 2008, 03:36:12 AM
ok thanks
and i already fixed it
i used plug and play cogwheel