#=============================================================================== # "Duel" mini-game # Based on the Duel minigame by Alael #=============================================================================== class DuelWindow < Window_AdvancedTextPokemon attr_reader :hp attr_reader :name attr_reader :is_enemy PLAYER_TEXT_BASE = Color.new(48, 80, 200) # Blue PLAYER_TEXT_SHADOW = Color.new(160, 192, 240) ENEMY_TEXT_BASE = Color.new(224, 8, 8) # Red ENEMY_TEXT_SHADOW = Color.new(248, 184, 112) HP_TEXT_BASE = Color.new(32, 152, 8) # Green HP_TEXT_SHADOW = Color.new(144, 240, 144) def initialize(name, is_enemy) @hp = 10 @name = name @is_enemy = is_enemy super() self.width = 160 self.height = 96 duel_refresh end def hp=(value) @hp = value duel_refresh end def name=(value) @name = value duel_refresh end def is_enemy=(value) @is_enemy = value duel_refresh end def duel_refresh if @is_enemy name_tag = shadowc3tag(ENEMY_TEXT_BASE, ENEMY_TEXT_SHADOW) else name_tag = shadowc3tag(PLAYER_TEXT_BASE, PLAYER_TEXT_SHADOW) end hp_tag = shadowc3tag(HP_TEXT_BASE, HP_TEXT_SHADOW) self.text = name_tag + fmtEscape(@name) + "\n" + hp_tag + _INTL("HP: {1}", @hp) end end #=============================================================================== # #=============================================================================== class PokemonDuel def pbStartDuel(opponent, event) @event = event @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport.z = 99999 @sprites = {} @sprites["player"] = IconSprite.new(-160, 96, @viewport) @sprites["player"].setBitmap(GameData::TrainerType.player_front_sprite_filename($player.trainer_type)) @sprites["opponent"] = IconSprite.new(Graphics.width + 32, 96, @viewport) @sprites["opponent"].setBitmap(GameData::TrainerType.front_sprite_filename(opponent.trainer_type)) @sprites["playerwindow"] = DuelWindow.new($player.name, false) @sprites["playerwindow"].x = -@sprites["playerwindow"].width @sprites["playerwindow"].viewport = @viewport @sprites["opponentwindow"] = DuelWindow.new(opponent.name, true) @sprites["opponentwindow"].x = Graphics.width @sprites["opponentwindow"].viewport = @viewport pbWait(0.5) pbWait(0.5) do |delta_t| @sprites["player"].x = lerp(-160, 0, 0.4, delta_t) @sprites["playerwindow"].x = lerp(-@sprites["playerwindow"].width, 160 - @sprites["playerwindow"].width, 0.4, delta_t) @sprites["opponent"].x = lerp(Graphics.width + 32, Graphics.width - 128, 0.4, delta_t) @sprites["opponentwindow"].x = lerp(Graphics.width, Graphics.width - 160, 0.4, delta_t) end @sprites["player"].x = 0 @sprites["playerwindow"].x = 160 - @sprites["playerwindow"].width @sprites["opponent"].x = Graphics.width - 128 @sprites["opponentwindow"].x = Graphics.width - 160 @oldmovespeed = $game_player.move_speed @oldeventspeed = event.move_speed pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::DIRECTION_FIX_ON]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::DIRECTION_FIX_ON]) pbWait(0.75) end def pbDuel(opponent, event, speeches) pbStartDuel(opponent, event) @hp = [10, 10] @special = [false, false] decision = nil loop do @hp[0] = 0 if @hp[0] < 0 @hp[1] = 0 if @hp[1] < 0 pbRefresh if @hp[0] <= 0 decision = false break elsif @hp[1] <= 0 decision = true break end action = 0 scores = [3, 4, 4, 2] choices = (@special[1]) ? 3 : 4 scores[3] = 0 if @special[1] total = scores[0] + scores[1] + scores[2] + scores[3] if total <= 0 action = rand(choices) else num = rand(total) cumtotal = 0 4.times do |i| cumtotal += scores[i] if num < cumtotal action = i break end end end @special[1] = true if action == 3 pbMessage(_INTL("{1}: {2}", opponent.name, speeches[(action * 3) + rand(3)])) list = [ _INTL("DEFEND"), _INTL("PRECISE ATTACK"), _INTL("FIERCE ATTACK") ] list.push(_INTL("SPECIAL ATTACK")) if !@special[0] command = pbMessage(_INTL("Choose a command."), list, 0) @special[0] = true if command == 3 if action == 0 && command == 0 pbMoveRoute($game_player, [PBMoveRoute::SCRIPT_ASYNC, "moveRight90", PBMoveRoute::SCRIPT_ASYNC, "moveLeft90", PBMoveRoute::SCRIPT_ASYNC, "moveLeft90", PBMoveRoute::SCRIPT_ASYNC, "moveRight90"]) pbMoveRoute(event, [PBMoveRoute::SCRIPT_ASYNC, "moveLeft90", PBMoveRoute::SCRIPT_ASYNC, "moveRight90", PBMoveRoute::SCRIPT_ASYNC, "moveRight90", PBMoveRoute::SCRIPT_ASYNC, "moveLeft90"]) pbWait(0.5) pbMessage(_INTL("You study each other's movements...")) elsif action == 0 && command == 1 pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::FORWARD]) pbWait(0.4) pbShake(9, 9, 8) pbFlashScreens(false, true) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) @hp[1] -= 1 pbMessage(_INTL("Your attack was not blocked!")) elsif action == 0 && command == 2 pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpForward"]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::BACKWARD]) pbWait(1.0) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::FORWARD]) pbMessage(_INTL("Your attack was evaded!")) elsif [0, 1, 2].include?(action) && command == 3 pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpForward"]) pbWait(0.4) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 5, PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 2]) pbWait(0.5) pbShake(9, 9, 8) pbFlashScreens(false, true) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::FORWARD]) @hp[1] -= 3 pbMessage(_INTL("You pierce through the opponent's defenses!")) elsif action == 1 && command == 0 pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::FORWARD]) pbWait(0.4) pbShake(9, 9, 8) pbFlashScreens(true, false) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) @hp[0] -= 1 pbMessage(_INTL("You fail to block the opponent's attack!")) elsif action == 1 && command == 1 pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::FORWARD]) pbWait(0.6) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::FORWARD]) pbWait(0.6) pbMoveRoute(event, [PBMoveRoute::BACKWARD]) pbMoveRoute($game_player, [PBMoveRoute::FORWARD]) pbWait(0.6) pbMoveRoute($game_player, [PBMoveRoute::BACKWARD]) pbMessage(_INTL("You cross blades with the opponent!")) elsif (action == 1 && command == 2) || (action == 2 && command == 1) || (action == 2 && command == 2) pbMoveRoute($game_player, [PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpForward"]) pbWait(0.8) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::FORWARD]) pbWait(0.9) pbShake(9, 9, 8) pbFlashScreens(true, true) pbMoveRoute($game_player, [PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 2]) pbMoveRoute(event, [PBMoveRoute::BACKWARD, PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 2]) pbWait(1.0) pbMoveRoute(event, [PBMoveRoute::FORWARD]) pbMoveRoute($game_player, [PBMoveRoute::FORWARD]) @hp[0] -= action # Enemy action @hp[1] -= command # Player command pbMessage(_INTL("You hit each other!")) elsif action == 2 && command == 0 pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::FORWARD]) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpBackward"]) pbWait(1.0) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::FORWARD]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) pbMessage(_INTL("You evade the opponent's attack!")) elsif action == 3 && [0, 1, 2].include?(command) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpForward"]) pbWait(0.4) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 5, PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 2]) pbWait(0.5) pbShake(9, 9, 8) pbFlashScreens(true, false) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::FORWARD]) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 2, PBMoveRoute::BACKWARD]) @hp[0] -= 3 pbMessage(_INTL("The opponent pierces through your defenses!")) elsif action == 3 && command == 3 pbMoveRoute($game_player, [PBMoveRoute::BACKWARD]) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpForward"]) pbMoveRoute(event, [PBMoveRoute::WAIT, 15, PBMoveRoute::CHANGE_SPEED, 4, PBMoveRoute::SCRIPT_ASYNC, "jumpForward"]) pbWait(1.0) pbMoveRoute(event, [PBMoveRoute::CHANGE_SPEED, 5, PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 2]) pbMoveRoute($game_player, [PBMoveRoute::CHANGE_SPEED, 5, PBMoveRoute::BACKWARD, PBMoveRoute::CHANGE_SPEED, 2]) pbShake(9, 9, 8) pbFlash(Color.new(255, 255, 255, 255), 20) pbFlashScreens(true, true) pbMoveRoute($game_player, [PBMoveRoute::FORWARD]) @hp[0] -= 4 @hp[1] -= 4 pbMessage(_INTL("Your special attacks collide!")) end end pbEndDuel return decision end def pbEndDuel pbWait(0.75) pbMoveRoute($game_player, [PBMoveRoute::DIRECTION_FIX_OFF, PBMoveRoute::CHANGE_SPEED, @oldmovespeed]) pbMoveRoute(@event, [PBMoveRoute::DIRECTION_FIX_OFF, PBMoveRoute::CHANGE_SPEED, @oldeventspeed]) pbWait(0.4) do |delta_t| new_opacity = lerp(255, 0, 0.4, delta_t) @sprites["player"].opacity = new_opacity @sprites["opponent"].opacity = new_opacity @sprites["playerwindow"].contents_opacity = new_opacity @sprites["opponentwindow"].contents_opacity = new_opacity @sprites["playerwindow"].opacity = new_opacity @sprites["opponentwindow"].opacity = new_opacity end pbDisposeSpriteHash(@sprites) @viewport.dispose end def pbFlashScreens(player, opponent) pbWait(0.2) do |delta_t| new_alpha = lerp(0, 255, 0.2, delta_t) if player @sprites["player"].color = Color.new(255, 255, 255, new_alpha) @sprites["playerwindow"].color = Color.new(255, 255, 255, new_alpha) end if opponent @sprites["opponent"].color = Color.new(255, 255, 255, new_alpha) @sprites["opponentwindow"].color = Color.new(255, 255, 255, new_alpha) end end pbWait(0.2) do |delta_t| new_alpha = lerp(255, 0, 0.2, delta_t) if player @sprites["player"].color = Color.new(255, 255, 255, new_alpha) @sprites["playerwindow"].color = Color.new(255, 255, 255, new_alpha) end if opponent @sprites["opponent"].color = Color.new(255, 255, 255, new_alpha) @sprites["opponentwindow"].color = Color.new(255, 255, 255, new_alpha) end end @sprites["player"].color.alpha = 0 @sprites["playerwindow"].color.alpha = 0 @sprites["opponent"].color.alpha = 0 @sprites["opponentwindow"].color.alpha = 0 pbWait(0.4) if !player || !opponent end def pbRefresh @sprites["playerwindow"].hp = @hp[0] @sprites["opponentwindow"].hp = @hp[1] pbWait(0.25) end end # Starts a duel. # trainer_id - ID or symbol of the opponent's trainer type. # trainer_name - Name of the opponent # event - Game_Event object for the character's event # speeches - Array of 12 speeches def pbDuel(trainer_id, trainer_name, event, speeches) trainer_id = GameData::TrainerType.get(trainer_id).id duel = PokemonDuel.new opponent = NPCTrainer.new( pbGetMessageFromHash(MessageTypes::TRAINER_NAMES, trainer_name), trainer_id ) speech_texts = [] 12.times do |i| speech_texts.push(_I(speeches[i])) end duel.pbDuel(opponent, event, speech_texts) end