Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Correct syntax to wait in a script

I am making a fishing script but i want the script to wait so many seconds like you can make events do. What is the correct syntax for this?

  def update
    @spriteset.update
    @fish.update
    @fish2.update
    *wait command here*
    update_fish
  end
 
Sobeman459":3innmhnz said:
I am making a fishing script but i want the script to wait so many seconds like you can make events do. What is the correct syntax for this?

  def update
    @spriteset.update
    @fish.update
    @fish2.update
    *wait command here*
    update_fish
  end

your best option is setting a variable somewhere, then, in the update, having that variable as variable -= 1. Then, put the a check to see if the variable is <= to 0. Or, you could just look up my multiple timers script and use that.
 
Do you want the game to wait a few moments during play until it reaches the next line, or do you want the method to do have the game do otherstuff for a few moments before doing update_fish. If you want the first, you can just make a commone event call the first part of the method, then put a wait in, call the second part. Then just use $game_temp.common_event_id = id to call it(this of course assumes that you are calling the method once, not every cycle.)
 
That didnt work, what im trying to do is make it wait so many frames before it switches to def update so text will stay on screen. Then again right before $scene = Scene_Map.new right at the end. If anyone could help that would be great, i also have the multi timer script if someone knows how to do it with that. Thanks.
-Sobe

Code:
class Scene_Fishing

   def main
    @spriteset = Spriteset_Map.new 
    @help_window = Window_Help.new
    @help_window.set_text("Fishing...", 1)
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
    @spriteset.dispose
    @help_window.dispose
    end
  def update
    @spriteset.update
    @help_window.update
    update_fish
  end
end
  def update_fish
    # If B button was pressed
    @help_window.set_text("Oh a bite!", 1)
    if Input.trigger?(Input::C)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      gain_random_fish
      return
    end
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to map screen
      $scene = Scene_Map.new
      return
    end
  end



def gain_random_fish
     case $game_player.direction
    when 2
      lookingx = $game_player.x
      lookingy = $game_player.y + 1
   when 4
      lookingx = $game_player.x - 1
      lookingy = $game_player.y
    when 6
      lookingx = $game_player.x + 1
      lookingy = $game_player.y
    when 8
      lookingx = $game_player.x
      lookingy = $game_player.y - 1
    end
     case $game_map.terrain_tag(lookingx,lookingy)
    when 6
        $FISH = [153, 154, 155, 156, 157, 158, 159]
    when 7
        $FISH = [142, 143, 144, 145, 146, 147, 148, 149, 150, 151]
      end
  fish2 = rand($FISH.size)
  $game_party.gain_item($FISH[fish2], 1)
  @help_window.set_text("You caught a " + $data_items[$FISH[fish2]].name + "!", 1)
  $game_variables[1] += 1
  $scene = Scene_Map.new
end
 
Well, with my script, it should be something like this:

Code:
class Scene_Fishing

   def main
    @spriteset = Spriteset_Map.new 
    @help_window = Window_Help.new
    @help_window.set_text("Fishing...", 1)
    Graphics.transition
    $game_temp.game_timer.start(seconds, 1)
    loop do
      Graphics.update
      Input.update
      $game_temp.game_timer.update_single(1)
      $game_temp.game_timer.update_single(2)
      if $game_temp. game_timer.check(1) == true
        update
      end
      if $scene != self
        if $game_temp. game_timer.check(2) == true
          break
        end
      end
    end
    Graphics.freeze
    @spriteset.dispose
    @help_window.dispose
    end
  def update
    @spriteset.update
    @help_window.update
    update_fish
  end
end
  def update_fish
    # If B button was pressed
    @help_window.set_text("Oh a bite!", 1)
    if Input.trigger?(Input::C)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      gain_random_fish
      $game_temp. game_timer.start(seconds, 2)
      return
    end
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to map screen
      $game_temp. game_timer.start(seconds, 2)
      $scene = Scene_Map.new
      return
    end
  end



def gain_random_fish
     case $game_player.direction
    when 2
      lookingx = $game_player.x
      lookingy = $game_player.y + 1
   when 4
      lookingx = $game_player.x - 1
      lookingy = $game_player.y
    when 6
      lookingx = $game_player.x + 1
      lookingy = $game_player.y
    when 8
      lookingx = $game_player.x
      lookingy = $game_player.y - 1
    end
     case $game_map.terrain_tag(lookingx,lookingy)
    when 6
        $FISH = [153, 154, 155, 156, 157, 158, 159]
    when 7
        $FISH = [142, 143, 144, 145, 146, 147, 148, 149, 150, 151]
      end
  fish2 = rand($FISH.size)
  $game_party.gain_item($FISH[fish2], 1)
  @help_window.set_text("You caught a " + $data_items[$FISH[fish2]].name + "!", 1)
  $game_variables[1] += 1
  $scene = Scene_Map.new
end

Just change the "seconds" in the script calls I added to make it work. I know you're probably teaching yourself to script, but I would recommend something other than the overdone fishing excercise. For my first two scripts, I made an early variant of the timer script you have, as well as a scripted thunderstorm. (The cool part about the thunderstorm is that it would play a random sound from a list I made, as well as put is at a random pitch and volums, or it might skip the thunder and lighning and (possibly, but not always) change the storm's intensity, or it might play multiple flashes before thunder)
 

Zeriab

Sponsor

There is no easy way of doing it like with events.
It will require you to implement some logic where you decrease a variable each frame or something like that.
Alternatively you could try using a Scheduler I have written although it most likely is a bit over your head.
Code:
#==============================================================================
# ** Scheduler
#------------------------------------------------------------------------------
#  This class allows to schedule a proc or method call a given amount of frames
#  into the future with any amount of arguments
#==============================================================================
class Scheduler
  #============================================================================
  # ** Order
  #----------------------------------------------------------------------------
  #  An order is a proc, method or something else which has 'call' as a method,
  #  and the arguments to pass along.
  #============================================================================
  # Create an struct for containing the data
  Order = Struct.new(:callable, :arguments)
  # Extend the class with a call-method which calls the callable with the args
  class Order
    #------------------------------------------------------------------------
    # * Call the callable with the present arguments
    #------------------------------------------------------------------------
    def call
      callable.call(*arguments)
    end
  end
  #============================================================================
  # ** RecurringOrder
  #----------------------------------------------------------------------------
  #  An order which is recurring every specified amount of time until 
  #  FalseClass is returned from the call.
  #  Note that arguments remain the same for each call
  #============================================================================
  # Create an struct for containing the data
  RecurringOrder = Struct.new(:callable, :arguments, :frames)
  # Extend the class with a call-method which calls the callable with the args
  class RecurringOrder
    #------------------------------------------------------------------------
    # * Call the callable with the present arguments
    #------------------------------------------------------------------------
    def call
      result = callable.call(*arguments)
      unless result == FalseClass
        Scheduler.schedule_recurring(frames, frames, callable, *arguments)
      end
    end
  end
  
  #============================================================================
  # ** Mapping
  #----------------------------------------------------------------------------
  # Maps an index to an array. Values can be added to these value.
  # Each array starts empty.
  #============================================================================
  class Mapping
    #------------------------------------------------------------------------
    # * Initialization
    #------------------------------------------------------------------------
    def initialize
      @mapping = {}
    end
    #------------------------------------------------------------------------
    # * Add an value to a given index
    #------------------------------------------------------------------------
    def add(index, value)
      @mapping[index] = [] if @mapping[index].nil?
      @mapping[index] << value
    end
    #------------------------------------------------------------------------
    # * Retrieve the list of values mapped to the index
    #------------------------------------------------------------------------
    def get(index)
      return [] if @mapping[index].nil?
      @mapping[index]
    end
    #------------------------------------------------------------------------
    # * Delete the array the index is mapped to. Conceptually it is now empty
    #------------------------------------------------------------------------
    def empty(index)
      @mapping.delete(index)
    end
  end
  
  #--------------------------------------------------------------------------
  # * Initialization
  #--------------------------------------------------------------------------
  def initialize
    # This maps 
    @mapping = Mapping.new
    @tick = 0
  end
  #--------------------------------------------------------------------------
  # * Scheduling
  #--------------------------------------------------------------------------
  def schedule(frames, callable, *arguments)
    # Create an order
    order = Order.new(callable, arguments)
    @mapping.add(frames + @tick, order)
  end
  #--------------------------------------------------------------------------
  # * Scheduling
  #--------------------------------------------------------------------------
  def schedule_recurring(frames, frames_to_wait, callable, *arguments)
    # Create an order
    order = RecurringOrder.new(callable, arguments, frames_to_wait)
    @mapping.add(frames + @tick, order)
  end
  #--------------------------------------------------------------------------
  # * Update the scheduler
  #--------------------------------------------------------------------------
  def update
    # Get the orders for the current tick
    orders = @mapping.get(@tick)
    # Delete the mapping's reference to the list of orders
    @mapping.empty(@tick)
    # Call each order
    for order in orders
      order.call
    end
    # Advance the tick (next frame)
    @tick += 1
  end
  
  #--------------------------------------------------------------------------
  # * 'Singleton' principle used although you can easily make 
  #   an extra scheduler. (Class method only works for this)
  #--------------------------------------------------------------------------
  @@instance = self.new
  def self.instance
    return @@instance
  end
  ## Class methods point to the equivalent instance methods
  def self.schedule_recurring(*args) instance.schedule_recurring(*args); end
  def self.schedule(*args) instance.schedule(*args); end
  def self.update(*args) instance.update(*args); end
end

You can schedule in two ways.
You can do a one-time schedule which works like this: (Using the class method)
Code:
Scheduler.schedule(frames, callable, *arguments)
# Here's an example
Scheduler.schedule(65, new Proc {|x,y| p x,y}, "A string", 42)
The 65 means that the proc will be called after 65 frames. (Or 65 ticks to be more precise. 1 update = 1 tick usually)
After 65 ticks the proc {|x,y| p x,y} will be called with the arguments x = "A string" and y = 42. (The *arguments means any number of arguments. This can also be no arguments at all)
The Scheduler uses duck typing and assumes that anything which has the .call method works properly in the context. I imagine procs and methods to be the most commonly used.

The next is that you can schedule a recurring call which works like this: (Using the class method)
Code:
Scheduler.schedule_recurring(frames, frames_to_wait, callable, *arguments)
# Here's an example
Scheduler.schedule_recurring(65, 30, new Proc {|x,y| p x,y}, "A string", 42)
The arguments is the same as for the one-time with the addition of the frames_to_wait argument.
This specifies that after the first 65 ticks each recurring call will happen after 30 ticks.
This will continue until the callable returns FalseClass. (Mind you it's false.class and not false)

Now you have to update the schedule every frame or it won't schedule properly.
Here is a binding where the scheduler updates every time the Graphics module updates. (Made for XP. I am unsure whether this part works in VX)
Code:
module Graphics
  class << self
	unless self.method_defined?(:scheduler_update)
	  alias :scheduler_update :update
	end
	def update(*args)
	  scheduler_update(*args)
	  Scheduler.update
	end
  end
end

Note that the class methods only work for one scheduler.

You can also consider having a parallel process running which waits a specific amount of frames before using a call script which does what you want it to do.

*hugs*
- Zeriab
 
that didnt work for what i wanted it to do, and yes im learning to script but its a system for my game. What i want to happen is after you choose what bait you want to use the "fishing..." comes up then say after 20 second or so it goes to "oh you have a bite" then you press enter and it goes to gain_random_fish and the "you caught a ____!" then you press enter then it goes to scene_map.new.

heres the new code with bait selection:
Code:
class Scene_Fishing

   def main
    @spriteset = Spriteset_Map.new 
    s1 = "Worm"
    s2 = "Cheese"
    s3 = "Bread"
    s4 = "Salt Pork"
    @command_window = Window_Command2.new(160, [s1, s2, s3, s4])
    @command_window.y = 64
    @command_window.opacity = 160
    if $game_party.item_number(161) == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(0)
    end
    if $game_party.item_number(162) == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(1)
    end
    if $game_party.item_number(163) == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(2)
    end
    if $game_party.item_number(164) == 0
      # Disable items, skills, equipment, and status
      @command_window.disable_item(3)
    end
    @help_window = Window_Help.new
    @help_window.set_text("Choose your bait.", 1)
    @help_window.opacity = 160
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
    @spriteset.dispose
    @command_window.dispose
    @help_window.dispose
    end
  def update
    @spriteset.update
    @command_window.update
    @help_window.update
    update_command
  end
    def update_command
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to map screen
      $scene = Scene_Map.new
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Branch by command window cursor position
      case @command_window.index
      when 0  # bait 1
      if $game_party.item_number(161) == 0 
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      else
        @help_window.set_text("Fishing...", 1)
        @command_window.visible = false
        @command_window.active = false
        $game_party.lose_item(161, 1)
        update_fish
      end
      when 1  # bait 2
      if $game_party.item_number(162) == 0 
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      else
        @help_window.set_text("Fishing...", 1)
        @command_window.visible = false
        @command_window.active = false
        $game_party.lose_item(162, 1)
        update_fish
      end
      when 2  # bait 3
        if $game_party.item_number(163) == 0 
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      else
        @help_window.set_text("Fishing...", 1)
        @command_window.visible = false
        @command_window.active = false
        $game_party.lose_item(163, 1)
        update_fish
      end
      when 3  # bait 4
      if $game_party.item_number(164) == 0 
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      else
        @help_window.set_text("Fishing...", 1)
        @command_window.active = false
        @command_window.visible = false
        $game_party.lose_item(164, 1)
        update_fish
      end
      end
      return
    end
  end
end

  def update_fish
    # If B button was pressed
    @help_window.set_text("Oh a bite!", 1)
    if Input.trigger?(Input::C)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      gain_random_fish
      return
    end
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Switch to map screen
      $scene = Scene_Map.new
      return
    end
  end



def gain_random_fish
     case $game_player.direction
    when 2
      lookingx = $game_player.x
      lookingy = $game_player.y + 1
   when 4
      lookingx = $game_player.x - 1
      lookingy = $game_player.y
    when 6
      lookingx = $game_player.x + 1
      lookingy = $game_player.y
    when 8
      lookingx = $game_player.x
      lookingy = $game_player.y - 1
    end
     case $game_map.terrain_tag(lookingx,lookingy)
    when 6
        $FISH = [153, 154, 155, 156, 157, 158, 159]
    when 7
        $FISH = [142, 143, 144, 145, 146, 147, 148, 149, 150, 151]
      end
  fish2 = rand($FISH.size)
  $game_party.gain_item($FISH[fish2], 1)
  @help_window.set_text("You caught a " + $data_items[$FISH[fish2]].name + "!", 1)
  $game_variables[1] += 1
  if Input.trigger?(Input::C)
  $scene = Scene_Map.new
  return
end
end
 
Take a look at the code I had in my post. It was an updated version of your code, and it included the commands for my Multiple Timers script. All you had to do for that one was change the seconds in the bits of code I added, and it should work just fine.
 
How can what I gave you not work?
Just add
Code:
for i in 0...40
  Graphics.update
end
wherever you want it to wait, and it will wait for 40 frames, remember it waits 40 frames (1 sec) not 40 sec, if you want it to wait 20 sec just change 40 to 800. :thumb:
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top