RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Time System

Morxeton

Sorceror
Time System

Time System v1.1.12
Released: February 18, 2006 @ 11:30 PM CST


Description:

A fully customizable date and time system that keeps track of it's own time or use real time. It loads it's data from a file at world load, and saves it's data on every world save.

Updates:

v1.1.12:
  • Fixed a bug in setting the TIMEFORMAT or CLOCKTIMEFORMAT without specifying a value would result in a null reference exception.
  • Added a [TS VERSION command to display the version of the time system.

v1.1.11:
  • Fixed the $nth$ format variable to now be either based off of day or month. $nth$ can no longer be used. It is now $nth-d$ for day and $nth-m$ for month.

v1.1.1:
  • Added a [TS APPEND command for appending to string variables. If you use the command for non-string variables, it just sets them as it would with [TS SET.
  • Fixed a bug when specifying a variable that does not exist, it would not notify you.

v1.1.01:
  • Changed some code in the Support.cs to allow customizing the names of your months in the m_MonthsList.

v1.1.0:
  • Fixed a bug that when specifying a number without a decimal point for the timerspeed, it would reject the attempt due to it being an int instead of a double.
  • Added a [TS STOP, [TS START, and [TS RESTART commands which will stop, start, and restart the time system. When stopping the system, it does not perform the calculations for light level and time. It will display the day level until the system is started again.
  • Added instructions for how to modify Spyclass.cs and Clocks.cs to reflect the moonphase and time.
  • Added time zones with ability to configure them yourself based on how many location.X is considered 1 minute. This was a huge overhaul to the system to be able to do this. The default is 16 X is 1 minute and can be changed via [TS SET TIMEZONEXDIVISOR <number>
  • You can disable using time zones by typing [TS SET USETIMEZONES false, in which the system will perform calculations on each tick of the timer only, and not each and every time a player moves.
  • Added [BASETIME command that gamemaster's and above can use to check the system's base time, which is the time the system keeps track of basing it's time zones from. Using [TIME will display the time in the current time zone.
  • Changed the variable name m_UseItemLighting to m_UseAutoLighting which means you will type UseAutoLighting instead of UseItemLighting using [TS SET.
  • Fixed a bug where changing the moonphaseday would not recalculate the light levels until the next timer tick.
  • Added a [TS SETTIME <hh:mm> command to allow you to set the time a bit easier.
  • Added a [TS QUERY command to query the time system to see if it is running, and if it is, how fast is it calculating time.
  • Added a Support.cs script to assist the system as well as help move some methods out of the Time System.cs so that the file is not too big.
  • Added custom formatting. This was a huge update. You will type [TS SET TIMEFORMAT <format> to set the formatting for the [TIME and [BASETIME commands. You will type [TS SET CLOCKTIMEFORMAT <format> to set the format for when double clicking on clock items. There are six presets you can choose from.

v1.0.4:
  • Fixed a bug when typing [TS it would not show the command list.

v1.0.3:
  • Fixed a bug when a managed light was deleted from the world and it was selected in PerformRandomLightOutage(), it would not check to see if it was deleted first.
  • Made it so when the managed lights list was repopulated, it would check to see if the item was deleted or not before adding it to the list.
  • Added a command called [TS REPOPLIGHTSLIST to force the list to be repopulated. Use this command after adding/removing lights that are of the type that will be managed by the system (i.e. LampPost1, LampPost2, LampPost3).
  • Typing [TS by itself will show a list of commands that can be used.

v1.0.2:
  • Fixed a bug in the code that was causing the time calculation to appear to occur one timer tick too slow.
  • Fixed a bug that would cause the lights to come on after the m_LightsOnLevel, and not on it.
  • Added UseRealTime variable in which by default is false. When true, it will use your computer's date and time.
  • Realized that my loading/saving method was not going to work, I had to make some slight changes in it which involves any pre v1.0.2 files to load "corrupt" and force the system to recreate the file using default values.
  • Fixed a bug where setting the Hour or Minute variable would not recalculate the light levels, instead it would wait for the next timer tick.

v1.0.1:
  • Fixed a minor bug when using the [TS SET command when setting a boolean value, it would only accept lowercase true or false.
  • Removed an unused method which was used to test how the light levels were handled in the distro.

Features:
  • Darkest Hour is a time period (default two hours) in which after night has fallen that it gets extremely dark. The time period can be adjusted as well as how long it takes to scale from Night/Darkest Hour and vice versa. The moon phase has no effect on the Darkest Hour.
  • During the Darkest Hour, random lampposts throughout the world will toggle on/off (as a result of the presence of evil in the air). This feature can be customized by a percentage of how often it can happen and then a random percent range of how many lights are affected at once. This feature can be disabled.
  • Light levels for Day/Night/Darkest Hour are customizable.
  • When a certain light level has been reached (by default when it's halfway to night fall), all the world lampposts will be turned on. This feature can be customized or disabled.
  • You can set the Minutes/Hour, Hours/Day, Days/Month, and Months/Year. Default is 60 min/hour, 24 hours/day, 30 days/month, 12 months/year.
  • The moon phase affects how dark it is at night. You can adjust how much the moon phase can affect the light level.
  • The amount of days per total moon phase can be adjusted (default is 16).
  • You can customize the moonphase enumerator, but this requires editting the script and adding in your own custom moonphases if you wish. Please read the comments in the script for instructions.
  • The timer by default ticks once every five seconds. You can adjust how often the timer ticks with a minimum value of 0.5 seconds. You can also set how many game minutes will pass with each tick (default 1).
  • You can customize the starting hour for day and night. By default night starts scaling at the 20th hour (8 PM) and day starts scaling at the 6th hour. There is a minimum difference of 4 hours required.
  • You can set the current year, month, day, hour, and minute as well as the current moon phase day.

Information:

To customize the system in-game, please use the [TS SET <variable> <value> command. Type [TS SET for a list of variables that can be set.

Use the [TIME command to see the current date/time/moonphase. Players are able to use this command. If you wish to disable them from using it, change the accesslevel in the Initialize function.

The only lights that will be toggled on/off are BaseLight types LampPost1, LampPost2, and LampPost3. You can add/remove types by changing the Type array m_ItemLightTypes.

If any lights are deleted from the world, they will not be removed from the m_LightsList array unless the PerformRandomLightOutage() method just so happens to come across a deleted light. I will look into another method for handling this without modifying BaseLight.cs and without being a resource hog.

If any lights are added to the world, they will not be controlled by the system unless the system wipes and repopulates the m_LightsList. You can force the list to be repopulated by typing [TS REPOPLIGHTSLIST.

For formatting help, please view the Formatting.txt inside the zip file.


TODO:
  • I am working on a plug-in system in which will control all of my scripts that I create. When that system is complete, this system will attach to that system and be configurable via gumps.
  • Implementing the change of seasons with the ability to toggle them on/off as well as a time differential variation (i.e. winter has shorter days and summer has longer days, and this feature can be turned on/off as well).
  • A weather system will be developed and integrated with this system for enhancing effects, such as it will get noticeably darker when it rains or snows.
  • The RandomLightOutage feature will be configurable by region, or can be turned on for the entire world as it works now. I also plan to create some custom lampposts that will have a bool value true/false to allow/disallow this feature (i.e. if value is true, the lamppost is always affected as long as RandomLightOutage is true, and if false, it will ignore the fact that the feature is on or off.)
  • Nightsight override will be implemented to where you can override the nightsight potion and spell from working during the darkest hour and/or nighttime in general.
  • I will be adding in more [TS commands.

Suggestions From Community:

Install:
Please see 2nd post in the thread.
 

Attachments

  • Time System v1.1.12.zip
    19.6 KB · Views: 423

Morxeton

Sorceror
Install:
To install, just extract the zip file into anywhere in the scripts directory. You must make changes to distro files. Please see below.

To make changes to LightCycle.cs located in Scripts/Misc:

Find the Initialize() method:
Code:
public static void Initialize()
{
	new LightCycleTimer().Start();
	EventSink.Login += new LoginEventHandler( OnLogin );

	Server.Commands.Register( "GlobalLight", AccessLevel.GameMaster, new CommandEventHandler( Light_OnCommand ) );
}
Change it to:
Code:
public static void Initialize()
{
	//new LightCycleTimer().Start();
	//EventSink.Login += new LoginEventHandler( OnLogin );

	Server.Commands.Register( "GlobalLight", AccessLevel.GameMaster, new CommandEventHandler( Light_OnCommand ) );
}
Find the ComputeLevelFor( Mobile from ) method:
Code:
public static int ComputeLevelFor( Mobile from )
{
    if (m_LevelOverride > int.MinValue)
        return m_LevelOverride;

    int hours, minutes;

    Server.Items.Clock.GetTime(from.Map, from.X, from.Y, out hours, out minutes);

    /* OSI times:
     * 
     * Midnight ->  3:59 AM : Night
     *  4:00 AM -> 11:59 PM : Day
     * 
     * RunUO times:
     * 
     * 10:00 PM -> 11:59 PM : Scale to night
     * Midnight ->  3:59 AM : Night
     *  4:00 AM ->  5:59 AM : Scale to day
     *  6:00 AM ->  9:59 PM : Day
     */

    if (hours < 4)
        return NightLevel;

    if (hours < 6)
        return NightLevel + (((((hours - 4) * 60) + minutes) * (DayLevel - NightLevel)) / 120);

    if (hours < 22)
        return DayLevel;

    if (hours < 24)
        return DayLevel + (((((hours - 22) * 60) + minutes) * (NightLevel - DayLevel)) / 120);

    return NightLevel; // should never be
}
Change it to:
Code:
public static int ComputeLevelFor( Mobile from )
{
    if (m_LevelOverride > int.MinValue)
        return m_LevelOverride;

// ** EDIT ** Time System
    if (TimeSystem.System.Enabled)
    {
        return TimeSystem.System.ComputeLevelFor(from);
    }
    else
    {
        int hours, minutes;

        Server.Items.Clock.GetTime(from.Map, from.X, from.Y, out hours, out minutes);

        /* OSI times:
         * 
         * Midnight ->  3:59 AM : Night
         *  4:00 AM -> 11:59 PM : Day
         * 
         * RunUO times:
         * 
         * 10:00 PM -> 11:59 PM : Scale to night
         * Midnight ->  3:59 AM : Night
         *  4:00 AM ->  5:59 AM : Scale to day
         *  6:00 AM ->  9:59 PM : Day
         */

        if (hours < 4)
            return NightLevel;

        if (hours < 6)
            return NightLevel + (((((hours - 4) * 60) + minutes) * (DayLevel - NightLevel)) / 120);

        if (hours < 22)
            return DayLevel;

        if (hours < 24)
            return DayLevel + (((((hours - 22) * 60) + minutes) * (NightLevel - DayLevel)) / 120);

        return NightLevel; // should never be
    }
// ** END ***
}
To make changes to Clocks.cs located in Scripts/Items/Skill Items/Tinkering:

At the very top of the file above the namespace, find:
Code:
using System;
using Server;
Change it to:
Code:
using System;
using Server;
// ** EDIT ** Time System
using Server.Network;
using Server.Mobiles;
// ** END ***

Find the GetTime( Map map, int x, int y, out int hours, out int minutes, out int totalMinutes ) method:
Code:
public static void GetTime( Map map, int x, int y, out int hours, out int minutes, out int totalMinutes )
{
    TimeSpan timeSpan = DateTime.Now - WorldStart;

    totalMinutes = (int)(timeSpan.TotalSeconds / SecondsPerUOMinute);

    if ( map != null )
        totalMinutes += map.MapIndex * 320;

    // Really on OSI this must be by subserver
    totalMinutes += x / 16;

    hours = (totalMinutes / 60) % 24;
    minutes = totalMinutes % 60;
}
Change it to:
Code:
public static void GetTime( Map map, int x, int y, out int hours, out int minutes, out int totalMinutes )
{
// ** EDIT ** Time System

    if (TimeSystem.System.Enabled)
    {
        totalMinutes = 0;

        TimeSystem.System.GetTime(x, out hours, out minutes);
    }
    else
    {
        TimeSpan timeSpan = DateTime.Now - WorldStart;

        totalMinutes = (int)(timeSpan.TotalSeconds / SecondsPerUOMinute);

        if ( map != null )
            totalMinutes += map.MapIndex * 320;

        // Really on OSI this must be by subserver
        totalMinutes += x / 16;

        hours = (totalMinutes / 60) % 24;
        minutes = totalMinutes % 60;
    }
// ** END ***
}
Find the OnDoubleClick( Mobile from ) method:
Code:
public override void OnDoubleClick( Mobile from )
{
    int genericNumber;
    string exactTime;

    GetTime( from, out genericNumber, out exactTime );

    SendLocalizedMessageTo( from, genericNumber );
    SendLocalizedMessageTo( from, 1042958, exactTime ); // ~1_TIME~ to be exact
}
Change it to:
Code:
public override void OnDoubleClick( Mobile from )
{
// ** EDIT ** Time System

    if (TimeSystem.System.Enabled)
    {
        NetState state = from.NetState;

        MessageType type = Network.MessageType.Regular;
        int hue = 0x3B2;
        string text = TimeSystem.System.GetTime(from.X, true);

        state.Send(new UnicodeMessage( Serial, ItemID, type, hue, 3, "ENU", Name, text ));
    }
    else
    {
        int genericNumber;
        string exactTime;

        GetTime( from, out genericNumber, out exactTime );

        SendLocalizedMessageTo( from, genericNumber );
        SendLocalizedMessageTo( from, 1042958, exactTime ); // ~1_TIME~ to be exact
    }
// ** END ***
}
To make changes to Spyglass.cs located in Scripts/Items/Skill Items/Tinkering:

Find the OnDoubleClick( Mobile from ) method:
Code:
public override void OnDoubleClick( Mobile from )
{
    from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1008155); // You peer into the heavens, seeking the moons...

    from.Send(new MessageLocalizedAffix(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, 1008146 + (int)Clock.GetMoonPhase(Map.Trammel, from.X, from.Y), "", AffixType.Prepend, "Trammel : ", ""));
    from.Send(new MessageLocalizedAffix(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, 1008146 + (int)Clock.GetMoonPhase(Map.Felucca, from.X, from.Y), "", AffixType.Prepend, "Felucca : ", ""));

    PlayerMobile player = from as PlayerMobile;

	if ( player != null )
	{
		QuestSystem qs = player.Quest;

		if ( qs is WitchApprenticeQuest )
		{
			FindIngredientObjective obj = qs.FindObjective( typeof( FindIngredientObjective ) ) as FindIngredientObjective;

			if ( obj != null && !obj.Completed && obj.Ingredient == Ingredient.StarChart )
			{
				int hours, minutes;
				Clock.GetTime( from.Map, from.X, from.Y, out hours, out minutes );

				if ( hours < 5 || hours > 17 )
				{
					player.SendLocalizedMessage( 1055040 ); // You gaze up into the glittering night sky.  With great care, you compose a chart of the most prominent star patterns.

					obj.Complete();
				}
				else
				{
					player.SendLocalizedMessage( 1055039 ); // You gaze up into the sky, but it is not dark enough to see any stars.
				}
			}
		}
	}
}
Change it to:
Code:
public override void OnDoubleClick( Mobile from )
{
// ** EDIT ** Time System
    if (TimeSystem.System.Enabled)
    {
        from.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, String.Format("You peer into the sky and see the moon is {0}.", TimeSystem.System.GetMoonPhaseName(from.X)));
    }
    else
    {
        from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1008155); // You peer into the heavens, seeking the moons...

        from.Send(new MessageLocalizedAffix(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, 1008146 + (int)Clock.GetMoonPhase(Map.Trammel, from.X, from.Y), "", AffixType.Prepend, "Trammel : ", ""));
        from.Send(new MessageLocalizedAffix(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, 1008146 + (int)Clock.GetMoonPhase(Map.Felucca, from.X, from.Y), "", AffixType.Prepend, "Felucca : ", ""));
    }
// ** END ***
	PlayerMobile player = from as PlayerMobile;

	if ( player != null )
	{
		QuestSystem qs = player.Quest;

		if ( qs is WitchApprenticeQuest )
		{
			FindIngredientObjective obj = qs.FindObjective( typeof( FindIngredientObjective ) ) as FindIngredientObjective;

			if ( obj != null && !obj.Completed && obj.Ingredient == Ingredient.StarChart )
			{
				int hours, minutes;
				Clock.GetTime( from.Map, from.X, from.Y, out hours, out minutes );

				if ( hours < 5 || hours > 17 )
				{
					player.SendLocalizedMessage( 1055040 ); // You gaze up into the glittering night sky.  With great care, you compose a chart of the most prominent star patterns.

					obj.Complete();
				}
				else
				{
					player.SendLocalizedMessage( 1055039 ); // You gaze up into the sky, but it is not dark enough to see any stars.
				}
			}
		}
	}
}

Fire up your server and enjoy!
 
Morxeton

Nice work! I'm glade to see you back :) Looking forward to the updates specially seasons.

Beneath: (The comma comes before "And" you were correct)
 

Morxeton

Sorceror
v1.0.1 released:
  • Fixed a minor bug when using the [TS SET command when setting a boolean value, it would only accept lowercase true or false.
  • Removed an unused method which was used to test how the light levels were handled in the distro.
 

Morxeton

Sorceror
okyzan said:
it shows the time incorrect when i type [time
how can i set the time

What time is incorrect? This system is not based on real time. It is based on it's own time. Type [TS SET for a list of variables that you may set, then type [TS SET <variable> <value> to change it to what you want.
 

okyzan

Wanderer
can it be work from real time?for example
in here the time is 7.33 in the morning.can it be the same in the game?and set the lights etc for this time.i think this gives more realism..
 

Morxeton

Sorceror
okyzan said:
can it be work from real time?for example
in here the time is 7.33 in the morning.can it be the same in the game?and set the lights etc for this time.i think this gives more realism..
Yes, if you type:

[TS SET timerspeed 60.0

This will set the timer to tick once every 60 seconds. Then set your hour and minute to what your local time is, i.e.:

[TS SET hour 7
[TS SET minute 33

Be sure to use 60.0 for the timerspeed, as it will think 60 by itself is an int, in which the system will inform you that the value must be a double. It's not a big deal, but I may fix that minor issue.

Please note:
If you take your server offline for x amount of time, after bringing it back online, the Time System will pick up where it left off, since it's not based on real time. You would have to set your hour and minute again.

Now that I think about it, maybe adding an option to use real time isn't a bad idea.
 

okyzan

Wanderer
if you add an option for real time this will be very good.because for example in world of warcraft it uses real time lighting and its very realistic.and in this version if i have to set the amount of hour and minute in every restarts it will be very annoying after a period of time.
 

okyzan

Wanderer
thank you very much.when its done.i am going to test this script in my shard and let you know the bugs (if exists) thanks again.
 

Morxeton

Sorceror
v1.0.2 released:
  • Fixed a bug in the code that was causing the time calculation to appear to occur one timer tick too slow.
  • Fixed a bug that would cause the lights to come on after the m_LightsOnLevel, and not on it.
  • Added UseRealTime variable in which by default is false. When true, it will use your computer's date and time.
  • Realized that my loading/saving method was not going to work, I had to make some slight changes in it which involves any pre v1.0.2 files to load "corrupt" and force the system to recreate the file using default values.
  • Fixed a bug where setting the Hour or Minute variable would not recalculate the light levels, instead it would wait for the next timer tick.
 

wulf monat

Sorceror
Very nice Idea

I love this idea i'm going to try this right away on my server, it'll fit in like its at home, heheheh thanks a mill for sharing this.......*+Karma*
 

goodmojo

Wanderer
I havent tried this yet but just wanted to comment that it seems like a first-rate effort from what im reading. Kudos to you!
 
Top