PDA

View Full Version : Sal's useful scripts [random mission weather]



Salmo
Feb-12-2014, 04:22
Maybe between RedDog & myself we can get mission builders to produce a better class of missions .....

Mission weather can be set in FMB when you make your mission, but there's no way to change the weather "on the fly" to avoid the same old weather every time the mission runs. Well, not so. Here's a script that will randomise mission weather each time the mission runs. So how does it work? It works by reading the mission text file every time the mission runs; the weather section of the mission file is then randomly changed & a new mission file is written over the top of the mission file that is loading. The game & windows does not seem to mind you doing this. Voila! Next time the mission runs, it starts with a different set of weather conditions & overwrites with the next random weather set.




using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis"); // MyMissionName is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 1500, 3000); // cloud height 1500m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180 / Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
double WindSpeed = 99;
while (DirMET < -180 || DirMET > 180 || WindSpeed > 5.9)
{
// random meteorological wind coordinates, right handed with respect to an upward +Wmet.
uMET = RandomDoubleBetween(-7, 7); // 7 m/s max
vMET = RandomDoubleBetween(-7, 7); // 7 m/s max
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI
WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2)); // m/s
}

// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter("tmpWeather.mis", true); // a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3 + 1);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3 + 1);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace("tmpWeather.mis", missionfile, null); // rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion

public double RandomDoubleBetween(double fMin, double fMax)
{
double result = random.NextDouble() * (fMax - fMin) + fMin;
return result;
}
}

Kling
Feb-12-2014, 05:13
this is awesome!!!
Will add alot to make difference between missions!
Well done!

SoW Reddog
Feb-26-2014, 11:05
Thanks for this Salmo.

Weather, clouds and wind is something that's completely new to me so I'll be using this in my upcoming mission. I think I'll make weather change based on a % chance and on a kind of linear scale, so if it starts with light clouds, the next mission might be clear, or have heavier clouds, the wind might get up or die down but not jump from calm to gale in one step.

No.401_Wolverine
Feb-26-2014, 12:59
Would be great to use this randomized weather. A few questions for you..

public RandomiseMissionWeather produces an error regarding return type (must have return type).

Using C:\Users\... produces unrecognized escape sequence errors.

The UseRandomWeather bool statement is never used in this script. Is there a condition missing? if (UseRandomWeather) inside the public override void init part of the script for example?

Also no declaration of the string 'result' in the script, so it doesn't exist?

Asking because I'm having trouble getting it to work. I'll keep trying and update if I do get it functional.

Salmo
Feb-26-2014, 17:53
Would be great to use this randomized weather. A few questions for you..

public RandomiseMissionWeather produces an error regarding return type (must have return type).

Using C:\Users\... produces unrecognized escape sequence errors.

The UseRandomWeather bool statement is never used in this script. Is there a condition missing? if (UseRandomWeather) inside the public override void init part of the script for example?

Also no declaration of the string 'result' in the script, so it doesn't exist?

Asking because I'm having trouble getting it to work. I'll keep trying and update if I do get it functional.

Sorry for the errors, I slightly modified the script 'on the fly' from my original which returned a string confirmation message to the MP console.

1. public RandomiseMissionWeather(string missionfile) should be public void RandomiseMissionWeather(string missionfile)

2. Using C:\Users\... produces unrecognized escape sequence errors - C# doesn't like backslashes in strings. Try using an @ symbol in front of the string. ie. @"My\Mission\Path"

3. bool UseRandomWeather is a switch to turn radmom weather on/off, I didn't include the IF statement. bool UseRandomWeather line can be removed.

4. String 'result' was the return string to the MP console. Can be deteled, not needed.

Script in 1st post chnaged/updated.

ATAG_Lolsav
Mar-04-2014, 16:26
Hi Salmo, found out a minor bug:

On


RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis"));

It has a extra ")"

Edit: Implemented sucessfully on test mission

Salmo
Mar-04-2014, 20:02
Hi Salmo, found out a minor bug:

On


RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis"));

It has a extra ")"

Edit: Implemented sucessfully on test mission

Thankyou Lolsav, 1st post updated with corrections.

No.401_Wolverine
Mar-05-2014, 00:32
Yep. Got it working as well. Needed to make a change to avoid some System.Exceptions though.

Where the script says "tmpweather.mis" I had to specifically direct the file path thusly:

@"C:\ (blah blah blah) missions\Multi\Dogfight\tmpWeather.mis"

After doing that it worked fine. I find using these lines at the start of your scripts help a lot for defining file paths (got the method from Kodiak's scripts):


private static string userdocpath = Environment.GetFolderPath(Environment.SpecialFolde r.MyDocuments);
private static string CLODO_FILE_PATH = userdocpath + @"\1C SoftClub\il-2 sturmovik cliffs of dover - mod\";
private static string FILE_PATH = @"missions\Multi\Dogfight\yourmissionname.mis";
private static string MISSION_FILE = CLODO_FILE_PATH + FILE_PATH;

That way, whenever you need to reference your mission file path in a script, you can just use MISSION_FILE or the other defined path fragments instead of having to write out the whole file path in string notation.

So, for example, in the weather script, for the tmpweather.mis file, I replaced
@"C:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\tmpweather.mis"
with
CLODO_FILE_PATH + @"missions\tmpweather.mis"

And also where the script calls the function RandomiseMissionWeather, I only need to write
RandomiseMissionWeather(MISSION_FILE);

Salmo
Mar-05-2014, 01:23
Yep. Got it working as well. Needed to make a change to avoid some System.Exceptions though.

Where the script says "tmpweather.mis" I had to specifically direct the file path thusly:

@"C:\ (blah blah blah) missions\Multi\Dogfight\tmpWeather.mis"

After doing that it worked fine. I find using these lines at the start of your scripts help a lot for defining file paths (got the method from Kodiak's scripts):


private static string userdocpath = Environment.GetFolderPath(Environment.SpecialFolde r.MyDocuments);
private static string CLODO_FILE_PATH = userdocpath + @"\1C SoftClub\il-2 sturmovik cliffs of dover - mod\";
private static string FILE_PATH = @"missions\Multi\Dogfight\yourmissionname.mis";
private static string MISSION_FILE = CLODO_FILE_PATH + FILE_PATH;

That way, whenever you need to reference your mission file path in a script, you can just use MISSION_FILE or the other defined path fragments instead of having to write out the whole file path in string notation.

So, for example, in the weather script, for the tmpweather.mis file, I replaced
@"C:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\tmpweather.mis"
with
CLODO_FILE_PATH + @"missions\tmpweather.mis"

And also where the script calls the function RandomiseMissionWeather, I only need to write
RandomiseMissionWeather(MISSION_FILE);

Thanks Wolvie, that exactly how I use the function, but I changed it so it would be easier for those who are less experienced with script work.

keeno
Mar-05-2014, 07:28
Hi guys,

I really enjoy messing around with FMB but know nothing of code so I'm hoping to copy and paste this weather generator into a home made mission. I've copied and pasted using notepad into my mission file. I've given the file a .cs extension and the same name as the mission "He 111 bomb training". I've changed the file path to the mission onto the weather generator code on the copied note pad but each time I go to "play mission" the game crashes due to an unexpected C+ runtime error.

any ideas, I'd really love to get this working.

cheers

keeno
Mar-05-2014, 07:33
Hi again, this is what I have as my "He 111 bomb training.cs" file. Can anyone spot my error? thanks again for this as I really am clue-less and simply trying to copy.

Cheers



public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\He 111 bomb training.mis"); // MyMissionName is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 1500, 3000); // cloud height 1500m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180/Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
while (DirMET < -180 || DirMET > 180)
{
uMET = random.NextDouble() * (1 - -1) + -1; // positive Umet is wind blowing to the East.
vMET = random.NextDouble() * (1 - -1) + -1; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI

}
// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter("tmpWeather.mis", true); // a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace("tmpWeather.mis", missionfile, null); // rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion
}

Salmo
Mar-05-2014, 07:38
Hi guys,

I really enjoy messing around with FMB but know nothing of code so I'm hoping to copy and paste this weather generator into a home made mission. I've copied and pasted using notepad into my mission file. I've given the file a .cs extension and the same name as the mission "He 111 bomb training". I've changed the file path to the mission onto the weather generator code on the copied note pad but each time I go to "play mission" the game crashes due to an unexpected C+ runtime error.

any ideas, I'd really love to get this working.

cheers

Let's take this one step at a time.

a. You say you've copied the the script in the 1st post of this thread into your mission file. That's the wrong thing to do, & probably why you're geeting a C error.

1. make your mission in FMB. Save your mission as "He 111 bomb training". If you go to the folder where you saved the mission you will notice it's named "He 111 bomb training.mis"

2. Now open notepad (or another text editor) & copy/paste the script from the 1st post. Save the file in the same folder as your mission file, but call the file "He 111 bomb training.cs".

3. You now have TWO files. ONE mission file & ONE script (cs) file.

4. Now run your mission. When a mission runs the game will automoatically look for a *.cs file of the same name as the mission file in the same directory. If it finds one, then it runs the script with the mission.

ATAG_Lolsav
Mar-05-2014, 07:41
On top of Salmo script, before evrything you need to tell the game what libraries its using:


using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Reflection;
using maddox.GP;
using System.Text.RegularExpressions;

Put all those on the very top of the script

Salmo
Mar-05-2014, 07:43
..... Can anyone spot my error? ....

Yep! You've missed putting the references to C# libraries at the start of your script. Actually I missed putting it in the 1st post beause I was just posting the function ....

Put this at the start of the script above the AMission line ...



using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;


1st post updated.

[EDIT] Ha! Lolsav beat me to it, thanks mate :)

keeno
Mar-05-2014, 08:02
Really, really great and thanks for the speedy replies.

Its difficult to explain sometimes what you (I) mean when you (I) don't know what you're (I'm) talking about. I believe I do have the filing correct .mis and .cs etc but I'll try and add the suggested text at the top of the weather generator file and give hat a go.

I'll let you know how I get on.

Thanks again, much appreciated.

keeno
Mar-05-2014, 08:11
Yes, excellent,

the mission starts!!!!!.

Question one: does this generator only affect wind and direction? I started he mission three times and each time it was brilliant sunshine with no clouds?

Question two: if I copy other pieces of script for other missions, do I always have to add the piece I missed for this one at the top of the script?

sorry if these questions seem a little dumb, Derrrr!!!!!!!

Thanks again chaps.

No.401_Wolverine
Mar-05-2014, 12:16
If you've got a mission already created with a script, the
using System.IO; is probably the critical one for this script as it holds the streamreader / streamwriter stuff that is required. You'll need a few of the others as well in the natural course of things, but this one in particular.

keeno, you might be encountering the same issue I did. Do a find/replace with these parameters (include the " marks in your search/replace):

find: "tmpWeather.mis"
replace with: @"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\tmpWeather.mis"

Also, you have a space between the 1 and the C in 1C SoftClub in your file path of the script you pasted here. I don't think there's a space there, but double check the way your folder structure is to make sure.

keeno
Mar-05-2014, 13:56
Wolverine, thanks for the reply,

I've got the mission to work, my new question is, Does the generator only affect wind speed, direction etc as I're ran the mission 3 times and each time the weather is bright sunshine with no clouds, i was expecting differing cloud conditions.

Cheers

No.401_Wolverine
Mar-05-2014, 15:31
From the sounds of it, the script isn't working. The mission runs, but a mission running isn't necessarily an indicator that the script associated with it is working correctly. While technically possible that the randomization has led to you getting sunny clear weather several times in a row, it is...unlikely.

Check the time on the dash clock of your aircraft when you run the mission. If the clock is always reading the same time and the weather is always the same, then the script is not working.

If the above is true, try the things I outlined in my previous post. It should be pretty obvious if the script is working. Yes, cloud cover will change with Salmo's script, as will the gusts, wind, and time of day.

keeno
Mar-05-2014, 16:48
Wolverine,

thanks again for the reply. I'm at work now but will try checking the time on the mission tomorrow, I'm fairly sure it is the same as the sun position etc was identical.

but..... your original post offering help may have well been written in another language, i don't understand code or scripting, i was hoping for a cut n paste job.

would you mind giving me it again in baby talk, step by step. no probs if that's as easy as it comes, i'll try and suss it out.

Cheers again for the support.

No.401_Wolverine
Mar-05-2014, 17:16
Just look at the part where I say find and replace.

1. Open your script file (the .cs one) in notepad.

2. Go to the edit menu and select Replace...

3. In the Find what: box, put this exactly: "tmpWeather.mis"

4. In the Replace with: box, put this exactly: @"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\tmpWeather.mis"

5. Click 'Replace All' (it should tell you it replaced two things.

6. Save the file and close it.


ALSO

Check your folder path that you entered. There is no (or shouldn't be) space between 1 and C in 1C SoftClub. If you've got a space between them, remove it.

keeno
Mar-05-2014, 17:57
Cheers Wolverine,

it looks like even I could follow that!

I'll try tomorrow and see how it goes.

Ta!!

Squiz
Mar-05-2014, 19:08
Salmo, I only get clear or light cloud using ("WeatherIndex", 1, 2). However if I use ("WeatherIndex", 1, 3) then I get light cloud and medium cloud. I have no idea why.

Squiz

bolox
Mar-05-2014, 19:14
Keeno, one thing that might help track down what's isn't working with script- in (single) mission, open the console (shift tab)- this should produce a bunch of text down lhs (and pause the game)
If there is a problem with the script there will be an error message relating to it, it will even give a hint what's wrong, and line#, character where the fault(s) is.
From experience look for non paired {} brackets as well as missing 'using' statements at top of cs file mentioned by Wolverine.
Good luck

1lokos
Mar-06-2014, 00:23
LOL!

I managed to this work in some Quick Mission.
Bolox tip show where wrong at first.

Thank you.

Sokol1

keeno
Mar-06-2014, 09:56
hi Wolverine,

I followed your instruction to the letter, notepad didn't give any indications that any script had been replaced as in step 5 of your instructions but now when I hit "play mission" I get the runtime error again and CLoD shuts down. her is my .cs file as it looks now, can you see any errors?

cheers for any help.

using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\He 111 bomb training.mis"); // MyMissionName is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 1500, 3000); // cloud height 1500m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180/Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
while (DirMET < -180 || DirMET > 180)
{
uMET = random.NextDouble() * (1 - -1) + -1; // positive Umet is wind blowing to the East.
vMET = random.NextDouble() * (1 - -1) + -1; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI

}
// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\tmpWeather.mis", true); // a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\tmpWeather.mis", missionfile, null); // rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion
}

keeno
Mar-06-2014, 10:20
Mmmmmmm,

ok, now I'm really lost. I thought I'd remove the .cs notepad file from "my mission" all together and see if the mission still plays as it did before adding the random weather file but now I get the runtime error which I didn't get before adding the random weather originally.

any ideas before I give up, would I be better off starting again with a simple mission and starting off from scratch?

thanks again.

ATAG_Lolsav
Mar-06-2014, 10:26
Do me a favor. Browse to your mission file folder and on top, where it points the way to that folder, left click ahead of the name, left drag to select the full path and choose to copy. After that post it here.

1lokos
Mar-06-2014, 10:36
Keeno,

I copy your above code, past on file (using Notepad++ - the good is this program show you in red the fields to change), replace your Documents\1C Soft... path with mines, as Tiger Moth.cs (a existent single mission), and test.

Then I realize that Tiger Moth don't have onboard clock to check time... :doh:

Not big problem, just access the console and this show the mission time - different in two run - cloud layer change too. :thumbsup:

http://i60.tinypic.com/1yk4g7.jpg
Notice the line time (11.062 and 2.566 - in console minutes is in percentage).

So the only things that can be wrong in your files is in paths:



"C:\Users\Ian\Documents\1 C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\He 111 bomb training.mis"
"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\tmpWeather.mis"
"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\tmpWeather.mis"


OOPS! And the error is in the first path - BTW already pointed by No.401_Wolverine above:

Is:

"C:\Users\Ian\Documents\1 C SoftClub\...

Should be:

"C:\Users\Ian\Documents\1C SoftClub\...

See?

And assure that you have in Single folder:

He 111 bomb training.mis
He 111 bomb training.cs

Sokol1

keeno
Mar-06-2014, 13:42
hi guys and thanks for the replies.

Sorry, this must be getting tedious.

I'm at work right now but will try your suggestions tomorrow.

one thing though, although the file path on the pasted note pad text file which I attached here shows a space between the 1 and C as such:


"C:\Users\Ian\Documents\1 C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\He 111 bomb training.mis"


it doesn't show this space on the the original notepad text file i'm trying to use, which is very strange.

I'll look again tomorrow when I'm not on nightshift in case I've made a tiredness mistake.

I'll let you guys know how i get on and cheers again.

No.401_Wolverine
Mar-06-2014, 13:57
It is possible, though EXTREMELY HIGHLY unlikely, that your install directory is different from everyone elses and indeed does include a space between the 1 and C. Triple check that file path to make sure. If it does have the space, then you need to adjust all the paths that reference it to include it.

keeno
Mar-06-2014, 15:19
hey wolverine,

yea I'll check that tomorrow. I think if i can nail at least one copied script and get it to work then i'll be on to something.

so it seems the copied script is correct as others have got it to work, its my file path to my mission (He 111 bomb training) which is incorrect.

what about the fact that I've removed the .cs weather generated file completely and now the mission (minus the .cs) file will not open and recieves a runtime error, what could cause that? is it not as simple as removing the .cs file to put themission back to how it was previously?

cheers.

ATAG_Lolsav
Mar-06-2014, 15:25
A very tiny contribution from my end, in truth i only add a number, a "1"

Debugging trough the mission i realised the random weather would very rarely, or almost never, get to weatherindex 2. I know why, because the "int RandomInt" has the highest probability of beeing "1" and only 1% of beeing "2", simply because if the integer of a random number 1,9999 is 1. So the "2" for weatherindex (medium clouds) had a very rare chance to appear.

What did i do? I "cheated". I dont know how to mess with the script but i could understand the reasoning behind it, so i just add a "+1" to where the result is provided :)


while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3)+1;

No.401_Wolverine
Mar-06-2014, 16:21
Nicely worked out Lolsav. Squiz and I were wondering what was going on there.

Salmo
Mar-07-2014, 07:36
A very tiny contribution from my end, in truth i only add a number, a "1"

while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3)+1;


Well spotted Lolsav. Although your addition is slightly off. The line should read as below otherwise you'll never get the bottom bound of the random integer:


int RandomInt = random.Next(key[i].Item3 + 1);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3 + 1);

1st post updated with this change.

keeno
Mar-07-2014, 11:08
Hi all and thanks for your patience.

Ok so I decided to start over again. I made the simplest mission possible, fly a spitfire from point A to point B.

I added the random weather .cs file to the mission file so that there was a test.cs and a test.mis file in the same folder.

I followed all the steps suggested in previous posts and spotted that my file path was indeed incorrect, I believe I'd missed out a "step" in the file path.

The file path is now @"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis"

Ok, so I ran the mission and it seemed to work, but.......

every mission now takes place a 06:00hrs, even though the box I opened by pressing shift-tab on the left hand side gives different figures for time of day each time the mission is played.

I also get a runtime error each time the mission closes.

here is my test.cs file currently, any thoughts?


using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis"); // MyMissionName is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 1500, 3000); // cloud height 1500m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180/Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
while (DirMET < -180 || DirMET > 180)
{
uMET = random.NextDouble() * (1 - -1) + -1; // positive Umet is wind blowing to the East.
vMET = random.NextDouble() * (1 - -1) + -1; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI

}
// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis", true); // a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3 + 1);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3 + 1);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis", missionfile, null); // rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion
}

1lokos
Mar-07-2014, 11:14
The file path is now @"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis"

If you are using the code past in your previous post:



RandomiseMissionWeather(@"C:\Users\Ian\Documents\1 C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis"); // MyMissionName is the full path to the mission


:)

Sokol1

SoW Reddog
Mar-07-2014, 11:24
I'm confused. It was my understanding that Mission loaded time = xxxxx was the seconds taken to actually LOAD the mission. Nothing to do with the time of day the mission represents?

Oh and Keeno, for the love of God, use the CODE tags please! :)

keeno
Mar-07-2014, 11:47
hey,

1lokos, I'm using a new file path, there is no space between 1 and C

Reddog, what's a CODE tag.

please remember I just copying, I actually know nothing of what I'm trying to do.


Thanks again.

1lokos
Mar-07-2014, 12:18
I bet that this will work (maybe).

Just copy and replace in your test.cs - not in test.mis



using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis"); // MyMissionName is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 1500, 3000); // cloud height 1500m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180 / Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
while (DirMET < -180 || DirMET > 180)
{
uMET = random.NextDouble() * (1 - -1) + -1; // positive Umet is wind blowing to the East.
vMET = random.NextDouble() * (1 - -1) + -1; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI

}
// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\tmpWeather.mis", true); // a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\tmpWeather.mis", missionfile, null); // rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion
}



PS - In Colander edition in your second post above the code have a two errors, see then? :)

Sokol1

No.401_Wolverine
Mar-07-2014, 12:27
I'm confused. It was my understanding that Mission loaded time = xxxxx was the seconds taken to actually LOAD the mission. Nothing to do with the time of day the mission represents?

Oh and Keeno, for the love of God, use the CODE tags please! :)

Yes, the Mission Loaded Time is representation of the time taken to load missions or submission objects. To get the in-game time, you need to specifically put in a bit of code that will display it for you in the server messages or, like I do, just look at the clock on your aircraft's dash.

1lokos: you might want to remove the bits of the forum you accidentally copy pasted into your code or you'll end up confusing him more!

keeno
Mar-07-2014, 13:12
thanks guys, i'll give it another go.

wolverine, the spitfire clock is showing 06:00hrs every time I play the mission.

1lokos, i'll try what you suggest.

cheers

keeno
Mar-07-2014, 13:24
Thanks but the mission is still stuck at 06:00hrs and there is a banner saying "runtime error etc etc" before the mission plays although it does still open, (at 06:00hrs!)

frustrating as I know it'll something silly I've done wrong.:(

1lokos
Mar-07-2014, 14:09
To get the in-game time, you need to specifically put in a bit of code that will display it for you in the server messages or, like I do, just look at the clock on your aircraft's dash.


No code need. I forget to say, just type on console "tod" - without " " (time of day), you get a number like 9.01800303939292 - is hour and minutes in percentage.


1lokos: you might want to remove the bits of the forum you accidentally copy pasted into your code or you'll end up confusing him more!

Ops, see this, fixed. :thumbsup:


@ Keeno

See if help - the only part of your file test.cs that need change is these three lines:

- in red color the path for your mission test.mis (the mission created in FMB)
- in blue color the path for tmpWeather.mis (a trick for the script set weather for your mission test.mis)



RandomiseMissionWeather(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\test.mis)"; // MyMissionName is the full path to the mission

StreamWriter sw = new StreamWriter(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\tmpWeather.mis", true); // a writer for the new temporary

File.Replace(@"C:\Users\Ian\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Single\test\tmpWeather.mis", missionfile, null); // rename temporary mis file (tmpWeather) as


Sokol1

Salmo
Mar-08-2014, 04:41
1st post code updated. Fixed a bug where wind direction was variable but wind speed was alway less than 1 m/s. Now wind direction varies 360 degrees & wind speed varies from 0 m/s to 6-7 m/s.

keeno
Mar-08-2014, 09:28
My god you guys have the patience of a saint!!!!!!

finally it works, 3 missions, 3 different times!!!!

looks like I had a " too many somewhere, on the surface it looks like a very simple task to make it work, I guess I just don't recognise the importance of a "


Thank again for all support given, I'm off to pound the British airfields with varying weather and at different times.

Cheers.

buster_dee
Mar-21-2014, 15:11
I've followed this thread and tried to avoid the mistakes, but no time changes It always uses the mission time I originally set in FMB). Does this work in Multiplayer Dogfight missions, or is it just for Singe Player?

ATAG_Lolsav
Mar-21-2014, 15:14
buster i managed to make it available for df server... You sure you didnt skip a step? Might want to drop the code here or send it to Salmo.

1lokos
Mar-21-2014, 15:20
Salmo,

If I want limit the time frame only to daylight I change here?


// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

Sokol1

ATAG_Lolsav
Mar-21-2014, 15:24
@Sokol

Yes, ive done it on my own mission ;)

buster_dee
Mar-21-2014, 15:36
buster i managed to make it available for df server... You sure you didnt skip a step? Might want to drop the code here or send it to Salmo.
Thanks. I'll take another careful look before I bother anyone.

No.401_Wolverine
Mar-24-2014, 21:36
Salmo, I think there's an error. WindSpeed is defined twice.



double WindSpeed = 99;
while (DirMET < -180 || DirMET > 180 || WindSpeed > 5.9)
{
// random meteorological wind coordinates, right handed with respect to an upward +Wmet.
uMET = RandomDoubleBetween(-7, 7); // 7 m/s max
vMET = RandomDoubleBetween(-7, 7); // 7 m/s max
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI
WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2)); // m/s
}

// wind speed Spd = sqrt(Umet2 + Vmet2) m/s
double WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2));

I think if you remove the 'double WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2));' at the bottom, it works fine.

Salmo
Mar-26-2014, 02:18
Salmo, I think there's an error. WindSpeed is defined twice.



double WindSpeed = 99;
while (DirMET < -180 || DirMET > 180 || WindSpeed > 5.9)
{
// random meteorological wind coordinates, right handed with respect to an upward +Wmet.
uMET = RandomDoubleBetween(-7, 7); // 7 m/s max
vMET = RandomDoubleBetween(-7, 7); // 7 m/s max
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI
WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2)); // m/s
}

// wind speed Spd = sqrt(Umet2 + Vmet2) m/s
double WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2));

I think if you remove the 'double WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2));' at the bottom, it works fine.

Done, 1st post updated

ATAG_Ezzie
Oct-11-2014, 03:47
Hi Salmo and everyone,

I'm hoping to use this random weather generator in my mission but cant get it to work. I've followed the procedure a couple of time trying to be extra careful and it still doesnt change the time or seemingly the clouds when i fly.

Here's what it looks like and i was wondering if someone could take a look and see what I'm doing wrong please?


using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"C:\Users\XXXX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\testwx\wxtst.mis"); // MyMissionName

is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 05, 12); // mission start time 5am to 12 noon
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 1500, 3000); // cloud height 1500m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180 / Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
double WindSpeed = 99;
while (DirMET < -180 || DirMET > 180 || WindSpeed > 5.9)
{
// random meteorological wind coordinates, right handed with respect to an upward +Wmet.
uMET = RandomDoubleBetween(-7, 7); // 7 m/s max
vMET = RandomDoubleBetween(-7, 7); // 7 m/s max
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI
WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2)); // m/s
}

// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter(@"C:\Users\XXXXX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\testwx\wxtst.mis", true); // a

writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3 + 1);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3 + 1);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace(@"C:\Users\XXXX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\testwx\wxtst.mis", missionfile, null); // rename

temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion

public double RandomDoubleBetween(double fMin, double fMax)
{
double result = random.NextDouble() * (fMax - fMin) + fMin;
return result;
}
}

Thanks

Ezzie

Salmo
Oct-11-2014, 05:07
Hi Salmo and everyone,

I'm hoping to use this random weather generator in my mission but cant get it to work. I've followed the procedure a couple of time trying to be extra careful and it still doesnt change the time or seemingly the clouds when i fly.

Here's what it looks like and i was wondering if someone could take a look and see what I'm doing wrong please? <snip>

Thanks Ezzie

You had 3 misplaced comment lines that were throwing errors. Here's your corrected code :salute:



using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
//================================================== =================
// user configurable switches & parameters
// change these as you like
//-----------------------------------------------------------------
bool UseRandomWeather = true; // turn random mission weather on/off
string MyMissionPath = @"C:\Users\XXXX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\testwx\wxtst.mis";
// MyMissionPath is the full path to the mission

// time of day
double gEarliestTimeOfDay = 5; // the earliest time of day for the mission start
double gLatestTimeOfDay = 12; // the lastest time of day for the mission start

// clouds
double gCloudBase = 1500; // the lowest altitude for clouds (metres)
double gCloudTop = 3000; // the highest altitude for clouds (metres)

// cloud density 0 = clear; 1 = light cloud; 2 = medium cloud
int gLowestCloudDensity = 1;
int gHighestCloudDensity = 2;

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
int gLowestWind = 0;
int gHighestWind = 8;

// Thermal activity (integer 0 - 10)
int gLowestThermalActivity = 0;
int gHighestThermalActivity = 10;

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
int gLowestWindGustLiklihood = 0;
int gHighestWindGustLiklihood = 10;

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
int gMinimumGustAngle = 0;
int gMaximumGustAngle = 45;

// --- end user configurable switches & parameters ---------
// === no need to change any code below here ===============

// random weather
Random random = new Random();

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather) RandomiseMissionWeather(@MyMissionPath);
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", (int)gEarliestTimeOfDay, (int)gLatestTimeOfDay); // mission start time of day
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", (int)gCloudBase, (int)gCloudTop); // cloud height
key.Add(tuple);

// cloud density
tuple = Tuple.Create("WeatherIndex", gLowestCloudDensity, gHighestCloudDensity); // none, light or medium clouds
key.Add(tuple);

// amount of wind
tuple = Tuple.Create("BreezeActivity", gLowestWind, gHighestWind); // no wind to gales
key.Add(tuple);

// Thermal Activity (0-10)
tuple = Tuple.Create("ThermalActivity", gLowestThermalActivity, gHighestThermalActivity);
key.Add(tuple);

// liklihood of wind gusts
tuple = Tuple.Create("GustPower", gLowestWindGustLiklihood, gHighestWindGustLiklihood);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", gMinimumGustAngle, gMaximumGustAngle);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180 / Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
double WindSpeed = 99;
while (DirMET < -180 || DirMET > 180 || WindSpeed > 5.9)
{
// random meteorological wind coordinates, right handed with respect to an upward +Wmet.
uMET = RandomDoubleBetween(-7, 7); // 7 m/s max
vMET = RandomDoubleBetween(-7, 7); // 7 m/s max
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI
WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2)); // m/s
}

// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter(@MyMissionPath, true);
// a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3 + 1);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3 + 1);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
// rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
File.Replace(@MyMissionPath, missionfile, null);
}
#endregion

public double RandomDoubleBetween(double fMin, double fMax)
{
double result = random.NextDouble() * (fMax - fMin) + fMin;
return result;
}
}

ATAG_Ezzie
Oct-11-2014, 05:29
Very many thanks Salmo.

I'll give it a whirl shortly - thanks.

At the risk of using up my alloted limit of questions

(a) Do you have any advice for how heavy to make the clouds for an ATAG server mission? I noticed you had used up to medium and was wondering what would happen if i made the clouds thicker (my mission is set in Nov hence why I'm interested in worse weather).

(b) And similarly - you had cloud heights 1500 - 3000m. Do you think i could make the cloud base lower (say 300m) and then stretch up to 4000m? Or would this incur too much of an FPS hit on players, especially if combined with thicker clouds.

(c) And another - since writing (a) and (b) and posting this I've just discovered local weather for the first time. Is your random weather generator compatible with local weather or is it one of the other?

Thanks again

Ezzie

Salmo
Oct-13-2014, 06:50
(a) Do you have any advice for how heavy to make the clouds for an ATAG server mission? I noticed you had used up to medium and was wondering what would happen if i made the clouds thicker (my mission is set in Nov hence why I'm interested in worse weather).
The game "stock" clouds can only be set as 0 = clear; 1 = light cloud; 2 = medium cloud, you can of course use a local eather object to put heavier clouds in a mission.


(b) And similarly - you had cloud heights 1500 - 3000m. Do you think i could make the cloud base lower (say 300m) and then stretch up to 4000m? Or would this incur too much of an FPS hit on players, especially if combined with thicker clouds.
You misunderstand the cloud base random setting mechanism. Let's say you want the cloud base to be (randomly) somewhere between 300m & 4000m, then you set the gCloudBase variable = 300 & the gCloudTop variable = 4000. That way you will get clouds somewhere between those two numbers.


(c) And another - since writing (a) and (b) and posting this I've just discovered local weather for the first time. Is your random weather generator compatible with local weather or is it one of the other?
It's compatible with the local weather object. The randomiser only changes the "weather" parameters that are in the [PARTS] section at the start of the mission file, it does not affect the local weather object settings. So hypothetically, you could have a random cloud base (say) somewhere between 300m & 1500m AND a local weather object over the top with clouds from 3500m to 4000m. The local weather object will move dynamically with the prevaling wind.

ATAG_Ezzie
Oct-13-2014, 14:20
Thanks Salmo.

I think I understand it a lot more now -thanks.

I've had a bit of a play with your random weather generator and local weather with pleasing results. I think the big unknown for me is how much local weather I can include before fps becomes an issue. Only testing will work that out I think and I'll add that to the list.

Thanks ezzie

ATAG_Ezzie
Oct-17-2014, 06:43
Salmo - i've got a problem trying to use this and i was wondering if you know what it might be?

I've created a very simple mission using one of the dogfight maps. I load your random weather script in, change the file location to match, make sure its named the same as the .mis file and it works. Very nice.

I then created a very simple trigger - as per Kodiak's (I think) description using BF110Spawn. But when i run the mission the spawn doesnt work - the weather and time randomise nicely though.

So i ran it a couple of times just to make sure and it didnt work. So i renamed the .cs file to make it different to the .mis file and ran it again. The spawn works (a couple of times i got run time errors and it eventually crashed my system with the BSOD again) when the random weather .cs file isnt involved. But once i rename the .cs file to match the .mis file the spawn stops working. And after a couple of attempts my system seems to crash.

So i was wondering if there is a conflict with using scripts via the .cs file and triggers via the FMB.

Here are the .mis file and the .cs file


using System.Text;
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using part;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using maddox.GP;

public class Mission : AMission
{
// random weather
Random random = new Random();
bool UseRandomWeather = true; // turn random mission weather on/off

public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
if (UseRandomWeather)
RandomiseMissionWeather(@"C:\Users\XXXXX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\script\trig1.mis"); // MyMissionName is the full path to the mission
}

public void RandomiseMissionWeather(string missionfile)
#region set random parameters for the weather lines in the mission file
{
// --------------------------------------------------------------------
// missionfile is the full path to the mission file ie something like ...
// F:\Users\Owner\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\MyMissionName.mis
//
// NOTE: C# Doesn't like backslashes in strings, so to call this function you should place
// a @ character in front of the path string, something like ... RandomiseMissionWeather(@"My\Mission\Path\MissionName.mis");
// Copyright Salmo 19-1-2014
// --------------------------------------------------------------------

List<Tuple<string, int, int>> key = new List<Tuple<string, int, int>>(); // list of weather line tuples
Tuple<string, int, int> tuple; // a tuple to hold weather line information, format is key-word; lowest integer value; highest integer value

// mission time
tuple = Tuple.Create("TIME", 07, 15); // mission start time 7am to 1300
key.Add(tuple);

// cloud height
tuple = Tuple.Create("CloudsHeight", 300, 3000); // cloud height 300m to 3000m
key.Add(tuple);

// cloud density
// 0 = clear; 1 = light cloud; 2 = medium cloud
tuple = Tuple.Create("WeatherIndex", 1, 2); // light or medium clouds
key.Add(tuple);

// amount of wind
/* See Beaufort wind scale http://en.wikipedia.org/wiki/Beaufort_scale#Modern_scale
0 = calm
1 = light breeze
2 = light breeze
3 = gentle breeze
4 = moderate breeze
5 = fresh breeze
6 = strong breeze
7 = high winds
8 = gale
9 = strong gale
10 = storm force
* */
tuple = Tuple.Create("BreezeActivity", 0, 8); // no wind to gales
key.Add(tuple);

//
tuple = Tuple.Create("ThermalActivity", 0, 10);
key.Add(tuple);

// liklihood of wind gusts
/*
GustPower > 8 = highly likely
GustPower > 6 = strong possiblility
GustPower > 4) = moderate possibility
GustPower > 2) = possibility
GustPower > 0) = probable
* */
tuple = Tuple.Create("GustPower", 0, 10);
key.Add(tuple);

// maximum angle of wind gusts relative to prevailing wind direction, -45 to +45 degrees
tuple = Tuple.Create("GustAngle", 0, 45);
key.Add(tuple);

// calculate wind angle in degrees from mission file arctangent vectors y, x
// ie. the line something like "Power 0.96 -3.32 0.00" where y=0.96, x=-3.32
// randomise arctan vectors so wind direction is variable from mission to mission
//
// the two-argument arc tangent function, atan2(y,x), which returns the arc tangent of y/x
// in the range -pi to pi radians, -180 to 180 degrees.
// ref: https://www.eol.ucar.edu/content/wind-direction-quick-reference
//
double DperR = 180 / Math.PI; // radians to degrees
double uMET = 0; // positive Umet is wind blowing to the East.
double vMET = 0; // positive Vmet is wind blowing to the North. This is right handed with respect to an upward +Wmet.
double DirMET = -200; // Dirmet is the direction with respect to true north, (0=north,90=east,180=south,270=west) that the wind is coming from.
double WindSpeed = 99;
while (DirMET < -180 || DirMET > 180 || WindSpeed > 5.9)
{
// random meteorological wind coordinates, right handed with respect to an upward +Wmet.
uMET = RandomDoubleBetween(-7, 7); // 7 m/s max
vMET = RandomDoubleBetween(-7, 7); // 7 m/s max
DirMET = Math.Atan2(-uMET, -vMET) * DperR; // get direction wind blowing FROM -180 to +180 as in game GUI
WindSpeed = Math.Sqrt(Math.Pow(uMET, 2) + Math.Pow(vMET, 2)); // m/s
}

// the actual wind angle in degrees
Double WindAngleDegrees = DirMET;
if (DirMET < 0) WindAngleDegrees = 180 - Math.Abs(DirMET) + 180;

tuple = Tuple.Create("Power", 0, 1);
key.Add(tuple);

// read the mission file one line at a time, randomise the weather line parameters & write to a temporary mission file
StreamReader sr = new StreamReader(missionfile); // a reader for the mission file
StreamWriter sw = new StreamWriter(@"C:\Users\XX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\script\tmpWeather.mis", true); // a writer for the new temporary mission file
string NewMisLine;
while ((NewMisLine = sr.ReadLine()) != null) // read mission file one line at a time
{
for (int i = 0; i < key.Count; i++) // cycle through each of the weather section line key words
{
if (NewMisLine.TrimStart().StartsWith(key[i].Item1)) // we found a line with a weather key word
{
// generate a random integer between the low & high range (inclusive)
int RandomInt = random.Next(key[i].Item3 + 1);
while (RandomInt < key[i].Item2) RandomInt = random.Next(key[i].Item3 + 1);

// look for some special weather words & process them seperately
if (NewMisLine.Contains("GustAngle") && random.Next(100) > 50) RandomInt = -RandomInt; // gustangle can be + or -
if (NewMisLine.TrimStart().StartsWith("Power"))
{
NewMisLine = " " + key[i].Item1 + " " + uMET.ToString("0.00") + " " + vMET.ToString("0.00") + " " + "0"; // power vector line
}
else
{
NewMisLine = " " + key[i].Item1 + " " + RandomInt.ToString(); // use the random integer value
}
}
}
sw.WriteLine(NewMisLine);
}
sr.Close(); // close the mission file to processing
sw.Close(); // close temporary mission file tmpWeather
File.Replace(@"C:\Users\XXXX\Documents\1C SoftClub\il-2 sturmovik cliffs of dover - MOD\missions\Multi\Dogfight\script\tmpWeather.mis", missionfile, null); // rename temporary mis file (tmpWeather) as the mission file (overwrites mis file)
}
#endregion

public double RandomDoubleBetween(double fMin, double fMax)
{
double result = random.NextDouble() * (fMax - fMin) + fMin;
return result;
}
}



[PARTS]
core.100
bob.100
[MAIN]
MAP Land$Online_Isles_of_Doom
BattleArea 0 0 40960 32768 10000
TIME 7
WeatherIndex 1
CloudsHeight 2852
BreezeActivity 0
ThermalActivity 5
player BoB_LW_LG2_I.000
[GlobalWind_0]
Power 2.51 5.28 0
BottomBound 0.00
TopBound 1500.00
GustPower 6
GustAngle -30
[splines]
[AirGroups]
BoB_LW_LG2_I.01
BoB_LW_LG2_I.02
[BoB_LW_LG2_I.01]
Flight0 1
Class Aircraft.Bf-110C-4N
Formation FINGERFOUR
CallSign 26
Fuel 100
Weapons 1
Skill 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
[BoB_LW_LG2_I.01_Way]
TAKEOFF 13232.91 16025.66 0 0
[BoB_LW_LG2_I.02]
Flight1 11
Class Aircraft.Bf-110C-4N
Formation FINGERFOUR
CallSign 30
Fuel 100
Weapons 1
SpawnFromScript 1
Skill 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
[BoB_LW_LG2_I.02_Way]
NORMFLY 14115.98 15657.08 100.00 300.00
NORMFLY 11041.67 17096.85 500.00 300.00
[CustomChiefs]
[Stationary]
[Buildings]
[BuildingsLinks]
[Trigger]
BF110Spawn TTime 30
[Action]
BF110Spawn ASpawnGroup 1 BoB_LW_LG2_I.02

bolox
Oct-17-2014, 10:20
So i was wondering if there is a conflict with using scripts via the .cs file and triggers via the FMB.

Triggers and scripts do 'conflict' in that if you have a script it 'overides' the triggers- so you must include the trigger and it's associated action within the script. something like this- where 264 and 56 are triggers spawning airgroups and the last 2 show a trigger changing integer/booleams for use elsewhere in script.
//'ed out gpHUDlog messages were for testing to check triggers worked properly.


public override void OnTrigger(int missionNumber, string shortName, bool active)
{
base.OnTrigger(missionNumber, shortName, active);

if ("264".Equals(shortName) && active)
{
AiAction action = GamePlay.gpGetAction("264");
if (action != null)
{
action.Do();
}
//GamePlay.gpHUDLogCenter("264");
GamePlay.gpGetTrigger(shortName).Enable = false;
}

if ("56".Equals(shortName) && active)
{
AiAction action = GamePlay.gpGetAction("56");
if (action != null)
{
action.Do();
}
//GamePlay.gpHUDLogCenter("56");
GamePlay.gpGetTrigger(shortName).Enable = false;
}

if (GamePlay.gpGetTrigger("land").Active) {
lnd = ++lnd; //increment lnd counter

//GamePlay.gpHUDLogCenter("land:"+lnd);
}
if (GamePlay.gpGetTrigger("mis").Active) {
end = true;
//GamePlay.gpHUDLogCenter("!"); // define reached mission objective
}
}

ATAG_Ezzie
Oct-17-2014, 16:19
Triggers and scripts do 'conflict' in that if you have a script it 'overides' the triggers- so you must include the trigger and it's associated action within the script. something like this- where 264 and 56 are triggers spawning airgroups and the last 2 show a trigger changing integer/booleams for use elsewhere in script.
//'ed out gpHUDlog messages were for testing to check triggers worked properly.


public override void OnTrigger(int missionNumber, string shortName, bool active)
{
base.OnTrigger(missionNumber, shortName, active);

if ("264".Equals(shortName) && active)
{
AiAction action = GamePlay.gpGetAction("264");
if (action != null)
{
action.Do();
}
//GamePlay.gpHUDLogCenter("264");
GamePlay.gpGetTrigger(shortName).Enable = false;
}

if ("56".Equals(shortName) && active)
{
AiAction action = GamePlay.gpGetAction("56");
if (action != null)
{
action.Do();
}
//GamePlay.gpHUDLogCenter("56");
GamePlay.gpGetTrigger(shortName).Enable = false;
}

if (GamePlay.gpGetTrigger("land").Active) {
lnd = ++lnd; //increment lnd counter

//GamePlay.gpHUDLogCenter("land:"+lnd);
}
if (GamePlay.gpGetTrigger("mis").Active) {
end = true;
//GamePlay.gpHUDLogCenter("!"); // define reached mission objective
}
}

Thanks Bolox - useful snippet of info re fmb v script conflicts. And thanks for your script. I will study and try and decipher and learn as I go hopefully.

Just been speaking with Mr Dell and they will be replacing my graphics card in the next couple of days. So should be back working on how to crawl with scripting in a few days time. In the meantime I'll read and read and maybe read some more.

Ezzie

Salmo
Oct-17-2014, 17:03
Thank's Bolox. Just to confirm Ezzie, (1) save your working mission file with trigger as different name. (2) Run the mission with randomise weather script (3) close the mission & open the mission file & compare to the saved files in (1). Is the trigger line the same?

ATAG_Ezzie
Oct-17-2014, 17:07
Thank's Bolox. Just to confirm Ezzie, (1) save your working mission file with trigger as different name. (2) Run the mission with randomise weather script (3) close the mission & open the mission file & compare to the saved files in (1). Is the trigger line the same?

Will do Salmo once my system is back up and running.

Thanks

Ezzie

ATAG_Ezzie
Oct-17-2014, 18:47
Bolox,

If what I am about to do is too painful for u please let me know and I'll desist.

I'm keen to get going on this scripting gig and seeing my PC is kaput I've decided to try and decipher a COD related script rather than the ones in my book as I hope that by doing so will let me learn about both c# and how COD works re scripting. And hopefully by the time my PC is back working I will be able to build and use a simple one and see how it goes. And triggers seems as good a place as any to start.

So starting with the first line of your script you sent me earlier - public override void OnTrigger (int missionNumber, string shortName, bool active)

public -means this class you are creating can be accessed by other classes in the script and game?

Override - I couldn't figure this out?

Void - this means that onTrigger doesn't return anything to the caller (is this COD -what /who is the caller?) and returns control back to something?(COD) when it gets to the }?

OnTrigger -this is a COD function from one of the .dlls?

int missionNumber- you've created an integer called missionNumber? Or has missionNumber been created elsewhere and you are just linking it with onTrigger?

String shortName - you've created a string called shortName? Looking ahead it seems that shortName is the squadron number that is part of the trigger? Or shortName has been created elsewhere and you are linking it with onTrigger?

Bool active -you've created a bool called active. This will either be true or false depending on some criteria defined somewhere? Or has active been declared elsewhere?

So in other words you are saying a trigger will be initiated if the mission number, squadron name (its number in this case) and some true/false condition attributed to the bool called active is met. And this trigger is available for other parts of the program to use.

Have I correctly interpreted it?

Once I understand this line I will move to the next and so on -I think I understand some of what is happening below re if etc. I think....

Like I said if this is too painful for you pls let me know.

From a week or so of reading all the various threads/forums on scripting and my c# book it seems that the best approach for me is to try and understand things as best I can and then ask questions to test my knowledge and learn about the COD side of things. And then build and experiment in fmb etc.

But I appreciate that requires yourself, Salmo etc giving me some of your time to respond and I for one are very conscious of that and really appreciate any assistance you can provide. Hopefully if I can persevere with learning this then I will be able to pass it on to others in due course and help spread the knowledge.

Ezzie

bolox
Oct-18-2014, 05:07
Don't sto:) - I'm just not sure how much I can help with accurate, 'class room' descriptions. I learnt this stuff empirically but yes public is used so 'results' can be accessed/used in other classes, overide means this class takes precedence- what we are doing is 'overiding' what I imagine is an internal class created by using the trigger in fmb.
Maybe this explains it more accurately? http://www.dotnetperls.com/override
Void -http://msdn.microsoft.com/en-gb/library/yah0tteb.aspx
Basically this 'sets up' the class 'ontrigger in your script(which is from CoD dll's) ready for use. The class has parameters mission No, short name and wether its is active or not).
I do SP stuff so so far I have not had the need to use submissions, so others may be better able to answer this
Shortname is the name of your trigger you created in fmb
Active is if the trigger is triggered.

So you just copy paste this section in (with curly brackets) and you are ready to do some fancy coding stuff:).
What we have done is created a class that runs when an ingame trigger is activated ready for us to read info, manipulate data or perform actions.

The 'base onTrigger' line is a 'belt and braces' approach saying that the class created is based on the one in CoD dll's.

Then we get to were we make 'stuff happen'

if ("264".Equals(shortName) && active)
This asks if trigger '264' is the trigger that has been activated.
Then comes the actions

{
AiAction action = GamePlay.gpGetAction("264");
if (action != null)
{
action.Do();
}
//GamePlay.gpHUDLogCenter("264");
GamePlay.gpGetTrigger(shortName).Enable = false;
}
this 'reads' the action for the trigger '264' and if it has an action it performs the action- in this case spawning the airgroup set up in fmb trigger.
The // hudlog line was for testing.
The last line disables further triggering to prevent multiple spawning of the airgroup.- note how it is not used in last 2 triggers.

Good luck getting your rig fixed

No601_Swallow
Oct-18-2014, 10:27
Bolox, that post goes straight in at number one-ish in my list of top 100 "Things you always wanted to know about scripts but were too embarrassed to ask."

Many thanks.

Ezzie, many thanks for going where I, for one, have feared to tread! S!

ATAG_Ezzie
Oct-18-2014, 16:20
Thanks Bolox - very very helpful - thanks.

I spent some time going thru the download you sent me yesterday - thanks - looking at the various other examples which was (a) useful (b) confusing but (c) helped a lot in getting a sense for what to do.

So I'm going to try and write a script today that is very very simple - one aircraft on the isle of doom map takes off (which causes a HUD message to be displayed) and then flies to another field and lands (another HUD message) - to see if i am understanding what I'm doing. I think i saw some use of onaircrafttakeoff (or thereabouts) and onaircraftland and the HUD msg scripting you used in your download so will cut and past those commands and see if i can get it working (once my rig is fixed - hopefully mid week).

And then experiment from there - timing (ontick?) etc - and slowly build things into it until i've figured out how to do all of the things i want in my mission.

Thanks again for you assistance. I found the hardest part thus far with this scripting thing is finding a place to start. Its like there's a big mountain ahead of me (scripting) that i want to climb (because of how useful scripting is) and there's a lot of advice on various climbing techniques for different parts of the ascent (forum posts). But i found its difficult/confusing to actually find a place to start climbing - i think I'm on the way now hopefully so thanks again for your help.

re rig - thanks. Its working OK as i type this but once i do anything that stresses the graphics card or even just after a random time doing internet it will crash. Not sure how it will like Visual Studio - will see in a few minutes..

Ezzie


Don't sto:) - I'm just not sure how much I can help with accurate, 'class room' descriptions. I learnt this stuff empirically but yes public is used so 'results' can be accessed/used in other classes, overide means this class takes precedence- what we are doing is 'overiding' what I imagine is an internal class created by using the trigger in fmb.
Maybe this explains it more accurately? http://www.dotnetperls.com/override
Void -http://msdn.microsoft.com/en-gb/library/yah0tteb.aspx
Basically this 'sets up' the class 'ontrigger in your script(which is from CoD dll's) ready for use. The class has parameters mission No, short name and wether its is active or not).
I do SP stuff so so far I have not had the need to use submissions, so others may be better able to answer this
Shortname is the name of your trigger you created in fmb
Active is if the trigger is triggered.

So you just copy paste this section in (with curly brackets) and you are ready to do some fancy coding stuff:).
What we have done is created a class that runs when an ingame trigger is activated ready for us to read info, manipulate data or perform actions.

The 'base onTrigger' line is a 'belt and braces' approach saying that the class created is based on the one in CoD dll's.

Then we get to were we make 'stuff happen'

if ("264".Equals(shortName) && active)
This asks if trigger '264' is the trigger that has been activated.
Then comes the actions

{
AiAction action = GamePlay.gpGetAction("264");
if (action != null)
{
action.Do();
}
//GamePlay.gpHUDLogCenter("264");
GamePlay.gpGetTrigger(shortName).Enable = false;
}
this 'reads' the action for the trigger '264' and if it has an action it performs the action- in this case spawning the airgroup set up in fmb trigger.
The // hudlog line was for testing.
The last line disables further triggering to prevent multiple spawning of the airgroup.- note how it is not used in last 2 triggers.

Good luck getting your rig fixed

ATAG_Ezzie
Oct-18-2014, 16:29
Thanks Swallow.

I spent a fair bit of time yesterday reading and re-reading one of your posts (the Serie B one) and found that very useful as well - thanks for writing that and it helped me become less confused about some things. Still early days but i hope I'm making progress re trying to understand this.

I did a lot of non-scripting work on my mission before looking at scripting and luckily i did as i think i might have given up if I'd jumped right on into scripting. A couple of times I've felt overwhelmed by trying to make sense of it but because i didn't want to waste all that previous effort i have persevered and i think am slowly making progress. If i can get the script that i described to Bolox working then that will be a major achievement for me and hopefully be enough to convince me to stick with it. I know what functions i need to script for my mission and its not a lot and i think i have a conceptual idea of how to achieve most of them at this stage.

Ezzie


Bolox, that post goes straight in at number one-ish in my list of top 100 "Things you always wanted to know about scripts but were too embarrassed to ask."

Many thanks.

Ezzie, many thanks for going where I, for one, have feared to tread! S!