[XP] Battle Arena

Started by ForeverZer0, April 28, 2010, 06:25:03 pm

Previous topic - Next topic

ForeverZer0

April 28, 2010, 06:25:03 pm Last Edit: May 15, 2011, 01:10:26 pm by Baraka
Battle Arena
Authors: ForeverZer0
Version: 1.0
Type: Betting/Competition System
Key Term: Misc System



Introduction

Pretty simple idea, will allow you to easily create a Battle Arena system (very much like the one in Final Fantasy VI). The player can wager items, weapons, and armors and then fight in the arena against different enemies and receive awards if they win. It's a 'winner-take-all' system, where the winner gets to keep their original bet, and the enemy's bet if they are victorious. If they lose they lose their original bet.


Features


  • Can easily configure to most battle systems
  • Fully configurable results for every item, weapon, and armor
  • Allows for 'one-time' rewards for specific bets
  • Simple to setup, and uses only two script calls in game to use
  • Logs wins/losses in game variables for easy access to stats



Screenshots

Register: ShowHide

Fight: ShowHide

Reward: ShowHide



Demo

Demo Link


Script

Here's the script.
Spoiler: ShowHide

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# Battle Arena  
# Author: ForeverZer0
# Date: 4.28.2010
# Version: 1.0
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#
# Explanation:
#
#   Relatively simple idea. Let's the player bet an item, weapon, or armor and
#   then fight against an enemy to receive a different item in return. Very
#   much like the system used in Final Fantasy VI for the SNES. If they win,
#   they get to keep their own item and get the enemy's item, if they lose, they
#   will lose the item they bet.
#
# Feature:
#
#   - Can easily configure to most battle systems
#   - Fully configurable results for any item, weapon, or armor
#   - Allows for 'one-time' rewards for specific bets
#   - Simple to install. After configuration, uses only two script
#     calls in game
#   - All wins/losses are logged in variables for easy access
#
# Instructions:
#
#   - Place script below default scripts and above main
#   - Instructions for each configuration are below
#   - Use these script calls:
#
#  --> $scene = Scene_BattleArena.new  
#
#      - calls the 'registration' scene
#
#  --> $game_temp.arena_battle_call(MAP_ID, X, Y)    
#
#      - after registering, use this where the actual battle will occur
#      - the values in ( ) will be where the player is transfered to after
#        battle. If you do not want them to move, just don't include the ( )
#                                          
#  --> $game_temp.arena_battle = false
#
#      - place this at every exit to your 'arena', otherwise it will cause
#        errors if the player leaves after registering, but before fighting
#
# Author's Notes:
#
#   - Make sure the player cannot save in between registering and fighting.
#     Anytime before or after is fine, but if they register then save and quit,
#     once the game is loaded the 'registraion' will have been lost.
#   - This system only uses one aliased method of the actual battle system. It
#     is basically just a redirect to the Arena Result screen if the flag was
#     present, so you can easily use any battle system you wish.
#   - The only problem you may have is if your battle system is not triggered
#     by the "$game_temp.battle_calling" flag, which most non-ABSs use.
#   - If your game freezes with the "$game_temp.arena_battle = false" script
#     call, it is not a problem with this script. You need to fix your
#     Interpreter command_355. Just look around where you found this script for
#     a fix for it, which you will likely want even if you don't use this system.
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:

module Zer0_CFG
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#                         BEGIN CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:

 WIN_VARIABLE = 1
 LOSS_VARIABLE = 2
 
 # These are the IDs of the variables that the will keep track of your wins
 # and losses.

 NO_BET_ITEMS = []
 NO_BET_WEAPONS = []
 NO_BET_ARMORS = []
 
 # Include IDs of any items/weapon/armors that the player cannot bet.
 # Any item that is "NO_BET" will not even show up as a choice in the window.
 
 ONLY_ONCE_ITEMS = []
 ONLY_ONCE_WEAPONS = []
 ONLY_ONCE_ARMORS = []
 
 # Include IDs of items/weapons/armors that the player will receive the reward
 # for only once. After that, if they re-bet the same item again it will only
 # return the DEFAULT_REWARD as the prize.
 
#-------------------------------------------------------------------------------
#                         BEGIN BATTLE ARENA DATABASE
#-------------------------------------------------------------------------------
#
#   There are 3 sections that will need configured; one each for Items, Weapons,
#   and Armors. Set each section up like this:
#
#         when ID then return [TROOP, REWARD_TYPE, REWARD_ID]
#
#   ID       - The database ID of the Item, Weapon, or Armor that is being bet.
#   TROOP    - The database ID of the troop that will be fought.
#
#   REWARD_TYPE - The 'type' of the reward that will be given if victorious  
#                 0 = Item
#                 1 = Weapon
#                 2 = Armor
#   REWARD_ID   - The ID in the database of the item (depending on type) that
#                 will be received.
#
#   Here's an example:
#
#     when 5 then return [4, 2, 34]  (let's pretend it is in the Item Database)
#
#     This would mean that if the player chose to wager Item with ID(5), they
#     would have to fight Troop with ID(4), and if they won would receive
#     Armor with ID(34). It is an armor because the TYPE is 2.
#
#-------------------------------------------------------------------------------
 
 DEFAULT_REWARD = [1, 0, 1]
 # This will be the configuration for any item/weapon/armor not defined.

 def self.wagers(item)
   if item.is_a?(RPG::Item)
     return DEFAULT_REWARD if $game_system.arena_one_time[0].include?(item.id)
     case item.id
#-------------------------------------------------------------------------------
# * Begin Item Wager Database
#-------------------------------------------------------------------------------
   
     when 1 then return [1, 0, 2]
     when 2 then return [3, 0, 3]
     when 3 then return [5, 0, 4]
     when 4 then return [8, 1, 1]
     when 5 then return [9, 2, 1]
       
#-------------------------------------------------------------------------------
# * End Item Wager Database
#-------------------------------------------------------------------------------
     end
   elsif item.is_a?(RPG::Weapon)
     return DEFAULT_REWARD if $game_system.arena_one_time[1].include?(item.id)
     case item.id
#-------------------------------------------------------------------------------
# * Begin Weapon Wager Database
#-------------------------------------------------------------------------------

     when 1 then return [1, 2, 1]
     when 2 then return [12, 1, 3]
     when 3 then return [20, 1, 5]
     when 4 then return [15, 2, 4]
     when 5 then return [25, 0, 10]
       
#-------------------------------------------------------------------------------
# * End Weapon Wager Database
#-------------------------------------------------------------------------------
     end
   elsif item.is_a?(RPG::Armor)
     return DEFAULT_REWARD if $game_system.arena_one_time[2].include?(item.id)
     case item.id
#-------------------------------------------------------------------------------
# * Begin Armor Wager Database
#-------------------------------------------------------------------------------
     
     when 1 then return [1, 1, 1]
     when 2 then return [5, 2, 3]
     when 3 then return [13, 2, 5]
     when 4 then return [10, 1, 5]
     when 5 then return [21, 2, 10]
       
#-------------------------------------------------------------------------------
# * End Armor Wager Database
#-------------------------------------------------------------------------------

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#                           END CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
     end
   end
   return DEFAULT_REWARD
 end
end

#-------------------------------------------------------------------------------
# ** Game_System
#-------------------------------------------------------------------------------

class Game_System
 
 attr_accessor :arena_one_time   # Retains data on all the ONCE_ONLY bets
 
 alias zer0_arena_once_only_init initialize
 def initialize
   zer0_arena_once_only_init
   @arena_one_time = [[],[],[]]
 end
end

#-------------------------------------------------------------------------------
# ** Game_Temp
#-------------------------------------------------------------------------------

class Game_Temp
 
 attr_accessor :arena_data      # Holds info for bet, reward, battler, etc
 attr_accessor :arena_battle    # Arena Battle flag
 attr_accessor :party_memory    # Memorizes party pre-battle to return after
 
 alias zer0_battle_arena_temp_init initialize
 def initialize
   zer0_battle_arena_temp_init
   @arena_data = []
   @party_memory = []
   @arena_battle = false
 end
 
 def arena_battle_call(map_id=$game_map.map_id, x=$game_player.x , y=$game_player.y)
   @party_memory.clear
   $game_party.actors.each {|actor| @party_memory.push(actor.id)}
   $game_party.actors.clear
   $game_party.add_actor(@arena_data[2])
   @battle_calling = true
   @battle_can_escape = false
   @battle_can_lose = true
   @battle_proc = nil
   @player_new_map_id = map_id
   @player_new_x = x
   @player_new_y = y
   @player_new_direction = 2
   Graphics.freeze
   @player_transferring = true
 end
end

#-------------------------------------------------------------------------------
# ** Scene_BattleArena
#-------------------------------------------------------------------------------

class Scene_BattleArena

 def main
   @help_window = Window_Help.new
   @item_window = Window_ItemBet.new
   @item_window.help_window = @help_window
   @status_window = Window_ArenaStatus.new
   @header1 = Window_Base.new(320, 64, 320, 64)
   @header1.contents = Bitmap.new(288, 32)
   @header1.contents.draw_text(0, 0, 288, 32, 'Which item will you wager?', 1)
   @header2 = Window_Base.new(176, 128, 288, 64)
   @header2.contents = Bitmap.new(256, 32)
   @header2.contents.draw_text(0, 0, 256, 32, 'Who will battle?', 1)
   @header2.z = 5000
   @actor_window = Window_BattlerSelect.new
   @actor_window.active = @actor_window.visible = @header2.visible = false
   Graphics.transition
   loop {Graphics.update; Input.update; update; break if $scene != self}
   [@help_window, @item_window, @status_window, @header1, @header2,
    @actor_window].each {|window| window.dispose}
 end
 
 def update
   [@help_window, @status_window, @item_window,
     @actor_window].each {|window| window.update}
   if @item_window.active
      @status_window.data = @item_window.item
     if Input.trigger?(Input::B)
       $game_system.se_play($data_system.cancel_se)
       $scene = Scene_Map.new
     elsif Input.trigger?(Input::C)
       $game_system.se_play($data_system.decision_se)
       @data = Zer0_CFG.wagers(@item_window.item)
       @actor_window.active = @actor_window.visible = @header2.visible = true
       @item_window.active = false
       return
     end
   elsif @actor_window.active
     if Input.trigger?(Input::B)
       $game_system.se_play($data_system.cancel_se)
       @actor_window.active = @actor_window.visible = @header2.visible = false
       @item_window.active = true
       return
     elsif Input.trigger?(Input::C)
       if $game_party.actors[@actor_window.index].dead?
         $game_system.se_play($data_system.buzzer_se)
         return
       end
       $game_system.se_play($data_system.decision_se)
       if $data_troops[@data[0]] != nil
         $game_temp.battle_troop_id = @data[0]
         $game_temp.arena_data[2] = $game_party.actors[@actor_window.index].id
         $game_temp.arena_data[0] = @item_window.item
         $game_temp.arena_data[1] = case @data[1]
         when 0 then $data_items[@data[2]]
         when 1 then $data_weapons[@data[2]]
         when 2 then $data_armors[@data[2]]
         end
         $game_temp.arena_battle = true
         $scene = Scene_Map.new
       end  
     end
   end
 end
end

#-------------------------------------------------------------------------------
# ** Scene_ArenaResult
#-------------------------------------------------------------------------------

class Scene_ArenaResult
 
 def initialize(battle_result)
   @result = battle_result
 end
 
 def main
   @map = Spriteset_Map.new
   $game_party.actors[0].hp = 1 if @result != 0
   $game_party.actors.clear
   $game_temp.party_memory.each_index {|i|
     $game_party.add_actor($game_temp.party_memory[i])}
   @message_window = Window_Message.new
   Graphics.transition
   bet_item = $game_temp.arena_data[0]
   case bet_item
   when RPG::Item
     if Zer0_CFG::ONLY_ONCE_ITEMS.include?(bet_item.id)
       unless $game_system.arena_one_time[0].include?(bet_item.id)
         $game_system.arena_one_time[0].push(bet_item.id)
       end
     end
   when RPG::Weapon
     if Zer0_CFG::ONLY_ONCE_WEAPONS.include?(bet_item.id)
       unless $game_system.arena_one_time[1].include?(bet_item.id)
         $game_system.arena_one_time[1].push(bet_item.id)
       end
     end
   when RPG::Armor
     if Zer0_CFG::ONLY_ONCE_ARMORS.include?(bet_item.id)
       unless $game_system.arena_one_time[2].include?(bet_item.id)
       $game_system.arena_one_time[2].push(bet_item.id)
       end
     end
   end
   if @result == 0
     Audio.se_play('Audio/SE/060-Cheer01', 80, 100)
     $game_variables[Zer0_CFG::WIN_VARIABLE] += 1
     reward = $game_temp.arena_data[1].name
     id = $game_temp.arena_data[1].id
     case $game_temp.arena_data[1]
     when RPG::Item then $game_party.gain_item(id, 1)
     when RPG::Weapon then $game_party.gain_weapon(id, 1)
     when RPG::Armor then $game_party.gain_armor(id, 1)
     end
     text = "Congratulations!\n" + 'You have won a ' + reward + '!'
   else      
     $game_variables[Zer0_CFG::LOSS_VARIABLE] += 1
     id = $game_temp.arena_data[0].id
     case $game_temp.arena_data[0]
     when RPG::Item then $game_party.lose_item(id, 1)
     when RPG::Weapon then $game_party.lose_weapon(id, 1)
     when RPG::Armor then $game_party.lose_armor(id, 1)
     end
     text = 'Lost...'
   end
   $game_temp.message_text = text
   loop {Graphics.update; Input.update; update; break if $scene != self}
   $game_temp.arena_battle = false
   $game_temp.arena_data.clear
   $scene = Scene_Map.new
   [@map, @message_window].each {|sprite| sprite.dispose}
 end
 
 def update
   [@map, @message_window].each {|sprite| sprite.update}
   if Input.trigger?(Input::C)
     $scene = Scene_Map.new
   end
 end
end

#-------------------------------------------------------------------------------
# ** Scene_Battle
#-------------------------------------------------------------------------------

class Scene_Battle
 
 alias zer0_battle_arena_result battle_end
 def battle_end(result)
   # This will just redirect the scene to the Arena Result screen instead
   # of Scene_Map if the arena flag is present
   zer0_battle_arena_result(result)
   if $game_temp.arena_battle
     $scene = Scene_ArenaResult.new(result)
   end
 end
end

#-------------------------------------------------------------------------------
# ** Window_ArenaStatus
#-------------------------------------------------------------------------------

class Window_ArenaStatus < Window_Base
 
 def initialize
   super(320, 128, 320, 352)
   self.contents = Bitmap.new(width - 32, height - 32)
   @data = nil
   refresh
 end
 
 def refresh
   self.contents.clear
   return if @data == nil
   @data = Zer0_CFG.wagers(@data)
   self.contents.font.color = system_color
   self.contents.draw_text(4, 0, 288, 32, 'Enemies:')
   self.contents.draw_text(4, 256, 288, 32, 'Reward:')
   self.contents.font.color = normal_color
   member = $data_troops[@data[0]].members
   names = []
   member.each_index {|i| names[i] = $data_enemies[member[i].enemy_id].name
     y = (i * 32) + 32
     self.contents.draw_text(4, y, 288, 32, names[i]) if y < 256}  
   case @data[1]
   when 0
     reward = $data_items[@data[2]].name
     icon = $data_items[@data[2]].icon_name
   when 1
     reward = $data_weapons[@data[2]].name
     icon = $data_weapons[@data[2]].icon_name
   when 2
     reward = $data_armors[@data[2]].name
     icon = $data_armors[@data[2]].icon_name
   end
   self.contents.draw_text(32, 288, 288, 32, reward)
   rect = Rect.new(x, y, self.width - 32, 32)
   self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
   self.contents.blt(4, 292, RPG::Cache.icon(icon), Rect.new(0, 0, 24, 24))
 end
 
 def data=(data)
   if @data != data
     @data = data
     refresh
   end
 end
end

#-------------------------------------------------------------------------------
# ** Window_ItemBet
#-------------------------------------------------------------------------------

class Window_ItemBet < Window_Selectable

 def initialize
   super(0, 64, 320, 416)
   @column_max, self.index = 1, 0
   refresh
 end

 def item
   return @data[self.index]
 end

 def refresh
   if self.contents != nil
     self.contents.dispose
     self.contents = nil
   end
   @data = []
   (1...$data_items.size).each {|i|
     if $game_party.item_number(i) > 0
       unless Zer0_CFG::NO_BET_ITEMS.include?(i)
         @data.push($data_items[i])
       end
     end
   }
   (1...$data_weapons.size).each {|i|
     if $game_party.weapon_number(i) > 0
       unless Zer0_CFG::NO_BET_WEAPONS.include?(i)
         @data.push($data_weapons[i])
       end
     end
   }
   (1...$data_armors.size).each {|i|
     if $game_party.armor_number(i) > 0
       unless Zer0_CFG::NO_BET_ARMORS.include?(i)
         @data.push($data_armors[i])
       end
     end
   }
   @item_max = @data.size
   if @item_max > 0
     self.contents = Bitmap.new(width - 32, row_max * 32)
     (0...@item_max).each {|i| draw_item(i)}
   end
 end

 def draw_item(index)
   item = @data[index]
   number = case item
   when RPG::Item then $game_party.item_number(item.id)
   when RPG::Weapon then $game_party.weapon_number(item.id)
   when RPG::Armor then $game_party.armor_number(item.id)
   end
   x = 4
   y = index * 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(item.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, 212, 32, item.name, 0)
   self.contents.draw_text(x + 240, y, 16, 32, ':', 1)
   self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2)
 end

 def update_help
   @help_window.set_text(self.item == nil ? '' : self.item.description)
 end
end

#-------------------------------------------------------------------------------
# ** Window_BattlerSelect
#-------------------------------------------------------------------------------

class Window_BattlerSelect < Window_Selectable
 
 def initialize
   w = ($game_party.actors.size * 64) + 32
   x = (640 - w) / 2
   super(x, 192, w, 96)
   self.contents = Bitmap.new(width - 32, height - 32)
   @row_max, self.index, self.z = 1, 0, 5000
   @item_max = @column_max = $game_party.actors.size
   refresh
 end
 
 def refresh
   $game_party.actors.each_index {|i|
   x = 32 + i * 64
   self.draw_actor_graphic($game_party.actors[i], x, 64)}
 end
 
 def update_cursor_rect
   cursor_width = 48
   x = @index * 64 + 8
   y = @index / @column_max * 32 - self.oy
   self.cursor_rect.set(x, y, cursor_width, 64)
 end
end



Instructions

In the script.


Compatibility

No known compatibility issues.


Credits and Thanks


  • ForeverZer0, for writing the script.



Author's Notes

Download the demo first if you have any questions, they may be answered in there. I have included examples and a little more in-depth explanations than can be found in just the script. If you find any bugs or still have issues after seeing the demo, be sure to let me know and I'll do my best to help/fix it.

Hope you enjoy!
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Nadim13

Ok, excellent work as always. ;)

All your script are simple but very very good.
Maybe I'll use this one for my game, I have to decide. However, good work!