View Full Version : How to obtain in-game time?
moggel
05-16-2012, 08:34 AM
I'm still experimenting with scripting stuff for the sim and I've come across a problem I haven't found a solution for: How do I get the in-game time?
I've experimented with Mission.Time but it seems all values are just offsets from the instant when the mission started. There's the concept of "real" time but that also seems to be an offset and unless I can figure out the mission start time it's of no use (at least for what I'm trying to do).
I had an idea that maybe I could read the start time from the main mission file by loading it as a section file but there doesn't seem to be a way to figure out the file name for it.
Has anyone figured any of this out?
41Sqn_Banks
05-16-2012, 09:50 AM
Yes reading the section file would be possible. You have to specify the name and path of the file though.
moggel
05-16-2012, 03:20 PM
Yes reading the section file would be possible. You have to specify the name and path of the file though.
That's the problem: I dunno which .mis file represents the current (main) mission. Is there a way to resolve that?
Smokeynz
05-16-2012, 09:32 PM
I'm trying to solve a similar(maybe the same objective) with real time at the moment to be able to reset a mission without reloading it. As you mention mostly we are dealing with Time.current() from the start of mission to cycle or run timers. It is not in game realtime.
In old IL2 it was tod (time of day) and you could just send a new time of day to the server or host by console or script.
I have found the following, I'm not sure if they are the same as Time.current()
ITime()
GamePlay.gpTime()
GamePlay.gpTime().current()
But up to now I haven't been able to parse them to a "reporting" hud or serverlog to see what they report. They wont convert to a string, int or double. (I think I'm just doing it wrong at present due to not knowing syntax).
Once we know what it is by type, in theory we should be able to alter gpTime()
Another way I have been considering is to create a section file of the "TIME" set out in the mis file under [MAIN] (I already do this with a number of other things). However this may not work as new sub missions ignore sections of sub missions including the Time value.
Because of this battle may need to be stopped to invoke a time change. In which case just reloading the main mission with an altered TIME may work, the catch is the CS itself, you can't run 2 occurances of the same CS and if you destroy the CS you are in you can't restart unless you monitor externally, like with clod commander....but this is clumsy just to reset the time!
I'm sure it is realtively simple once we identify the syntax and gameplay code to work with.
Might need help from the experienced coders on this one.
Smokeynz
05-16-2012, 09:43 PM
This (needs checking), may work as to load a 6am time value by section file.
GamePlay.gpPostMissionLoad(CreateNewTime()); // loader placed in statement to trigger when required(inside timetick section)
// section file to load, sits outside timetick section
internal ISectionFile CreateNewTime()
{
ISectionFile newtime = GamePlay.gpCreateSectionFile();
newtime.add("MAIN", "TIME 6", "");
return newtime;
}
moggel
05-17-2012, 01:26 PM
I'm trying to solve a similar(maybe the same objective) with real time at the moment to be able to reset a mission without reloading it. As you mention mostly we are dealing with Time.current() from the start of mission to cycle or run timers. It is not in game realtime.
In old IL2 it was tod (time of day) and you could just send a new time of day to the server or host by console or script.
I have found the following, I'm not sure if they are the same as Time.current()
ITime()
GamePlay.gpTime()
GamePlay.gpTime().current()
But up to now I haven't been able to parse them to a "reporting" hud or serverlog to see what they report. They wont convert to a string, int or double. (I think I'm just doing it wrong at present due to not knowing syntax).
Once we know what it is by type, in theory we should be able to alter gpTime()
Another way I have been considering is to create a section file of the "TIME" set out in the mis file under [MAIN] (I already do this with a number of other things). However this may not work as new sub missions ignore sections of sub missions including the Time value.
Because of this battle may need to be stopped to invoke a time change. In which case just reloading the main mission with an altered TIME may work, the catch is the CS itself, you can't run 2 occurances of the same CS and if you destroy the CS you are in you can't restart unless you monitor externally, like with clod commander....but this is clumsy just to reset the time!
I'm sure it is realtively simple once we identify the syntax and gameplay code to work with.
Might need help from the experienced coders on this one.
In my little experiment I've been reading those values. They are all of type 'double' and reflects the number of seconds elapsed since the mission started. So far I haven't been able to find any way to figure out the in-game time (what the pilot reads from the dashboard clock). If only there was a way to get the mission start time it would be a simple matter of adding the GamePlay.gpTime() value to the start time to get the in-game time. But I have not been able to find a way to obtain the mission start time and that's where I'm stuck at the moment.
Ataros
05-17-2012, 07:06 PM
That's the problem: I dunno which .mis file represents the current (main) mission.
Why? Time is set in the main mission file IIRC.
Smokeynz
05-17-2012, 09:16 PM
Ataros, I see 2 reasons for needing ingame "realtime" as opposed to mission run time.
1. If you want to create timelapse over shorter mission time.
For example: Each hour step forward 3 hours.
So during game play of 2~3hours, you could have morning, mid day, dusk and evening.
2. If you want to reset the day, which is actually how clod works.
In theory you can run 24/7 on one "map" layout, which means either night missions(many can't be arsed with that) or being able to reset the time to mission start or some other time.
Btw I tested tod by entering tod into the console, "Shift-Tab" type tod, enter and the console reports the game real time, as IL2 used to.
But I can't find tod in clod, only the Time(), ITime().
During the IL2 series tod shifted between accessable to alter and not accessable to alter between releases.
So ingame realtime is there as tod(via console), but probably not accessable or alterable by game script.
btw I tested my little code snipet above to enter a new section time and this fails as I predicted.
moggal, another and relatively simple way to establish ingame realtime is to gather the mission time by streamreader, then add runtime to the mission start time, there by infering the realtime.
There is probably a way to check "tod" directly, just don't know the syntax to interigate the host/server for tod.
moggel
05-18-2012, 08:42 AM
Why? Time is set in the main mission file IIRC.
Because the stuff I'm writing needs to be built to work with any mission. I'm building a simulated "Fighter Command" for MP use and the solution needs to be working with whatever mission the server operator is setting up. The reason I want in-game time is because I would like to simulate the British Sector Clock (http://en.wikipedia.org/wiki/Sector_clock), color coding all reports as they where back in the day.
Ataros
05-18-2012, 11:34 AM
C# should be able to read file names from a given folder I think but I may be wrong.
There was a mission posted here called Mission Loader that can read mission filenames. Banks' COOP lobby can do this too IIRC.
Smokeynz
05-18-2012, 12:09 PM
Moggel, I can sort that code out, Ill do it over weekend.
I have a script in development where I read data like this from mis files all over the place, a simple mod to a section I should be able to gather what you want.(doesn't help me though) But will help you.
Ataros, I have includded a modified version of the missionloader(because it works well) into my current script, going to post it soon once I sort out some stuff...stuff is of course never finished ;)
Smokeynz
05-19-2012, 05:12 AM
Ok here is a mission timer (Attached)
Reports Mission design TIME value by reading mis data directly.
Reports Ingame run timer, Mins, Seconds,Ticks
Reports Time from Mission TIME + run time(in decimal mins)
Note Config in system folder,
Config:
"timeIO", "ON"
"timevalue", "15"
set "timeIO", "ON" = runs timer,
set "timeIO", "OFF" = turns off timer,
set "timevalue", "15" = seconds between count and screen reporting.
Rerun mission to activate new time values
note download the attached Mistimer.zip, as it contains correct setup
Note: drop MisTimer into missions folder and run from there.
here is the script for those interested,
Please report bugs if found. seems to work though.
enjoy.
/**MisTimer.cs**/
//
//C# script for CLOD missions,
//Features:
//Configlist: for easy setup "ON" runs timer, "OFF" turns off timer, timevalue = seconds between count and screen reporting.
//
//By Smokeynz
//
//lastmod 19/5/2012
//Dedicated server compatible
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.IO;
using maddox.game;
using maddox.game.world;
using maddox.GP;
public class Mission : AMission
{
/*=========================================*/
#region Mission paths
/*=========================================*/
static string userdocpath = Environment.GetFolderPath(Environment.SpecialFolde r.Personal);
/*=========================================*/
// the following 2 items are for main mission folder path and mis name, edit for preference
static string MISname = "MisTimer.mis"; //alter this to your mission name
static string FILEname = "MisTimer"; //alter this to your mission folder name
/*=========================================*/
static string filepackpath = userdocpath + @"\1C SoftClub\il-2 sturmovik cliffs of dover\missions\"; //path to mission file pack
static string mainmissionpath = filepackpath + FILEname + @"\"; // main mission
//configs
static string syspath = mainmissionpath + @"system\"; // data path for system config
static string configfile = syspath + "config.txt";
//loading mission path data
static string timefile = mainmissionpath + MISname;
/*=========================================*/
#endregion
/*=========================================*/
#region Declarations, ints, doubles, bools
/*=========================================*/
//Msgs To
private const int All = -1;
private const int Allies = 1;
private const int Axis = 2;
bool timeIO;// = true; //time indicator switch on/off
double timevalue;
double timeindicator;
double MisHour;
double MisMin;
//config file indexing
int idxIO;
int idxTV;
// Internal file creation
public int idxlist;
/*=========================================*/
#endregion
/*=========================================*/
#region Mission Parse & Class
/*=========================================*/
// mission config settings(Allows external configuration)
List<Config> ConfigList = new List<Config>();
internal class Config
{
public string ConfigName { get; set; }//item name
public string ConfigValue { get; set; }//item value
public Config(string configName, string configValue)
{
this.ConfigName = configName;
this.ConfigValue = configValue;
}
}
public void ParseConfigFile(string confile)
{
if (!File.Exists(confile))
{
GamePlay.gpLogServer(null, "File {0} not found!", new object[] { confile });
return;
}
using (StreamReader reader = new StreamReader(confile))
{
string conline;
int conlineNr = 0;
while ((conline = reader.ReadLine()) != null)
{
conlineNr++;
if (conline != "")
{
string[] tmpconPart;
conline = conline.TrimStart('"'); // remove first "
conline = conline.TrimEnd('"'); // remove last "
tmpconPart = conline.Split(new string[] { "\", \"", "\",\"" }, StringSplitOptions.None); // split string on ", " or ","
if (tmpconPart.Length < 2)
{
GamePlay.gpLogServer(null, "Error reading configlist file: {0} : {1}", new object[] { conlineNr, conline });
}
else
{
if (tmpconPart[0].Equals("null"))
tmpconPart[0] = null;
if (tmpconPart[1].Equals("null"))
tmpconPart[1] = null;
ConfigList.Add(new Config(tmpconPart[0], tmpconPart[1]));
}
}
}
}
idxIO = ConfigList.FindIndex(r => r.ConfigName.Equals("timeIO"));
idxTV = ConfigList.FindIndex(s => s.ConfigName.Equals("timevalue"));
double.TryParse(ConfigList[idxTV].ConfigValue, out timevalue);
}
public void ParseTimeDataFile(string Tfile)
{
if (!File.Exists(Tfile))
{
GamePlay.gpLogServer(null, "File {0} not found!", new object[] { Tfile });
return;
}
using (StreamReader reader = new StreamReader(Tfile))
{
string line;
int lineNr = 0;
while ((line = reader.ReadLine()) != null)
{
lineNr++;
if (line != "")
{
if (line.Contains("TIME"))
{
string[] tmptime = line.Split(new string[] { " " }, StringSplitOptions.None); // split string
if (tmptime.Length < 3)
{
GamePlay.gpLogServer(null, "Error reading Time object line : {0} : {1}", new object[] { lineNr, line });
}
else
{
GamePlay.gpLogServer(null, "Time Line Split 0:{0} 1:{1} 2:{2} 3:{3}", new object[] { tmptime[0], tmptime[1], tmptime[2], tmptime[3] });//test reading
string[] tmptime2 = tmptime[3].Split(new string[] { "." }, StringSplitOptions.None); // split string
if (tmptime2.Length < 2)
{
double.TryParse(tmptime2[3], out MisHour);
}
else
{
GamePlay.gpLogServer(null, "Time Line Split 0:{0} 1:{1}", new object[] { tmptime2[0], tmptime2[1] });
double.TryParse(tmptime2[0], out MisHour);
double.TryParse(tmptime2[1], out MisMin);
if (MisMin < 10) { MisMin = MisMin / 10; }
if (MisMin > 9) { MisMin = MisMin / 100; }
}
}
}
}
}
}
}
/*=========================================*/
#endregion
/*=========================================*/
#region Main mission operation
/*=========================================*/
//listen to events from all missions.
public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;
ParseConfigFile(configfile);
ParseTimeDataFile(timefile);
}
public override void OnTickGame()
{
base.OnTickGame();
// Time.current() in seconds from Battle Start
timeIO = (ConfigList[idxIO].ConfigValue == "ON" ? true : false);
if (timeIO == true)
{
if (Time.current() >= timeindicator)
{
double MisTime = MisHour + MisMin;
ScreenMsg(-1, "MisStart:: " + MisTime + " decimalhours");
Timeout(2.0, () => { ScreenMsg(-1, "Elapsed Time:Min:" + timeindicator / 60 + " Secs:" + timeindicator + " Ticks:" + timeindicator * 30); });
MisTime = Math.Round((MisHour + ((MisMin*60) + (timeindicator / 60)) / 60), 2);
Timeout(4.0, () => { ScreenMsg(-1, "MisTime:: " + MisTime + " decimalhours"); });
}
}
if (Time.current() >= timeindicator)
{
timeindicator = timeindicator + timevalue;
}
}
/*=========================================*/
#endregion
/*=========================================*/
#region ScreenMsg screen message
/*=========================================*/
private void ScreenMsg(int army, string msg, params object[] args)
{
List<Player> Consignees = new List<Player>();
if (GamePlay.gpPlayer() != null)
Consignees.Add(GamePlay.gpPlayer());
if (GamePlay.gpRemotePlayers() != null)
Consignees.AddRange(GamePlay.gpRemotePlayers());
if (army == -1)
{
GamePlay.gpHUDLogCenter(null, msg, args);
GamePlay.gpLogServer(null, msg, args);
}
else if (Consignees.Exists(item => item.Army() == army))
{
GamePlay.gpHUDLogCenter(Consignees.FindAll(item => item.Army() == army).ToArray(), msg, args);
GamePlay.gpLogServer(Consignees.FindAll(item => item.Army() == army).ToArray(), msg, args);
}
}
/*
private void sendChatMessage(int army, string msg, params object[] args)
{
List<Player> Consignees = new List<Player>();
if (GamePlay.gpPlayer() != null)
Consignees.Add(GamePlay.gpPlayer());
if (GamePlay.gpRemotePlayers() != null)
Consignees.AddRange(GamePlay.gpRemotePlayers());
if (army == -1)
GamePlay.gpLogServer(null, msg, args);
else if (Consignees.Exists(item => item.Army() == army))
GamePlay.gpLogServer(Consignees.FindAll(item => item.Army() == army).ToArray(), msg, args);
}
*/
/*=========================================*/
#endregion
/*=========================================*/
}
//note the last bracket wraps Amission
moggel
05-21-2012, 01:58 PM
C# should be able to read file names from a given folder I think but I may be wrong.
There was a mission posted here called Mission Loader that can read mission filenames. Banks' COOP lobby can do this too IIRC.
Yes, reading files from a specified folder is quite easy. Just call System.IO.Directory.GetFiles(<user's IL-2 missions folder>, "*.mis") and you'll get a nice array of strings representing all missions found.
But since I don't know which file is the one containing the current main mission I don't have much use for it. Hard coding the name of the mission into every mission file is not the way I want it to work since that would force the server operator to open up the mission .cs files and fiddle with its content. That, in turn, requires coding skills and presents a big risk he/she will corrupt the mission.
Instead, I'm aiming for a solution where all "extensions" (like "Fighter Command") can be installed from installation packages using a graphical installer, just like we're used to install normal desktop applications.
I wrote the coding framework for this (and the installer) a few week back and "Fighter Command" will be the first extension for it followed by "Live Map" (which automatically populates the landscape with traffic, livestock etc as the player flies over the map). The "framework", which I call "IL2X" right now seems to be stable and allows the coder to write code like he/she is used to, splitting up all code into libraries which can be reused and distributes automatically. Also, you can use normal runtime debugging in Visual Studio, setting up breakpoints or tracepoints to figure out how the sim works and for hunting down bugs in the code if need be. It works fine right now but needs more testing before I present it to the forums (hopefully within a week or two :rolleyes:)
So (sorry for the digression), what I'm really looking for here would be something like: "myMission.GamePlay.gpCurentFileName()" or something similar to it. I have not been able to find it though...
FG28_Kodiak
05-21-2012, 04:47 PM
There is no way to get the MissionfileName from a script (i am looking for it too), via CloDo - API
It would be possible (i think) if we can create Addins for Multiplayer, to get the current directory.
IGame:
gameInterface.ToFileSystemPath(..)
moggel
05-21-2012, 05:02 PM
There is no way to get the MissionfileName from a script (i am looking for it too), via CloDo - API
It would be possible (i think) if we can create Addins for Multiplayer, to get the current directory.
IGame:
gameInterface.ToFileSystemPath(..)
What is CloDo - API? Linky? :)
FG28_Kodiak
05-21-2012, 05:10 PM
I call the managed Dlls CloDo-API. Cliffs of Dover Application Programming Interface ;)
moggel
05-21-2012, 05:42 PM
I call the managed Dlls CloDo-API. Cliffs of Dover Application Programming Interface ;)
Silly me! :-P
moggel
05-21-2012, 06:08 PM
There is no way to get the MissionfileName from a script (i am looking for it too), via CloDo - API
It would be possible (i think) if we can create Addins for Multiplayer, to get the current directory.
IGame:
gameInterface.ToFileSystemPath(..)
Sounds interesting. Where can I obtain IGame objects? I've found the type and apparently it inherits from IGamePlay. If I set a breakpoint in OnTickGame and cast it to IGame I do get an object but the IGame.BattleScriptFileName property is always null. I performed the test in SP mode. I then tried doing the same from OnBattleStarted() and OnBattleInit() but those never gets called.
I then performed the exact same test running a server thinking that maybe a "battle" is what gets started when you type "battle start" in the server console but ... no.
When are those methods called anyway?
By the way: I think we should set up a scripting WIKI...
Ataros
05-21-2012, 06:54 PM
If a server owner starts his mission via script (TAB-4) or a Server Commander, the script or the commander will 'know' which file the server owner started I guess.
FG28_Kodiak
05-21-2012, 07:02 PM
When are those methods called anyway?
Thats the problem in the GUI (gamePages, take a look at the tstcampaign). So wie need a addin to get access to it, or the devs creates a methods so it would be easier for us. :rolleyes:
Smokeynz
05-21-2012, 09:06 PM
If you can figure out how to call the console( As per in game pilot manual Shift-tab enter tod) and enter "tod" you can gather the "time of day" which is the mission time at that point from mission start.
It is currently hard coded, that is, cannot be altered as per IL2-46(although this was un alterable between patches even for 46)
vBulletin® v3.8.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.