HELPER FOR TRACKING TIME (AT THE SPEED OF PLOT; RMVXACE)

Posts

Pages: 1
I'm making a game where I want to track the passage of time, but not in real-time! more like "oh, you traveled to X city? that took 2 days " or "fights just always take 20 minutes" (or maybe I could get fancy and count the turns taken, and multiply by some number, etc).

(and, I suppose, if you REALLY WANTED, you could probably rig up some kind of parallel process common event to automatically make the calls to progress the time.)

anyway, so I want an easy way to track the time: add various increments, slap the current month or whatever into conditionals, and even format it for display in a custom HUD. and doing this through events seemed cumbersome to me, soooooo: I made this script to handle it all for me.

it is incomplete at this time, but once complete, I'd definitely like to post it here, and elsewhere. until then, if it seems like something you'd use, and/or there are any other features you'd like in something like this, lemme know, and I'll see about adding them!

EDIT: added more formatting strings. added saving and loading of $game_date_and_time (oops). fixed some bugs.

=begin

complete method reference

  $game_date_tnd_time.year            # the current year
  $game_date_and_time.month
  $game_date_and_time.day
  $game_date_and_time.hour
  $game_date_and_time.minute

  $game_date_and_time.AddMinute        # adds one minute
  $game_date_and_time.AddMinutes(5)    # adds 5 minutes
  $game_date_and_time.RemoveMinutes(5) # goes BACK IN TIME 5 minutes - whoa
  
  $game_date_and_time.AddHour
  $game_date_and_time.AddHours(5)
  $game_date_and_time.RemoveHours(5)
  
  $game_date_and_time.AddDay
  $game_date_and_time.AddDays(5)
  $game_date_and_time.RemoveDays(5)
  
  $game_date_and_time.AddMonth
  $game_date_and_time.AddMonths(5)
  $game_date_and_time.RemoveMonths(5)
  
  $game_date_and_time.AddYear
  $game_date_and_time.AddYears(5)
  $game_date_and_time.RemoveYears(5)
  
  $game_date_and_time.DaysThisMonth   # returns the number of days this month
  
  $game_date_and_time.LongMonthName   # returns the name of the month
  $game_date_and_time.ShortMonthName  # returns the abbreviated month name
  $game_date_and_time.MonthName       # identical to LongMonthName

  $game_date_and_time.DayOfMonthSuffix # returns "st", "nd", "rd", or "th"

  $game_date_and_time.LeapYear?       # 'true' if current year is a leap year
  
  $game_date_and_time.Format("Y-m-d g:i A")
  
format requires some explanation >_> it returns the current date and time,
formatted according to the string you pass it. you can put anything you want
into the format string, and certain letters will be replaced with specific
date or time information. I do a lot of PHP coding, so I'm using the PHP
standard for date format, if you're familiar. if not, here's a table:

  d       Day of the month, 2 digits with leading zeroes
  D       Short day name (ex: Mon)
  j       Day of the month, without leading zeroes
  l       Full day name (ex: Monday)
  N       Numeric day of the week, from 1 = Monday to 7 = Sunday
  S       Returns "st", "nd", "rd", or "th" as appropriate for the current day
          (use with "j", ex "jS" might return "12th", "3rd", etc)
  w       Numeric day of the week, from 0 = Sunday to 6 = Saturday
  z       not yet implemented
  W       not yet implemented
  F       Full month name (ex: September)
  m       Month of the year, 2 digits with leading zeroes
  M       Short month name (ex: Sep)
  n       Month of the year, without leading zeroes
  t       Number of days in this month
  L       "1" if it's a leap year, "0" otherwise
  Y       Full year (ex: 2013)
  y       Last two digits of year (ex: 13)
  a       "am" or "pm"
  A       "AM" or "PM"
  g       Hour, in 12-hour format, without leading zeroes
  G       Hour, in 24-hour format, without leading zeroes
  h       Hour, in 12-hour format, 2 digits with leading zeroes
  H       Hour, in 24-hour format, 2 digits with leading zeroes
  i       Minutes, 2 digits with leading zeroes

any other characters (ex: "b", "Q", ":", " ") will be left alone.
  
so, for example, $game_date_and_time.Format("Y-m-d g:i A") might return
"2013-02-13 3:21 AM"

if you're familiar with PHP, you may notice that I did not list all the letters
that PHP supports. I do not intend to add support for those letters at this
time.

=end

module DataManager
  #--------------------------------------------------------------------------
  # * Create Game Objects
  #--------------------------------------------------------------------------
  def self.create_game_objects
    $game_temp          = Game_Temp.new
    $game_system        = Game_System.new
    $game_timer         = Game_Timer.new
    $game_message       = Game_Message.new
    $game_switches      = Game_Switches.new
    $game_variables     = Game_Variables.new
    $game_self_switches = Game_SelfSwitches.new
    $game_actors        = Game_Actors.new
    $game_party         = Game_Party.new
    $game_troop         = Game_Troop.new
    $game_map           = Game_Map.new
    $game_player        = Game_Player.new
    $game_date_and_time = Game_DateAndTime.new
  end
  #--------------------------------------------------------------------------
  # * Create Save Contents
  #--------------------------------------------------------------------------
  def self.make_save_contents
    contents = {}
    contents[:system]        = $game_system
    contents[:timer]         = $game_timer
    contents[:message]       = $game_message
    contents[:switches]      = $game_switches
    contents[:variables]     = $game_variables
    contents[:self_switches] = $game_self_switches
    contents[:actors]        = $game_actors
    contents[:party]         = $game_party
    contents[:troop]         = $game_troop
    contents[:map]           = $game_map
    contents[:player]        = $game_player
    contents[:date_and_time] = $game_date_and_time
    contents
  end
  #--------------------------------------------------------------------------
  # * Extract Save Contents
  #--------------------------------------------------------------------------
  def self.extract_save_contents(contents)
    $game_system        = contents[:system]
    $game_timer         = contents[:timer]
    $game_message       = contents[:message]
    $game_switches      = contents[:switches]
    $game_variables     = contents[:variables]
    $game_self_switches = contents[:self_switches]
    $game_actors        = contents[:actors]
    $game_party         = contents[:party]
    $game_troop         = contents[:troop]
    $game_map           = contents[:map]
    $game_player        = contents[:player]
    $game_date_and_time = contents[:date_and_time]
  end
end

class Game_DateAndTime
  attr_reader   :year
  attr_reader   :month
  attr_reader   :day
  attr_reader   :hour
  attr_reader   :minute
  
  # CUSTOMIZE ME!
  # the date and time you set here will be the date and time when a player
  # creates a new game. use 24 hour clock (ex: @hour = 15 means 3PM).
  def initialize
    @year = 2006
    @month = 8
    @day = 2
    @hour = 15
    @minute = 20
  end
  
  def AddMinute
    AddMinutes(1)
  end
  
  def AddMinutes(m)
    if m < 0
      RemoveMinutes(-m)
    else
      @minute += m
      if @minute / 60 > 0
        AddHours(@minute / 60)
        @minute = @minute % 60
      end
    end
  end
  
  def RemoveMinutes(m)
    if m < 0
      AddMinutes(-m)
    else
      @minute -= m
      
      # TODO: replace this while loop with MATH
      while @minute < 0 do
        RemoveHours(1)
        @minute += 60
      end
    end
  end

  def AddHour
    AddHours(1)
  end
  
  def AddHours(h)
    if h < 0
      RemoveHours(-h)
    else
      @hour += h
      if @hour / 24 > 0
        AddDays(@hour / 24)
        @hour = @hour % 24
      end
    end
  end
  
  def RemoveHours(h)
    if h < 0
      AddHours(-h)
    else
      @hour -= h
      
      # TODO: replace this while loop with MATH
      while @hour < 0 do
        RemoveDays(1)
        @hour += 24
      end
    end
  end
  
  def AddDay
    AddDays(1)
  end
  
  def AddDays(d)
    if d < 0
      RemoveDays(-d)
    else
      @day += d
      while @day > self.DaysThisMonth do
        @day -= self.DaysThisMonth
        AddMonth
      end
    end
  end
  
  def RemoveDays(d)
    if d < 0
      AddDays(-d)
    else
      @day -= d
      
      # can't replace this while loop with math, that I know of...
      while @day <= 0 do
        RemoveMonths(1)
        @day += self.DaysThisMonth
      end
    end
  end
  
  def AddMonth
    AddMonths(1)
  end
  
  def AddMonths(m)
    if m < 0
      RemoveMonths(-m)
    else
      @month += m
      if (@month - 1) / 12 > 0
        AddYears((@month - 1) / 12)
        @month = (@month - 1) % 12 + 1
      end
    end
  end
  
  def RemoveMonths(m)
    if m < 0
      AddMonths(-m)
    else
      @month -= m
      
      # TODO: replace this while loop with MATH
      while @month < 1 do
        RemoveYears(1)
        @month += 12
      end
    end
  end
  
  def AddYear
    AddYears(1)
  end
      
  def AddYears(y)
    # EASY PEASY!
    @year += y
  end
  
  def RemoveYears(y)
    # EASY PEASY!
    @year -= y
  end

  # TODO: does this work with negative years? >_> maybe we won't care
  def LeapYear?
    return (@year % 4 == 0 && @year % 100 != 0) || @year % 400 == 0
  end
  
  def DaysThisMonth
    if @month == 1 || @month == 3 || @month == 5 || @month == 7 || @month == 8 || @month == 10 || @month == 12
      31
    elsif @month == 2
      if LeapYear?
        29
      else
        28
      end
    else
      30
    end
  end

  def MonthName
    self.LongMonthName
  end
    
  def LongMonthName
    case @month
    when 1
      "January"
    when 2
      "February"
    when 3
      "March"
    when 4
      "April"
    when 5
      "May"
    when 6
      "June"
    when 7
      "July"
    when 8
      "August"
    when 9
      "September"
    when 10
      "October"
    when 11
      "November"
    when 12
      "December"
    else
      "Invalid"
    end
  end
    
  def ShortMonthName
    self.LongMonthName[0,3]
  end

  def DayName
    self.LongDayName
  end
  
  def LongDayName
    case self.DayOfWeek
    when 0
      "Sunday"
    when 1
      "Monday"
    when 2
      "Tuesday"
    when 3
      "Wednesday"
    when 4
      "Thursday"
    when 5
      "Friday"
    when 6
      "Saturday"
    else
      "Invalid"
    end
  end
  
  def ShortDayName
    self.LongDayName[0, 3]
  end
  
  def DayOfMonthSuffix
    if (@day >= 4 && @day <= 20) or (@day >= 24 && @day <= 30)
      'th'
    else
      return ["st", "nd", "rd"][@day % 10 - 1]
    end
  end
  
  def Format(format)

    hour12 = (@hour == 0) ? 12 : (@hour <= 12 ? @hour : @hour - 12)
    w = self.DayOfWeek

    dict = {
      "d" => "%.2d" % @day,
      "D" => self.ShortDayName,
      "j" => @day,
      "l" => self.LongDayName,
      "N" => w == 0 ? 7 : w,
      "S" => self.DayOfMonthSuffix,
      "w" => w,
      "F" => self.LongMonthName,
      "m" => "%.2d" % @month,
      "M" => self.ShortMonthName,
      "n" => @month,
      "t" => self.DaysThisMonth.to_s,
      "L" => self.LeapYear? ? '1' : '0',
      "Y" => @year,
      "y" => @year.to_s[-2, 2],
      "a" => @hour < 12 || @hour == 24 ? 'am' : 'pm',
      "A" => @hour < 12 || @hour == 24 ? 'AM' : 'PM',
      "g" => hour12,
      "G" => @hour,
      "h" => "%.2d" % hour12,
      "H" => "%.2d" % @hour,
      "i" => "%.2d" % @minute,
    }
    
    format.gsub /[dDjlNSwFmMntLYyaAgGhHi]/ do |match|
      dict[match.to_s]
    end
  end
  
  # returns 0 for Sunday, 1 for Monday, ..., and 6 for Saturday
  # from [url]http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week[/url]
  # SAMPAT MANE's Method
  def DayOfWeek
    d = @day
    m = [0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5][@month - 1]
    yy = @year.to_s[-2, 2].to_i
    q = yy / 4
    centuryMod = ((@year / 100) * 100) % 400
    
    if centuryMod == 0
      c = 6
    elsif centuryMod == 100
      c = 4
    elsif centuryMod == 200
      c = 2
    else # 300
      c = 0
    end
    
    finalD = d + m + yy + q + c
    
    if ((@month == 1 || @month == 2) && self.LeapYear?)
      finalD -= 1
    end
    
    finalD % 7
  end

end
The major suggestion I would put out: alias your methods in DataManager. It doesn't work quite the same as alias normally does because DataManager is a module, not a class, but it can be done (see this link). It'll help compatibility quite a lot (as I personally know a lot of my projects in the past, and most likely the future, have made use of additional game objects).
Pages: 1