Date time script

darkrose289

New member
Q1: Is there a script available to get TRS22 to use my computer's date time as the games world date time?

Q2: Is there a script that will allow for manual world-time entry rather than using the dial in the Edit Environment?
 
Q1: I have not come across such a script

Q2: I agree, the dial is clunky and not as accurate as I would like - try setting the time dial to exactly 08:30 for example. You can jump from Driver into Surveyor to set the time using the Time and Rate Rule in the Session Editor and then jump back into Driver.
 
Sooooo, I started looking into starting a script to get the current time and date from the user's system and convert that into Trainz Normalised time. What follows is a VERY rough draft idea of how part of it would work but I need some big time SME intervention to really make this into a usable script. If you are a Trainz scripting expert or OOP (e.g., C++) scripting expert, your ideas and solutions are greatly sought after and appreciated. And if your like me with little to no programming skills or somewhere between me and expert, please share any thoughts you might have to bring success to this little project.

C++:
/*
Scratch pad area for creating a formula to convert real time into Trainz time values

N3V Wiki Notes (https://online.ts2009.com/mediaWiki/index.php/Class_World)

Trainz World Set Time command example
    public void SetGameTime(float time)

        World.SetGameTime(0.5); //sets the game time to midnight

    Game time is normalised to a value between 0.0 and 1.0
    0.0 = midday
    0.25 = 6 p.m.
    0.5 = midnight
    0.75 = 6 a.m.
    1.0 = midday again
    Use the Time Value constants to convert human readable times to normalised values.
   
Time Value Constatnts:
public define float TIME_SECOND = 1.0f                  //One second.
public define float TIME_MINUTE = TIME_SECOND * 60.0f     //One minute, 60.0 seconds.
public define float TIME_HOUR = TIME_MINUTE * 60.0f     //One hour, 60.0 minutes, 3600.0 seconds.
public define float TIME_DAY = TIME_HOUR * 24.0f         //One day, 24 hours, 1440.0 minutes, 86400.0 seconds.


**********          darkrose289 PSUEDO CODE based in part on C++          **********
Program assumes 24-hour time is retrieved from the system regardless of User OS GUI time settings

Note: testing some simple C++ time functions returned UTC time. Retrieivng local time will need to account for the user's time zone otherwise UTC time is the system default.

Psuedo Variables:
    int RealWorldHour; //RWH
    int RealWorldMinute; //RWM
    float fGameHour; //GH - Normalised Hours
    float fGameMinute; //GM - Normalised Minutes
    float fGameTime; //GT - Normalised Time
    int secondsPerDay = 86400; //SPD - 24 hours * 60 minutes * 60 seconds
    int secondsPerHour = 3600; //SPH - 60 minutes * 60 seconds
    int offsetHours = 12; //OH - because Trainz uses 1200 (12:00 pm or Noon) as the first hour of the World.GameTime instead of midnight (2400, 0000, or 12:00 am) as in the real world.

Equation psuedo code

GET RWH;
    IF (RWH >= 0 OR RWH <= 11) {
        THEN GH = ((RWH + OH) * SPH) / SPD; // Real world hours 0 - 11 add 12
    } ELSE {
        GH = ((RWH - OH) * SPH) / SPD; // Real world hours 12 - 23 subtract 12
    }
GET RWM;
GM = (RWM * 60) / SPD; // Yeilds the normalised minutes
GT = GH + GM; // Resulting values will never equal 1, range is from 0.0 (1200) to 0.9993 (2359)

Sample times (24-hour format) with normalised values
1352 normalised is 0.0778 (13 = 0.0417 and 52 = 0.0361)
1651 normalised is 0.2021 (16 = 0.1667 and 51 = 0.0354)
0316 normalised is 0.6361 ( 3 = 0.6250 and 16 = 0.0111)
1030 normalised is 0.9375 (10 = 0.9167 and 30 = 0.0208)

Formulae were fine tuned in MS Excel spreadsheet to ensure correct values for normalised time were generated



**********           Using Trainz Time Constants and proper syntax...mostly (except for where GET occurs; still trying to determine the best route for this part, i.e., lots of research)          **********

include "World.gs"
include "Browser.gs"                //not sure if this is required
include "KUID.gs"                    //not sure if this is required, possibly not since this is not interacting directl with any assets
include "RealTimeRule.gs"     //Sets the Game Date and Time with the local system date and time - should only need to run it once per game or session start.

public define float TIME_SECOND = 1.0f                  //One second.
public define float TIME_MINUTE = TIME_SECOND * 60.0f     //One minute, 60.0 seconds.
public define float TIME_HOUR = TIME_MINUTE * 60.0f     //One hour, 60.0 minutes, 3600.0 seconds.
public define float TIME_DAY = TIME_HOUR * 24.0f         //One day, 24 hours, 1440.0 minutes, 86400.0 seconds.
int RealWorldHour;
int RealWorldMinute;
float fGameHour; // Normalised Hours
float fGameMinute; // Normalised Minutes
float time; // Normalised Time
int offsetHours = 12; // Because Trainz uses 1200 (12:00 pm or Noon) as the first hour of the World.GameTime instead of midnight (2400, 0000, or 12:00 am) as in the real world.

GET RealWorldHour; //get system time hours field and assign to variable

if (RealWorldHour >= 0 || RealWorldHour <= 11) {
    fGameHour = ((RealWorldHour + offsetHours) * TIME_HOUR) / TIME_DAY; // Real world hours 0 - 11 add 12
}
else {
    fGameHour = ((RealWorldHour - offsetHours) * TIME_HOUR) / TIME_DAY; // Real world hours 12 - 23 subtract 12
}

GET RealWorldMinute; //get system time minutes field and assign to variable

fGameMinute = (RealWorldMinute * TIME_MINUTE) / TIME_DAY; // Yeilds the normalised minutes
time = fGameHour + fGameMinute; // Resulting values will never equal 1, range is from 0.0 (1200) to 0.9993 (2359)


**********          Last thoughts          **********
I know there is a ton of refinement needed for the above script idea. Hopefully this the proverbial "diamond in the rough". I'm sure that in the right hands, this endeavor
can have a more elegant code than what I have drafted so far. Sadly it would probably take me months if not years to figure out what some of you could probably conjure up in your sleep.


EOF
*/



Thank you for taking time to read this!
 
Nothing in Trainzscript is easy. ;) Debugging tools are virtually non existent so you need to proceed incremental steps much like Andi's code in the WiKi tutorials. Those tutorials are actually out of date and need an update to match changes to the standard script libraries.

The only actual time function I know of is this function in the library script interface.gs. It's used in Andi's HelloWorld example. This is the definition:

Code:
  //=============================================================================
  // Name: GetTimeStamp
  // Desc: Returns the current real-world time, represented as seconds elapsed
  //       since midnight (00:00:00), January 1, 1970, coordinated universal time
  //       (UTC). Note that the return value is a string as this value no longer
  //       fits in a signed 32 bit integer, and gsc does not support any extended
  //       integer types.
  //=============================================================================
  public native string GetTimeStamp(void);


The first problem is that it returns a string and, when I ran it in a test script, I got:

; <NULL> : Interface.Print> 'Hello World, Good Afternoon - 1704350844'

The string at the end is the number of seconds since Jan 1, 1970. That's a lot of seconds.

Your problem is that the string will need to be converted to an integer or float to do the necessary math to get whatever time values are of interest to you.
In your test code you need only reference world.gs and those existing constants/definitions will be available to you. I would probably:

1. Convert the string to something you can work with.
2. Calculate the year taking into account leap years.
3. Calculate the month and day.
4. Finally calculate the hours, mins and seconds.

Sounds like an exercise a first year software engineering student might be assigned. :) Not especially difficult but tricky.

Here's some tips for you. Find the script libraries in your Trainz installation folder and take a copy of all the gs files and put them somewhere else to use as a reference. Making a copy is a good idea as examining those files could easily result in the file being changed. That can cause Trainz to crash.
When you are looking for functions/methods, those files will be more up to date than the corresponding WiKi pages. There is also more information in those files than on the WiKi pages.
There have been some substantial changes to base library scripts in TS19 and TS22 and relying on code made for earlier versions can result in errors for obsolete or deprecated functions/methods.
If are going to be serious about writing scripts then you should probably turn off compatibility mode in the Trainz settings while testing. Turn it back on when finished.
 
Thank you Paul! Time to knock off the cob webs from my programming knowledge* and implement your recommendations. 😁

* Learned BASIC (with my parents, many nights on a TR(a)S(h)-80 typing in various programs to play very simple games); FORTRAN, C, C++, and Java as part of college courses; self taught in MS-DOS Batch files, HTML, and some CSS and a sprinkle of JavaScript.
 
Thank you Paul! Time to knock off the cob webs from my programming knowledge* and implement your recommendations. 😁

* Learned BASIC (with my parents, many nights on a TR(a)S(h)-80 typing in various programs to play very simple games); FORTRAN, C, C++, and Java as part of college courses; self taught in MS-DOS Batch files, HTML, and some CSS and a sprinkle of JavaScript.
Much more experience than most attempting to learn Trainzscript. ;) Never owned a TRS80 but had a TI99/4 and TI99/4A before PCs arrived. Most of my software experience was pascal, Ada, some Cobol (ugh) and C/C++. I have a bit of a mental block with Python as it ignores all the tight type casting of languages such as Ada. But I occasionally play with it because of using Blender.

Trainzscript (originally Gamescript) is mostly about changing the characteristics of an object so you will never write a program that becomes an executable. Most of my test code, such as the time check stuff, I attach to a scenery object which can literally be a cube. When you place the scenery object in a scene, the Init() function will be called so you can just output stuff to the logs using Interface.Print().

Good luck with your endeavours. You can find me in the Trainz Discord server with the same user name if you have any questions.
 
pcas1986: I came from a similar background, but I had Commodore hardware. I program, so I might be able to help you there. I can write esoteric stuff in *.gs files; I just can`t handle the easy stuff. I once wrote a Trainz library with extensive debugging output of internal data and not much else, YET, except I lost it when Windows XP decided to eat my data partition. (Everything is still there, but nothing can find it except a Python script that I wrote. Unfortunately, I lost the reference document I was using before I could complete the script.) If you are interested in trading *.gs basics for Python basics, let me know and I`ll contact you outside of the public forums and try to help.

To the original poster: I`m not familiar with anything like either of those, but they both look like they would be easy to write, if only I hadn`t forgotten all of the easy stuff.
 
pcas1986: I came from a similar background, but I had Commodore hardware. I program, so I might be able to help you there. I can write esoteric stuff in *.gs files; I just can`t handle the easy stuff. I once wrote a Trainz library with extensive debugging output of internal data and not much else, YET, except I lost it when Windows XP decided to eat my data partition. (Everything is still there, but nothing can find it except a Python script that I wrote. Unfortunately, I lost the reference document I was using before I could complete the script.) If you are interested in trading *.gs basics for Python basics, let me know and I`ll contact you outside of the public forums and try to help.

To the original poster: I`m not familiar with anything like either of those, but they both look like they would be easy to write, if only I hadn`t forgotten all of the easy stuff.
Thank your for the offer and I'll keep it in mind, however at present I don't have any Python projects in mind but rather trying to get my head around character animation in Blender. Harder than it looks. I have a Blender addon called Serpens that generates Python code for menus and limited Blender operations.
My other Trainz related programming activity is writing pascal programs in Lazarus. I have a pet program for manipulating images for Trainz materials such as PBR.
I'm happy to help out with Trainzscript code snippets. I do that quite often but mostly on Discord.
 
pcas1986: I`m not on Discord, and not much interested in adding new social media. What I`m interested in are things like a rule that runs cleanly but doesn`t actually DO anything, that I can use as a starting point for my own rules that DO do things, and similar for other types of scripted assets: just fully-functional do-nothing scripts. Heck, they don`t even need the various support files, as long as I know what is missing.

Trying to keep this relevant to the original poster, I`d be interested in getting some practice under my belt by taking such an empty rule and turning it into a rule that allows one to set the game clock digitally instead of using a clunky analog widget. Heck, I might even post it for consideration by the DLS maintainers as my first-ever *published* asset. You (or anyone else) have a free-to-use Rule Template in either of your back pockets? My own templates got eaten by WinXP years ago.
 
Guys, I just found a host of tutorial/documentation pages on the Wiki. I`ll try to use them to get up-to-speed enough to try this as a practice asset. Do you think the DLS would be interested?
 
Guys, I just found a host of tutorial/documentation pages on the Wiki. I`ll try to use them to get up-to-speed enough to try this as a practice asset. Do you think the DLS would be interested?
I suggest your practice asset will get lost in the DLS but you could do that.
IMO a better idea would be to host the sample scripts in the Trainz WiKi together with an explanation of usage. You could then point to your asset on the DLS as an example of a working asset.

@MasterTracklayer - I've never published a rule so they are mostly unknown territory to me. Some time ago I did look at a weather rule that Pitkin initiated but never got very far with it. There are several rule specialists with assets on the DLS that you can look at providing the scripts are not encrypted.
 
I wrote at least one functional rule back when I was running Trainz Simulator 2 Pack (TS2009/2010) on a different machine; I`m just rusty because it has been so long since I`ve done anything like that. I also attempted to write one (1) empty rule since downloading Trainz22 almost a month ago, and while I don`t recall testing it, it at least appears to have compiled cleanly when I imported it into my local trainzbase. Meanwhile, since posting the message you quoted, I have integrated the Hello World tutorial in the Wiki into a copy of that empty rule, but I have not attempted to validate/test the rule for reasons that are detailed at length in my thread "Asset Database Backup: Wow! Over 20,000 files!" Still, my rusty wheels are starting roll, albeit still with a loud rust-on-rust squeal. I`m tryin`. I`ve also read through the asset-creation tutorial also on the Wiki, and things are *starting* to come back to me. I still need to read up a little more before I can make any real progress on this rule. I want to at least skim a rule-writing tutorial first, and I think I found one of those on the Wiki too, but right now I think that I am a little too tired for much of it to stick. I *am* building up a list of bookmarks into the Wiki, though. :D
 
Back
Top