[XP] Timed Choices

Started by KK20, June 01, 2013, 09:27:29 pm

Previous topic - Next topic

KK20

June 01, 2013, 09:27:29 pm Last Edit: June 03, 2013, 04:16:33 pm by KK20
Timed Choices
Authors: KK20
Version: 1.01
Type: Message Add-on
Key Term: Message Add-on



Introduction

You know the 'Show Choices' command that you can put in your events? Ever wanted to make it where the user is timed to make a decision? Look no further! This relatively small and simple script will do just that for you.


Features


  • 'Show Choices' can be timed for the player

  • Makes a nice little window to display the time remaining

  • Want to request some features? Post them here!




Screenshots

Spoiler: ShowHide



Demo

None.


Script

Spoiler: ShowHide

#=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# Timed Choices                                                       Ver 1.01
#   by KK20                                                          [03/06/13]
#=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# [ Description ]
# RPG Maker is built with a 'Show Choices' command, giving players a list of
# items to choose from. This script will throw in a timer element, limiting
# players with the amount of time they have to make a decision. Should the timer
# hit zero, the last item highlighted will be selected.
#
# [ Instructions ]
# Place below default scripts and any scripts that modify messages.
# There is very little to configure below.
#
# For events, use the script call
#
#    $game_system.choices_timer = frames
#
# replacing frames with an integer value. The timer counts down in frames. If
# your game is running at 40 frames per second, a value of 400 is equivalent to
# 10 seconds.
#
# The timer will carry on over to the next time choices are given. Thus, if you
# always want the player to have a fresh 5 seconds every time he/she is given
# choices, you will need to use the above script call every time before every
# 'Show Choices' command.
#
# If you wish to disable the timer, use the above script call but set it equal
# to -1.
#
# [ Tips ]
# Should you ever want to store the current timer, you can use this script call:
#
#     $game_variables[id] = $game_system.choices_timer
#
# replacing 'id' with the game variable you wish to use. You can then do
#
#     $game_system.choices_timer = $game_variables[id]
#
# to set the timer back.
#
# [ Compatibility ]
# - Fix for CCoa UMS v1.80 has been made as of v1.01
#
# Be wary of scripts that modify how messages are displayed.
# Aliases Window_Message class methods to ensure best compatibility.
#
# [ Credits ]
# KK20 - For script
#=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#                       C O N F I G U R A T I O N
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Determines position of timer window. 0 for left, 1 for center, 2 for right.
POSITION = 0
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#                   E N D   C O N F I G U R A T I O N
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
#  This message window is used to display text.
#==============================================================================

class Window_Message < Window_Selectable
  attr_reader :choice_window # Ccoa UMS fix
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  alias init_choices_timer_window initialize
  def initialize
    init_choices_timer_window
    @timer_window = Window_ChoicesTimer.new(self)
  end
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  alias dispose_timer_window dispose
  def dispose
    dispose_timer_window
    @timer_window.dispose
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  alias update_rest_of_msg_window update
  def update
    @timer_window.adjust_position(self.x,self.y)
    @timer_window.update
    # If choices displayed and timer has hit zero
    if $game_temp.choice_max > 0 and $game_system.choices_timer == 0
      super
      # Revert timer back to -1
      $game_system.choices_timer = -1
      # Force decision based on current item highlighted
      $game_system.se_play($data_system.decision_se)
      # Ccoa UMS fix
      var = defined?(Window_Choice) ? @choice_window.index : self.index
      $game_temp.choice_proc.call(var)
      terminate_message
      return
    end
    # Alias update method
    update_rest_of_msg_window
  end
end

#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
#  Adds another variable @choices_timer
#==============================================================================
class Game_System
  attr_accessor :choices_timer
  alias init_choices_timer initialize
  def initialize
    @choices_timer = -1
    init_choices_timer
  end
end

#==============================================================================
# ** Window_ChoicesTimer
#------------------------------------------------------------------------------
#  This window displays the amount of time the player has left to make a choice.
#==============================================================================
class Window_ChoicesTimer < Window_Base
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(msgwin)
    # Basic initialization variables
    super(0, 0, 64, 48)
    self.contents = Bitmap.new(self.width-32, self.height-32)
    self.visible = false
    self.z = 9998
    @fade_in = false
    @fade_out = false
    self.active = false
    # Assign message window
    self.message_window = msgwin
  end
  #--------------------------------------------------------------------------
  # * Assign message window and make appropriate movements to timer box
  #--------------------------------------------------------------------------
  def message_window=(msgwin)
    @message_window = msgwin
    adjust_position(msgwin.x,msgwin.y)
  end
  #--------------------------------------------------------------------------
  # * Moves the timer box
  #--------------------------------------------------------------------------
  def adjust_position(x,y)
    case POSITION
    when 1 then x = x + (width / 2) - 32
    when 2 then x = x + width - 64
    end
    if y <= 48
      y += height
    else
      y -= 48
    end
    return if [self.x,self.y] == [x,y]
    self.x, self.y = x,y
  end
  #--------------------------------------------------------------------------
  # * Update
  #--------------------------------------------------------------------------
  def update
    super
    # If window is fading in
    if @fade_in
      self.contents_opacity += 24
      if self.contents_opacity == 255
        @fade_in = false
      end
      return
    end
    # If the timer window needs to be displayed, prepare to display it
    if !self.visible and $game_temp.message_text != nil and
    $game_temp.choice_max > 0 and $game_system.choices_timer > 0
      # CCoa UMS fix
      if defined?(Window_Choice)
        return unless @message_window.choice_window.visible
      end
      @fade_in = true
      self.visible = true
      self.contents_opacity = 0
      self.opacity = 255
      self.back_opacity = 160
      # Draw timer
      self.contents.clear
      self.contents.font.size = 16
      sec = $game_system.choices_timer / Graphics.frame_rate
      min = sec / 60
      time = sprintf("%02d:%02d", min, sec)
      self.contents.draw_text(0,-15,self.width,self.height,time)
      return
    end
    # If no longer making choice, fade out window
    if $game_temp.choice_max == 0
      @fade_out = true
      self.opacity -= 48
      self.contents_opacity -= 48
      if self.opacity == 0
        self.visible = false
        @fade_out = false
      end
      return
    end
    # If window is visible, count down timer and draw it to window
    if self.visible
      self.contents.clear
      self.contents.font.size = 16
      sec = $game_system.choices_timer / Graphics.frame_rate
      min = sec / 60
      time = sprintf("%02d:%02d", min, sec)
      self.contents.draw_text(0,-15,self.width,self.height,time)
      $game_system.choices_timer -= 1
    end
  end
end



Instructions

Explained all in the script. Main script call is
$game_system.choices_timer = frames



Compatibility

- Fix for Ccoa's UMS v1.80 has been made as of v1.01
Might be incompatible with message systems (e.g. Ccoa, Hermes). This script should always be placed under those scripts. I aliased three methods in Window_Message so it should work most of the time. If you're not using any fancy messaging scripts, this should fit like a glove.


Credits and Thanks


  • KK20 - For realizing that he couldn't find a similar script to this despite having seen one before and getting off his lazy ass to write one himself




Author's Notes

Think a certain feature would be nice? Post away!
Current Ideas: ShowHide


  • Apply a timer to 'Input Number'

  • If timer runs out, perform a specific action rather than auto-selecting highlighted option

  • Give the timer window more configurations



Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

exile360

Simple but cool idea! And if you implement the stuff you have planned, I can already see this being used for hacking minigames and such. Good work. :)

Terv

I was planning to script it myself but yours looks just decent, thanks :haha:

Feature request: display a bar instead of 4 digit timer so the player knows the time remaining out from the corner of his eye and without having to stop reading the choices.

KK20

Thanks for the input!

Yeah, I had that idea of using a bar to represent the time. That kinda fell under 'Give the timer window more configurations' bit.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Terv

June 03, 2013, 01:45:03 pm #4 Last Edit: June 03, 2013, 01:47:32 pm by Terv
Two last things; the script call in the instructions of the start post is incorrect. Your script is compatible with latest ccoa's UMS (v1.80), however not entirely:

Normal choice: ShowHide

Timed choice: ShowHide


Here's the project in case you're interested in fixing this: UMS180_TimedChoices.zip

KK20

June 03, 2013, 03:13:01 pm #5 Last Edit: June 03, 2013, 04:21:05 pm by KK20
I think I see what the problem is, but I'll need to play with it a bit. Throwing the script call in between the Show Message and Show Choices disrupts the UMS. Basically, I have to make it so that when the choices window pops up, the timer does as well.

EDIT: Updated to v1.01. Fixed a couple other things in there as well. If you aren't using a custom message system, you won't notice the changes I made so you should still be good with v1.00.

If using Ccoa UMS, put the script call above the Show Message preceding Show Choices.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Terv

Epic, thanks a bunch! I'm sure I'm not the only one profiting from UMS compatibility.

How about an optional parameter that determines what happens if time runs out? Currently the hovered choice is selected, but what about respecting the "When Cancel" setting? So you can do something special if the player is too slow.

KK20

It's already in the plans. ;)

The way of how to go about it is still in the works. I'm not sure if doing a "Branch" for "When Cancel" and then making a script call that prevents the user from being able to cancel is the best way yet. Or if I just make a variable (say $game_temp.choice_timed_out) and then the user makes a Conditional Branch to see if that is set to true.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!