• Do not use Discord to host any images you post, these links expire quickly! You can learn how to add images to your posts here.
  • Eevee Expo's webhost has been having technical issues since Nov. 20th and you might be unable to connect to our site. Staff are also facing issues connecting, so please send a DM to Cat on-site or through Discord directly for faster service!
Resource icon

v21.1 Timer Based Safari Zone 1.0.0

This resource pertains to version 21.1 of Pokémon Essentials.
Ruby:
Expand Collapse Copy
#===============================================================================
#Timer Based Safari Zone by Hobbs
#Version 1.0.0 01/13/2024
#===============================================================================
# Install instructions
#
# replace existing safari zone script with this script
# adjust timer in settings line 93 as seen below:
#
# The number of seconds a Bug-Catching Contest lasts for (0=infinite).
# BUG_CONTEST_TIME        (Time is set here-->) = 20 * 60   # 20 minutes
#===============================================================================
#
#===============================================================================
class SafariState
  attr_accessor :ballcount
  attr_accessor :captures
  attr_accessor :decision
  attr_accessor :timer_start
 
  TIME_ALLOWED = Settings::BUG_CONTEST_TIME    # In seconds

  def initialize
    @start      = nil
    @ballcount  = 0
    @captures   = 0
    @inProgress = false
    @steps      = 0
    @decision   = 0
  end

  def expired?
    return false if !undecided?
    return false if TIME_ALLOWED <= 0
    return System.uptime - timer_start >= TIME_ALLOWED
  end

  def pbReceptionMap
    return @inProgress ? @start[0] : 0
  end

  def inProgress?
    return @inProgress
  end

  def undecided?
    return (@inProgress && @decision == 0)
  end

  def decided?
    return (@inProgress && @decision != 0) || @ended
  end

  def pbGoToStart
    if $scene.is_a?(Scene_Map)
      pbFadeOutIn do
        $game_temp.player_transferring   = true
        $game_temp.transition_processing = true
        $game_temp.player_new_map_id    = @start[0]
        $game_temp.player_new_x         = @start[1]
        $game_temp.player_new_y         = @start[2]
        $game_temp.player_new_direction = 2
        pbDismountBike
        $scene.transfer_player
      end
    end
  end

  def pbStart(ballcount)
    @start      = [$game_map.map_id, $game_player.x, $game_player.y, $game_player.direction]
    @ballcount  = ballcount
    @inProgress = true
    @timer_start = System.uptime
  end

  def pbEnd
    @start      = nil
    @ballcount  = 0
    @captures   = 0
    @inProgress = false
    @decision   = 0
    $game_map.need_refresh = true
  end
end

#===============================================================================
#
#===============================================================================
class TimerDisplay # :nodoc:
  attr_accessor :start_time

  def initialize(start_time, max_time)
    @timer = Window_AdvancedTextPokemon.newWithSize("", Graphics.width - 120, 0, 120, 64)
    @timer.z = 99999
    @start_time = start_time
    @max_time = max_time
    @display_time = nil
  end

  def dispose
    @timer.dispose
  end

  def disposed?
    @timer.disposed?
  end

  def update
    time_left = @max_time - (System.uptime - @start_time).to_i
    time_left = 0 if time_left < 0
    if @display_time != time_left
      @display_time = time_left
      min = @display_time / 60
      sec = @display_time % 60
      @timer.text = _ISPRINTF("<ac>{1:02d}:{2:02d}", min, sec)
    end
  end
end

#===============================================================================
#
#===============================================================================
def pbInSafari?
  if pbSafariState.inProgress?
    # Reception map is handled separately from safari map since the reception
    # map can be outdoors, with its own grassy patches.
    reception = pbSafariState.pbReceptionMap
    return true if $game_map.map_id == reception
    return true if $game_map.metadata&.safari_map
  end
  return false
end

def pbSafariState
  $PokemonGlobal.safariState = SafariState.new if !$PokemonGlobal.safariState
  return $PokemonGlobal.safariState
end

#===============================================================================
#
#===============================================================================
EventHandlers.add(:on_map_or_spriteset_change, :show_safari_game_timer,
  proc { |scene, _map_changed|
    next if !pbInSafari? || pbSafariState.decision != 0 || SafariState::TIME_ALLOWED == 0
    scene.spriteset.addUserSprite(
      TimerDisplay.new(pbSafariState.timer_start, SafariState::TIME_ALLOWED)
    )
  }
)

EventHandlers.add(:on_frame_update, :safari_game_counter,
  proc {
    next if !pbSafariState.expired?
    next if $game_player.move_route_forcing || pbMapInterpreterRunning? ||
            $game_temp.message_window_showing
    pbMessage(_INTL("ANNOUNCER: BEEEEEP!"))
    pbMessage(_INTL("Time's up!"))
    pbSafariState.decision = 1
    pbSafariState.pbGoToStart
  }
)

#===============================================================================
#
#===============================================================================
EventHandlers.add(:on_calling_wild_battle, :safari_battle,
  proc { |pkmn, handled|
    # handled is an array: [nil]. If [true] or [false], the battle has already
    # been overridden (the boolean is its outcome), so don't do anything that
    # would override it again
    next if !handled[0].nil?
    next if !pbInSafari?
    handled[0] = pbSafariBattle(pkmn)
  }
)

def pbSafariBattle(pkmn, level = 1)
  # Generate a wild Pokémon based on the species and level
  pkmn = pbGenerateWildPokemon(pkmn, level) if !pkmn.is_a?(Pokemon)
  foeParty = [pkmn]
  # Calculate who the trainer is
  playerTrainer = $player
  # Create the battle scene (the visual side of it)
  scene = BattleCreationHelperMethods.create_battle_scene
  # Create the battle class (the mechanics side of it)
  battle = SafariBattle.new(scene, playerTrainer, foeParty)
  battle.ballCount = pbSafariState.ballcount
  BattleCreationHelperMethods.prepare_battle(battle)
  # Perform the battle itself
  decision = 0
  pbBattleAnimation(pbGetWildBattleBGM(foeParty), 0, foeParty) do
    pbSceneStandby { decision = battle.pbStartBattle }
  end
  Input.update
  # Update Safari game data based on result of battle
  pbSafariState.ballcount = battle.ballCount
  if pbSafariState.ballcount <= 0
    if decision != 2   # Last Safari Ball was used to catch the wild Pokémon
      pbMessage(_INTL("Announcer: You're out of Safari Balls! Game over!"))
    end
    pbSafariState.decision = 1
    pbSafariState.pbGoToStart
  end
  # Save the result of the battle in Game Variable 1
  #    0 - Undecided or aborted
  #    2 - Player ran out of Safari Balls
  #    3 - Player or wild Pokémon ran from battle, or player forfeited the match
  #    4 - Wild Pokémon was caught
  if decision == 4
    $stats.safari_pokemon_caught += 1
    pbSafariState.captures += 1
    $stats.most_captures_per_safari_game = [$stats.most_captures_per_safari_game, pbSafariState.captures].max
  end
  pbSet(1, decision)
  # Used by the Poké Radar to update/break the chain
  EventHandlers.trigger(:on_wild_battle_end, pkmn.species_data.id, pkmn.level, decision)
  # Return the outcome of the battle
  return decision
end

#===============================================================================
#
#===============================================================================
class PokemonPauseMenu
  alias __safari_pbShowInfo pbShowInfo unless method_defined?(:__safari_pbShowInfo)

  def pbShowInfo
    __safari_pbShowInfo
    return if !pbInSafari?
    if Settings::SAFARI_STEPS <= 0
      @scene.pbShowInfo(_INTL("Balls: {1}", pbSafariState.ballcount))
    else
      @scene.pbShowInfo(_INTL("Caught: None/nBalls: {1}", pbSafariState.ballcount))
    end
  end
end

MenuHandlers.add(:pause_menu, :quit_safari_game, {
  "name"      => _INTL("Quit"),
  "order"     => 60,
  "condition" => proc { next pbInSafari? },
  "effect"    => proc { |menu|
    menu.pbHideMenu
    if pbConfirmMessage(_INTL("Would you like to leave the Safari Game right now?"))
      menu.pbEndScene
      pbSafariState.decision = 1
      pbSafariState.pbGoToStart
      next true
    end
    menu.pbRefresh
    menu.pbShowMenu
    next false
  }
})
Credits
No credit needed, but if used I would appreciate a subscribe on youtube. https://www.youtube.com/c/HobbsLive
Author
hobbs
Downloads
153
Views
516
First release
Last update

Ratings

0.00 star(s) 0 ratings

More resources from hobbs

Back
Top