PDA

View Full Version : Online War - FMB scripting


Ataros
04-16-2011, 08:56 AM
I'll just copy my post from Syndicate forums (http://syndicatesquadron.com/forum/showthread.php?284-Doghouse-mission&p=1838&viewfull=1#post1838):

Please have a look at post #73 from a developer here.
http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=ru&tl=en&u=http%3A%2F%2Fwww.sukhoi.ru%2Fforum%2Fshowthread. php%3Ft%3D67964%26page%3D3

Corrected translation:
In the enclosure there is simple example of a mission with a script - run mission 1.mis (in 2 pieces), it executes the script 1.cs - every 1200 ticks of game (~ 30 ticks a second, iirc) which loads the mission 2.mis (1 Spitfire) - this is the answer to how to create a group of aircraft every N minutes.

When a player leaves the plane - an event triggered OnPlaceLeave and a second later the plane is killed - this is the answer on how to get rid of bots. Naturally, for your specific conditions, all this can be reconfigured.

I think using these scripts we can
1) kill all bots after a player exits an aircraft for better stability

and much more important(!)

2) create any submissions for current mission loading every 10, 15, 20 and 30 minutes, including

- programmed bombing runs on England (and France )
- tank battles
- armored cars attacking airfields
- ship convoys (bombing/intercepting submissions)
- free hunters surprisingly attacking on takeoff
- submarines sinking convoys (with 3rd party addons :grin: )
- etc, etc.

Basically any mission from Offline Campaign can be taken online.

Another useful thread on scripting and triggers.
http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=ru&tl=en&u=http%3A%2F%2Fwww.sukhoi.ru%2Fforum%2Fshowthread. php%3Ft%3D68369

upd. New forum section on FMB and scripting http://translate.google.com/translate?hl=en&sl=ru&tl=en&u=http%3A%2F%2Fwww.sukhoi.ru%2Fforum%2Fforumdispla y.php%3Ff%3D234

Lets make some small missions consisting of 3-4 submissions first to simulate what we had in IL-2 online wars like VEF or ADW.

File with sample mission from developer attached. Let the full-scale war begin!

doghous3
04-16-2011, 10:09 AM
had a look at that this morning.

1. works a treat. spawn, respawn, first spawn plane immediately gone.

2. didn't work. From what I could see, it actually tries to load a new mission. Perhaps it is possible to load a mission into a mission, doesn't seem desirable, but then maybe i need more coffee.

Great finds again though Ataros. :)

Ataros
04-16-2011, 02:35 PM
From what I could see, it actually tries to load a new mission. Perhaps it is possible to load a mission into a mission, doesn't seem desirable, but then maybe i need more coffee.

Oleg mentioned long time ago that this is their idea for multiplayer i.e. continuous non-stop war. Server does not have to stop the mission and put all connected players into waiting interface screen when server is changing mission objectives as it was in original IL-2.

In original Il-2 when mission objectives are met you server had to stop the mission to load a new one. If you were flying in the air at this moment you would have to start again on the ground.

Now in CoD you can continue flying when "mission is changing".

Say you have a mission to stop enemy tanks from taking an airfield.
Then you have options
1) If you are successful this triggers loading next objectives:
- for your tanks advance to next city and for your aircraft to cover them.
- for enemy to bomb your airfield

2) If you fail to protect your airfield the objectives will be different:
- for you to cover bomber strike on enemy tank factory
- for enemy to escort transport aircraft to the newly taken airfield.

New objectives (together with new aircraft, tanks, ships, etc.) will be loaded into current mission while you are still flying in the air. You can prepare say 20-50 such small sub-missions and they will rotate on your server depending on results of previous missions set as triggers. Several sub-missions may overlap in time.
And this is just one possibility, there are much more of them.

Atm you may wish to try adding sub-missions of Stukas attacking shipping in the channel loading into your current mission every 20 minutes. ...and Beaufighters attacking blue airfields every 30 minutes, and... the possibilities are endless.

I will try to do it myself on Monday probably as i am currently away from my gaming PC.

doghous3
04-16-2011, 03:30 PM
Ah, thanks for explaining the concept.

Part of the confusion was that in 2.mis, it contained information for [PARTS], [MAIN] etc.. (set as a full mission) also, and call me a doughnut, I had the tmp file in multi folder, not just missions. *facepalm*

So most the fluff can be removed and in that instance just have the airgroup/waypoints.

It does work. I need that caffiene in the morning.

baffa
04-16-2011, 04:36 PM
These things looks really promising!

Jwam
04-16-2011, 04:45 PM
Thank you very much for sharing.

I'm using it on my server, and it's really cool not to see thousands of IAs flying without ammo or standing on the taxiway.

Thee_oddball
04-16-2011, 05:00 PM
Great find!!!

now if i can only script the dog to walk himself in the morning and not pester me :)

S!

Thee_oddball
04-17-2011, 12:08 AM
The name of the offending applications: Launcher.exe_Launcher, version: 1.0.0.0, time stamp: 0x4d6e3d08
0x4ce7ba58 Faulting module name: ntdll.dll, version: 6.1.7601.17514, time stamp 0x4ce7ba58
Exception Code: 0xc0000005 Exception Code: 0xc0000005

An access violation is a serious problem: it is an unexpected attempt to write to an invalid memory address. As John already clarified, the unmanaged DLL might already have corrupted the process memory before the access violation has been raised. This can have unpredicted effects on any part of the current process

The original poster of the error also noted it happend after the Chanel map has been running for a while.

S!

Thee_oddball
04-17-2011, 02:34 AM
I must be doing something wrong...i have added the script to one of my maps and there is even a .cs file of the same name but when i tested it and spwned four planes they just took off like they always do :( is the file below correct?
using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{


public override void OnTickGame()
{
{
if (Time.tickCounter() % 1200 == 0)
{

GamePlay.gpPostMissionLoad("missions\Multi\Dogfight\basic40c.mis");
}
}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () =>
{
AiAircraft CurAircraft = player.Place() as AiAircraft;
AiAircraft PrevAircraft = actor as AiAircraft;
if (CurAircraft != PrevAircraft)
{ (actor as AiAircraft).Destroy(); }
});
}

}

Ataros
04-17-2011, 11:55 AM
when i tested it and spwned four planes they just took off like they always do :( is the file below correct?

I can not say if something is wrong as I do not know C# myself.
Why do you expect the AI aircraft not to take off? If basic40c.mis tells them to take off, they will.


upd. All events you can use in a mission script. Sorry for jpg format.
http://www.sukhoi.ru/forum/attachment.php?attachmentid=132279&d=1303038770

upd.2 And a good thread on triggers here http://forum.1cpublishing.eu/showthread.php?t=20995&highlight=builder&page=2

Thee_oddball
04-17-2011, 09:09 PM
I can not say if something is wrong as I do not know C# myself.
Why do you expect the AI aircraft not to take off? If basic40c.mis tells them to take off, they will.



you misunderstand me..the AI i am talking about are player abandoned air craft not scripted AI

Ataros
04-18-2011, 09:12 AM
Sample use of triggers to load a new mission into current one.

110s attack convoy of static objects. When it is killed trigger loads a new mission where 110s attack just one car. When it is killed OnActorDead does not work unfortunately...
http://www.sukhoi.ru/forum/showthread.php?t=68629&p=1599354&viewfull=1#post1599354

It does not work on static objects completely as intended but works for aircraft I think.

File attached

ZaltysZ
04-19-2011, 06:22 AM
Spawn/despawn script is kinda "incomplete" and causes unwanted behavior: plane instantly disappearing on bail out or plane disappearing when single member of crew leaves the plane (i.e. one of bomber gunners leaves the plane) while other members are still inside.

Additionally checking if plane is manned before "killing" it should help with multicrew plane despawns. Bail out despawns probably will be a lot tricker.

Ataros
04-19-2011, 03:19 PM
Attention mission makers! A person from dev team told we can put AA guns on oil tankers at other forums. This means we can have some sea battles going on in the channel )) or coastal airfields attacked from sea.

Can not try it myself yet.

Ataros
04-19-2011, 03:20 PM
Spawn/despawn script is kinda "incomplete" and causes unwanted behavior: plane instantly disappearing on bail out or plane disappearing when single member of crew leaves the plane (i.e. one of bomber gunners leaves the plane) while other members are still inside.

Additionally checking if plane is manned before "killing" it should help with multicrew plane despawns. Bail out despawns probably will be a lot tricker.

Someone who knows C# can change it hopefully. I do not see much interest from community to this topic unfortunately. Hopefully when bugs are fixed and we have a stable dedi server things change.

ZaltysZ
04-19-2011, 07:35 PM
Script for despawning planes without humans inside. Multicrew friendly.

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return;}

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if (PlaneIsEmpty)
{ (actor as AiAircraft).Destroy(); }
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () =>
{
_DespawnEmptyPlane(actor);
});
}
}
}

Ataros
04-19-2011, 10:48 PM
WOW! Thanks a lot!!!

Thee_oddball
04-19-2011, 10:48 PM
Attention mission makers! A person from dev team told we can put AA guns on oil tankers at other forums. This means we can have some sea battles going on in the channel )) or coastal airfields attacked from sea.

Can not try it myself yet.oops I thought you guys knew that...my first map has 8 tankers and 3 with bofars :)

the selection will be under cargo :)

Thee_oddball
04-19-2011, 10:49 PM
thank you Zalty does this replace the original script?

Ataros
04-19-2011, 11:08 PM
oops I thought you guys knew that...my first map has 8 tankers and 3 with bofars :)

the selection will be under cargo :)

Did you upload your mission somewhere? Could I have a look at it in FMB?

ZaltysZ
04-20-2011, 06:02 AM
thank you Zalty does this replace the original script?

Yes, if previous one handled only despawning.

ZaltysZ
04-20-2011, 07:27 PM
I have edited my despawn script post and added additional "null" check to prevent some possible error.

Jwam
04-20-2011, 08:23 PM
I have edited my despawn script post and added additional "null" check to prevent some possible error.

Cool thank you very much ! I'll use it :)

edit : It seems there is one more "}" than needed, but works flawlessly :)

Ataros
04-25-2011, 10:52 PM
More experiments with scripting. New version of Battle of France mission here http://forum.1cpublishing.eu/showpost.php?p=273231&postcount=12

LeadFarmer
04-26-2011, 02:58 AM
bottom of that script says timeout 1 which is one sec. set that to 60 and your planes will despawn after 60 sec which is enough time for an aircraft to hit the ground when you bail and despwan ;)

Ralith
04-26-2011, 06:29 AM
Won't that leave the AI in control for 60 seconds, rather than having it glide into the ground? Really, the code should be ran instantly, and it should disable AI control instead of simply removing the aircraft--assuming that's currently possible.

Ataros
04-26-2011, 08:12 AM
This sample script made for fun disables player controls. Maybe someone can use it to disable AI controls for say 10 minutes before destroying AI

using System;
using maddox.game;
using maddox.game.world;

public class Mission: maddox.game.AMission
{
/ / Override the method that is invoked when some of the planes will take off ...
public override void OnAircraftTookOff (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftTookOff (missionNumber, shortName, aircraft); / / call the base method (you never know ...)
if (GamePlay.gpPlayer ()! = null) / / check if we have a player.
{
if (GamePlay.gpPlayer (). Place ()! = null) / / check that the player is sitting somewhere and not hanging out on the rag.
{
if (aircraft.Name (). Equals (GamePlay.gpPlayer (). Place (). Name ())) / / if the plane took off - a player, then ...
{
aircraft.hitNamed (part.NamedDamageTypes.ControlsElevatorDisabled); / / ... disables elevators ...
aircraft.hitNamed (part.NamedDamageTypes.ControlsAileronsDisabled); / / ... aileron ...
aircraft.hitNamed (part.NamedDamageTypes.ControlsRudderDisabled); / / ... rudder.
/ / Have a nice flight!
}
}
}
}
}

More scripts here http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=ru&tl=en&u=http%3A%2F%2Fwww.sukhoi.ru%2Fforum%2Fshowthread. php%3Ft%3D68369

ZaltysZ
04-26-2011, 09:09 AM
Won't that leave the AI in control for 60 seconds, rather than having it glide into the ground? Really, the code should be ran instantly, and it should disable AI control instead of simply removing the aircraft--assuming that's currently possible.

The aim is not to make how it should look in real life. The aim is to remove clutter at first and then make the best you can with realism, because piles of planes have huge impact on playability.

Yes, you can disable the controls, but trimmed plane can happily fly even without working controls. What I want to say: disabling the controls does not guarantee a quick crash.

Extending despawn timeout can lead to great clutter, i.e. when player presses "Create" multiple times.

robtek
04-26-2011, 09:38 AM
The aim should be, imho, when a player bails from a working plane and he tries to create a new plane, he find himself in that "abandoned" plane, as long as it is still flying :-D
And from a realism point of view, it is realistic that planes with dead crews were hunted and so live planes could escape.
I dont think that happens so often to have a felt influence on playability.

ZaltysZ
04-26-2011, 10:11 AM
The aim should be, imho, when a player bails from a working plane and he tries to create a new plane, he find himself in that "abandoned" plane, as long as it is still flying :-D

You mean injection after ejection? :o I don't think game engine allows you to teleport a crew member into plane. You can force a player posses a virtual crew member, but at first there should be something to posses in cockpit.

And from a realism point of view, it is realistic that planes with dead crews were hunted and so live planes could escape.
I dont think that happens so often to have a felt influence on playability.

In fact, the problem isn't flying Dutchmen alone. The problem is bigger. All despawning logic isn't so trivial and implementation can become very complex. The more I play in MP, the more pitfalls I see. :mad:

robtek
04-26-2011, 11:06 AM
Thanks for the answer ZaltysZ,

the first part of my post was just wishful thinking, pointed at players which abandon a working plane so they dont have to fly home and land.

And for your second point, i think i saw part of the problems in form of fata-morgana-bomber-raids, which disappear as you come closer to them, on the syn-server.

Ataros
04-26-2011, 11:02 PM
Yes, you can disable the controls, but trimmed plane can happily fly even without working controls. What I want to say: disabling the controls does not guarantee a quick crash.

Can a script apply say full aileron before disabling controls or set engine on fire?

Ataros
04-27-2011, 08:50 AM
In my opinion this is what we need:



There are 2 issues with online currently:

1) when a player exits a plane AI takes control resulting in too many AI flying around at a server. There is a script to destroy AI after player exit http://forum.1cpublishing.eu/showpost.php?p=268215&postcount=16
the problem with this script is that if a player exits while under attack his plane would disappear making the attacker very disappointed. Discussion is here http://forum.1cpublishing.eu/showthread.php?t=21518&page=3

Possible solution: damage an aircraft upon player exit to make it fall down and destroy it later in 10 minutes after it hits the ground.

2) When AI bombers are scripted to reappear on a server as time goes by the server can become very crowded with AI bombers making it unplayable. Mission example http://forum.1cpublishing.eu/showpost.php?p=273758&postcount=24

The solution would be to damage AI bombers one by one (with 1-2 min intervals) in 15-25 minutes after their last waypoint. OnTaskCompleted()? Then when they fall down destroy them in 10 minutes.

Ideally damage applied to aircraft should be different (say 10 different types of damage in rotation) but deadly enough to make aircraft fall down in 1-3 minutes.



CoD possible Damage Types http://forum.1cpublishing.eu/showthread.php?t=22184 Thanks to FG28_Kodiak.

ZaltysZ
04-27-2011, 09:02 AM
About bombers. Doesn't the problem dissappear if their last waypoint is "landing"?

mcler002
04-27-2011, 09:22 AM
I would think so... But landing takes time ...

I just want them to disappear once they get back over 'friendly' areas

ZaltysZ
04-27-2011, 09:32 AM
I just want them to disappear once they get back over 'friendly' areas

Destroy() method of AiAircraft inside OnTaskCompleted().

Ataros
04-27-2011, 10:08 AM
Destroy() method of AiAircraft inside OnTaskCompleted().

Yes, we need someone to make this script to allow just copy-and-paste for those who does not know C# or any other language at all but makes missions in FMB like myself. Please... :grin:

This is an example of my mission that runs on Repka server atm. http://forum.1cpublishing.eu/showpost.php?p=273758&postcount=24
I have no idea what I should put in the .cs file to make "Destroy() method of AiAircraft inside OnTaskCompleted(). " work. Another thing is that aircraft should fall to ground before it is destroyed with some timeout ideally as described here http://forum.1cpublishing.eu/showpost.php?p=274221&postcount=33.

FG28_Kodiak
04-27-2011, 02:26 PM
So have modified ZaltysZ script, with some damage ;), fastes way to ground is to disable all controlls and the engines.


using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return;}

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if (PlaneIsEmpty)
{

(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sElevatorDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sAileronsDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sRudderDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng0Tot alFailure);
//for 2mots
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng1Tot alFailure);

//wait 10min
Timeout(600.0, () => {
(actor as AiAircraft).Destroy();
});

}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
_DespawnEmptyPlane(actor);
}
}

Ataros
04-27-2011, 02:35 PM
FG28_Kodiak, thank you so much! i will try it tonight.

ZaltysZ
04-27-2011, 03:05 PM
Guys, don't bother with engines, kill fuel pump instead (all engines should stop). :-P

By the way, what will happen if player presses "Create" multiple time? There will probably be lots of planes on ground without working controls and engines. There is handy method IsAirborne(). If it returns false, plane should be destroyed immediately; if it returns true, only then disabling of controls should commence.

FG28_Kodiak
04-27-2011, 03:11 PM
Disable fuel pump doesn't help, the engines wouldn't stop. Fuel pump is only nessesary at altitudes above 2500m.

You are right IsAirborne() can be very usefull in this script.

Corrected Version ;)


using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return;}

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if ((PlaneIsEmpty) && (actor as AiAircraft).IsAirborne())
{

(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sElevatorDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sAileronsDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sRudderDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng0Tot alFailure);
//for 2mots
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng1Tot alFailure);

//then wait 10min
Timeout(600.0, () => {
(actor as AiAircraft).Destroy();
});

}
else if (PlaneIsEmpty)
{
(actor as AiAircraft).Destroy();
}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
_DespawnEmptyPlane(actor);
}
}

Ataros
04-27-2011, 03:56 PM
Thanks again!
Copied to my mission script. Is it OK?

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{


public override void OnTickGame()
{

if (Time.tickCounter() % 90000 == 18000) // 50-10 60-10 108000 == 18000
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFsmGroundv1_0.mis");
GamePlay.gpHUDLogCenter("Protect friendly shipping in the channel near France!");
}

if (Time.tickCounter() % 72000 == 72000) // 40-40 45-35 81000 == 63000
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFsmBombersv1_0.mis");
GamePlay.gpHUDLogCenter("Intel: Enemy bombers are heading to blue airfields!");
}

if (Time.tickCounter() % 72000 == 45000) // 40-25 45-45 81000 == 81000
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFsmBombersv1_0a.mis");
GamePlay.gpHUDLogCenter("Intel: Enemy bombers are heading to red airfields in France!");
}


}

public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return; }

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if ((PlaneIsEmpty) && (actor as AiAircraft).IsAirborne())
{

(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sElevatorDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sAileronsDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sRudderDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng0Tot alFailure);
//for 2mots
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng1Tot alFailure);

//then wait 10min
Timeout(600.0, () =>
{
(actor as AiAircraft).Destroy();
});

}
else if (PlaneIsEmpty)
{
(actor as AiAircraft).Destroy();
}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
_DespawnEmptyPlane(actor);
}

}

mcler002
04-27-2011, 04:22 PM
if (Time.tickCounter() % 72000 == 45000) // 40-25 45-45 81000 == 81000

[/CODE]

Dude, what do those numbers do?

I have noticed that the time counter isnt 100% accurate - the planes appears a couple of minutes soon than what they should... bug?

Ross

Ataros
04-27-2011, 04:32 PM
Destroys crashlanded aircraft in 5 seconds ))
public override void OnAircraftCrashLanded(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftCrashLanded(missionNumber, shortName, aircraft);
Timeout(5, () =>
{
aircraft.Destroy();
});
}

Have to figure out how to use it though.

Dude, what do those numbers do?



Just notes for myself on timing. Not processed by program.

if (Time.tickCounter() % 72000 == 72000) is wrong probably.

mcler002
04-27-2011, 05:15 PM
someone help me here :S
Main map starts at 05:00 - like the rest of the "sub" maps


using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{


public override void OnTickGame()
{

if (Time.tickCounter() % 54000 == 18000)
{

GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/Ross/OnlineBOBb1.mis");
GamePlay.gpHUDLogCenter("Intel: 4x He115's, Heading for Convoy!");
}

if (Time.tickCounter() % 99000 == 36000)
{

GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/Ross/OnlineBOBb2.mis");
GamePlay.gpHUDLogCenter("Intel: 8x He111's, Heading for Lympne!");
}

if (Time.tickCounter() % 108000 == 27000)
{

GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/Ross/OnlineBOBr1.mis");
GamePlay.gpHUDLogCenter("Intel: 12xBlenheim, Heading for Calais Marck!");
}

}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () =>
{
AiAircraft CurAircraft = player.Place() as AiAircraft;
AiAircraft PrevAircraft = actor as AiAircraft;
if (CurAircraft != PrevAircraft)
{ (actor as AiAircraft).Destroy(); }
});
}

}


But actual results...

He 115 starts at 05:09 - 1 min fast
Blenheim starts at 05:13 - 7 min fast!!
He 111 starts at 05:18 - 3 min late?!

Whats going on :S :S :S

ZaltysZ
04-27-2011, 05:18 PM
if (Time.tickCounter() % 72000 == 72000) is wrong probably.

This will always result in FALSE. % gives you a remainder of division (Остаток от деления), so this operation will always give result greater or equal to 0 and less than divisor (assuming positive numbers).

if (Time.tickCounter() % 72000 == 0)

Will be TRUE every time tickCounter() returns multiple of 72000 (i.e. every time 72000 ticks pass, when counted from 0: 72000, 2*72000, 3*72000 and so on).

mcler002
04-27-2011, 05:20 PM
Check attachment...

Is the last comment for me or :S

Ataros
04-27-2011, 05:30 PM
if (Time.tickCounter() % 72000 == 0)

Will be TRUE every time tickCounter() returns multiple of 72000 (i.e. every time 72000 ticks pass, when counted from 0: 72000, 2*72000, 3*72000 and so on).

And if I want to delay the first execution by 71999 ticks it should be like follows?
if (Time.tickCounter() % 72000 == 71999)

Thanks a lot for your help.

FG28_Kodiak
04-27-2011, 05:52 PM
The % is the modulus operator in C# (C, C++ and others)
http://en.wikipedia.org/wiki/Modulo_operation

ZaltysZ
04-27-2011, 05:53 PM
And if I want to delay the first execution by 71999 ticks it should be like follows?
if (Time.tickCounter() % 72000 == 71999)


Yes. The general formula is:

if (Time.tickCounter() % A == B)

where:

A = 30 * amount second of seconds you want to repeat something
B = 30 * amount second you want to offset (delay) from beginning of mission

I suppose you want to delay something by 72000 and not by 71999 (although the difference is only 1/30s). So:

if (Time.tickCounter() % 72000 == 0 && Time.tickCounter()-72000==0)

mcler002
04-27-2011, 05:53 PM
The % is the modulus operator in C# (C, C++ and others)
http://en.wikipedia.org/wiki/Modulo_operation

You trying to blow my brains out haha?

ZaltysZ
04-27-2011, 06:21 PM
Regarding ticks.

1) naryv (dev) said that 30 ticks are around 1 second. Because of that "around", you can get errors. :)

2) No one said that single tick always takes the same amount of time (if so, lag can screw your timing badly).

mcler002
04-27-2011, 08:09 PM
Regarding ticks.

1) naryv (dev) said that 30 ticks are around 1 second. Because of that "around", you can get errors. :)

2) No one said that single tick always takes the same amount of time (if so, lag can screw your timing badly).

Wants 30 ticks to equal 1 seconds on the dot :(! or 1 tick to equal one second!

please ;)

Ataros
04-27-2011, 10:36 PM
30 ticks ~ 1 sec

Tested this. Works most of the time I think ))

Thanks to all for scripts!

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{

// loads my sub-missions
public override void OnTickGame()
{

if (Time.tickCounter() % 72000 == 18000) // 40-10
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFsmGroundv1_0.mis");
GamePlay.gpHUDLogCenter("Protect friendly shipping in the channel near France!");
}

if (Time.tickCounter() % 72000 == 71999) // 40-40
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFsmBombersv1_0.mis");
GamePlay.gpHUDLogCenter("Intel: Enemy bombers are heading to blue airfields!");
}

if (Time.tickCounter() % 72000 == 45000) // 40-25
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFsmBombersv1_0a.mis");
GamePlay.gpHUDLogCenter("Intel: Enemy bombers are heading to red airfields in France!");
}


}

// destroys aircraft abandoned by a player
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return; }

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if ((PlaneIsEmpty) && (actor as AiAircraft).IsAirborne())
{

(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sElevatorDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sAileronsDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sRudderDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng0Tot alFailure);
//for 2mots
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng1Tot alFailure);

//then wait 10min
Timeout(600.0, () =>
{
(actor as AiAircraft).Destroy();
});

}
else if (PlaneIsEmpty)
{
(actor as AiAircraft).Destroy();
}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
_DespawnEmptyPlane(actor);
}
// destroys crushlanded aircraft in 10 minutes
public override void OnAircraftCrashLanded(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftCrashLanded(missionNumber, shortName, aircraft);
Timeout(600, () =>
{
aircraft.Destroy();
});
}
}


Runs at Repka server.

Ataros
04-28-2011, 09:13 AM
Valuable note from a developer here

With new engine you can create your own game inside our game, for example: you connect to server, and server sends to you completly new user interface (no restriction, but protected by sandbox, no one can read, write or modify your data that out border of game).
New GUI, new rules of game, new score system with ranks and etc.
It can do right now, anyone for their game server.
Of course you need some knowledge of scripting and design. We will assist wherever possible to all comers.
We are working to create examples.

Imagine in the future, each server will be unique, different battles on land, in air or under water, or global war :)

Anyone wants to write an interface for an online war?

ATM we have some knowledge on the following:
- triggers to check if mission objectives are complete
- scripts to load new mission objectives into a current mission based on triggers
- simple interface to give players new objectives GamePlay.gpHUDLogCenter

Say if enemy tanks are destroyed in a mission, we can move frontline, change one airfield spawnpoint from blue to red and load next mission objectives. But a good interface mod would be extremely useful to show different briefings based on airfields selected, to allow relocating airgroups from airfield to airfield, manage fuel resources, routes of supply convoys, voting for a commander, etc.
There is a great game-mode mod called "Warfare" in ArmA2. I hope we can create something similar and better.

MuxaHuk
04-28-2011, 09:34 AM
This sample to use Time.current()
count in seconds from started battle.

private double nextMsgTime = 0;
public override void OnTickGame() {
base.OnTickGame();
// Time. current() in seconds from Battle Start
if ( Time.current() > nextMsgTime ) {
nextMsgTime = Time.current() + 10.0; // 10 seconds to next message
GamePlay.gpHUDLogCenter( "Time elapsed (in seconds) = " + Time.current() + ", next message will be at "+nextMsgTime);
}
}

Flashman
04-28-2011, 04:09 PM
These all are very useful posts, in fact I have borrowed a bit of the script for my own mission that I hope will appear on the Syndicate Server soon.

I have a few questions as I know nothing about these scripts

1) If I want the text that comes up with the 'GamePlay.gpHUDLogCenter' command to show to only one team, can this be done and if so how?

2) I have noriced that using these scripts with the spawn removal stops the in game action and trigger events working where it spawns an aircraft. Is there a way of using both?

Keep up the good work, and thanks for your help in advance.

Ataros
04-28-2011, 05:24 PM
These all are very useful posts, in fact I have borrowed a bit of the script for my own mission that I hope will appear on the Syndicate Server soon.

I have a few questions as I know nothing about these scripts

1) If I want the text that comes up with the 'GamePlay.gpHUDLogCenter' command to show to only one team, can this be done and if so how?

2) I have noriced that using these scripts with the spawn removal stops the in game action and trigger events working where it spawns an aircraft. Is there a way of using both?

Keep up the good work, and thanks for your help in advance.

1) I asked devs the same question at Sukhoi.ru.

2) Did not quite get what you mean by "spawn removal" and "trigger events working where it spawns an aircraft". Could you clarify please.

Ataros
04-28-2011, 06:00 PM
New bits of code from devs.

Shows mission objectives to players depending on side and aircraft type (fighter/bomber).

"hitler caput" lol

public override void OnPlaceEnter(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceEnter(player, actor, placeIndex);
AiAircraft aircraft = actor as AiAircraft;

if (aircraft != null)
switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] {player},"Red Bomber, Bomb it all, hitler caput"); }
else { GamePlay.gpHUDLogCenter(new Player[] { player }, "Red Fighter, fight them all"); }
break;
case 2:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Das bomber!"); }
else { GamePlay.gpHUDLogCenter(new Player[] { player }, "Das jager!"); }
break;

}
}

public override void OnAircraftTookOff(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftTookOff(missionNumber, shortName, aircraft);

if (GamePlay.gpPlayer().Place() != aircraft)
return;

switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Bomber, Bomb it all, hitler caput"); }
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Fighter, fight them all"); }
break;
case 2:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Das bomber!"); }
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Das jager!"); }
break;

}
}

Flashman
04-28-2011, 06:18 PM
Hi Ataros,

Hopefully I will be a little more clear this time!

I used the in-game script system using a Trigger to cause an Action to happen. Eg in my missions if a plane I select is shot down, it triggers the spawn of another plane.

EDIT>Script

Trigger: Walrus 1= Target Group destroyed (Walrus flying boat selected)
Action: Walrus 1= Air spawn group (second walrus selected)

This system works in single player, so that when the first walrus is shot down a second spawns at a preselected place. However, when I include the scripts you guys have been developing to despawn empty aircraft (for use online) the ingame script above does not work in either single or multiplayer.

Any ideas what i am doing wrong?

mcler002
04-28-2011, 06:31 PM
I was just looking at the .mis files in notepad...


Example
[PARTS]
core.100
bob.100
[MAIN]
MAP Land$English_Channel_1940
BattleArea 200000 160000 120000 100000 9000
TIME 5
WeatherIndex 0
CloudsHeight 1000
BreezeActivity 1
ThermalActivity 1
[GlobalWind_0]
Power 3.000 0.000 0.000
BottomBound 0.00
TopBound 1500.00
GustPower 5
GustAngle 45
[splines]
[AirGroups]
gb02.0F
[gb02.0F]
Flight0 1 2 3
Flight1 11 12 13
Flight2 21 22 23
Flight3 31 32 33
Class Aircraft.BlenheimMkIV
Formation VIC
CallSign 31
Fuel 86
Weapons 1 1 2 1 1
Detonator Bomb.Bomb_GP_250lb_MkIV 2 130 11
Skill 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
[gb02.0F_Way]
NORMFLY 224480.60 255230.91 500.00 230.00
NORMFLY 254029.14 255139.99 1000.00 230.00
NORMFLY 274678.41 250003.49 1500.00 230.00
NORMFLY 290803.61 240345.28 1500.00 230.00
GATTACK_POINT 290788.83 215917.45 1500.00 230.00
NORMFLY 290883.76 208132.47 1500.00 230.00
NORMFLY 265387.72 208373.88 1500.00 230.00
NORMFLY 246038.12 228039.38 1500.00 230.00
NORMFLY 224003.28 252601.51 1500.00 230.00
[CustomChiefs]
[Stationary]
[Buildings]
[BuildingsLinks]
[Trigger]
trigger TTime 1200


Is there any way of adding a line to prompt "end mission" at time #### ???

Also looks like we can edit aircraft here much "easier"... if you know what your doing! :D

NOTE - not at home to test it myself lol

Ross

Flashman
04-28-2011, 06:31 PM
New bits of code from devs.

Shows mission objectives to players depending on side and aircraft type (fighter/bomber).

"hitler caput" lol

public override void OnPlaceEnter(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceEnter(player, actor, placeIndex);
AiAircraft aircraft = actor as AiAircraft;

if (aircraft != null)
switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] {player},"Red Bomber, Bomb it all, hitler caput"); }
else { GamePlay.gpHUDLogCenter(new Player[] { player }, "Red Fighter, fight them all"); }
break;
case 2:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Das bomber!"); }
else { GamePlay.gpHUDLogCenter(new Player[] { player }, "Das jager!"); }
break;

}
}

public override void OnAircraftTookOff(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftTookOff(missionNumber, shortName, aircraft);

if (GamePlay.gpPlayer().Place() != aircraft)
return;

switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Bomber, Bomb it all, hitler caput"); }
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Fighter, fight them all"); }
break;
case 2:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Das bomber!"); }
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Das jager!"); }
break;

}
}

THis is an interesting one, just tried it! The only thing is that for me the german one says 'Das jager' even when I am in a bomber such as the Ju87 or Ju88. Is there any setting I need to apply?

FG28_Kodiak
04-28-2011, 07:28 PM
Argh german language:

Das bomber! -> (singular) Der Bomber! (plural) Die Bomber!
Das jager! -> (singular) Der Jäger! (plural) Die Jäger!

Next time i fly a bombing raid over the translator. :grin:

AircraftType could be:
AmphibiousPlane
BNZFighter
Bomber
DiveBomber
Fighter
Glider
HeavyFighter
JaBo
SailPlane
Scout
Sturmovik
TNBFighter
TorpedoBomber
Transport
UNKNOWN

So if you are in a Ju87 or Ju88 there should be Bomber or DiveBomber to Show that you are in a Bomber

if ((aircraft.Type() == AircraftType.Bomber) || (aircraft.Type() == AircraftType.DiveBomber)) // if Bomber or Divebomber
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Der Bomber!"); } // show Der Bomber!
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Der Jäger!"); } //in all other cases show Der Jäger!

Ataros
04-28-2011, 09:08 PM
Any ideas what i am doing wrong?

I did not learn how to use triggers yet but if you paste here a complete script I am sure someone would help.

Ataros
04-28-2011, 09:13 PM
Is there any way of adding a line to prompt "end mission" at time #### ???

Depends on what you mean by end mission. It is like in real life when one mission is over you have another one if you are alive or if you have none you have a vacation.

I think you can shut server down with .cmd file.

mcler002
04-28-2011, 09:47 PM
Well as you know we both start a mission through the script, but i want to know if we can stop it... as we had already discused :S

But as we dont know how to do this via scipt, i was woundering is we could do it through the .mis file...

ATAG_Bliss
04-28-2011, 10:12 PM
Yeah, I would like to know this as well. The way the MP missions are designed are amazing (with missions able to be loaded into missions etc.) but, for instance, lets say you want an ongoing war, how are you going to stop it from going into the night?

Or could you just load a mission and make the sun appear again out of nowhere, without missing a beat, while others are playing at the same time?

More testing I guess :)

Ataros
04-28-2011, 10:25 PM
I wish I were a part of the dev team and know all the answers :grin:

Meanwhile another script destroying abandoned planes from ru forums. Tell me what you think of it.

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
private bool isAiControlledPlane (AiAircraft aircraft)
{
if (aircraft == null)
{
return false;
}

Player [] players = GamePlay.gpRemotePlayers ();
foreach (Player p in players)
{
if (p != null && (p.Place() is AiAircraft) && (p.Place() as AiAircraft) == aircraft)
{
return false;
}
}

return true;
}

private void destroyPlane (AiAircraft aircraft)
{
if (aircraft != null) {
aircraft.Destroy ();
}
}

private void explodeFuelTank (AiAircraft aircraft)
{
if (aircraft != null)
{
aircraft.hitNamed (part.NamedDamageTypes.FuelTank0Exploded);
/***
aircraft.hitNamed (part.NamedDamageTypes.FuelTank1Exploded);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank2Exploded);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank3Exploded);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank4Exploded);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank5Exploded);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank6Exploded);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank7Exploded);
***/
}
}

private void fuelTankFire (AiAircraft aircraft)
{
if (aircraft != null)
{
aircraft.hitNamed (part.NamedDamageTypes.FuelTank0Fire);
/***
aircraft.hitNamed (part.NamedDamageTypes.FuelTank1Fire);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank2Fire);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank3Fire);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank4Fire);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank5Fire);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank6Fire);
aircraft.hitNamed (part.NamedDamageTypes.FuelTank7Fire);
***/
}
}

private void destroyAiControlledPlane (AiAircraft aircraft)
{
if (isAiControlledPlane (aircraft))
{
destroyPlane (aircraft);
}
}

private void damageAiControlledPlane (AiActor actor)
{
if (actor == null || !(actor is AiAircraft))
{
return;
}

AiAircraft aircraft = (actor as AiAircraft);

if (!isAiControlledPlane (aircraft))
{
return;
}

if (aircraft == null)
{
return;
}

aircraft.hitNamed (part.NamedDamageTypes.ControlsElevatorDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsAileronsDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsRudderDisabled);

aircraft.hitNamed (part.NamedDamageTypes.FuelPumpFailure);
// aircraft.hitNamed (part.NamedDamageTypes.Eng0TotalFailure);
// aircraft.hitNamed (part.NamedDamageTypes.Eng1TotalFailure);

/*** Tank fire doesn't work after engine total failure - ???
Timeout (15, () =>
{fuelTankFire (aircraft);}
);
***/

/*** Cool, but kills fps
Timeout (25, () =>
{explodeFuelTank (aircraft);}
);
***/

Timeout (90, () =>
{destroyPlane (aircraft);}
);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

public override void OnPlaceLeave (Player player, AiActor actor, int placeIndex) {
base.OnPlaceLeave (player, actor, placeIndex);
Timeout (1, () =>
{damageAiControlledPlane (actor);}
);
}

public override void OnAircraftCrashLanded (int missionNumber, string shortName, AiAircraft aircraft) {
base.OnAircraftCrashLanded (missionNumber, shortName, aircraft);
Timeout (30, () =>
{destroyAiControlledPlane (aircraft);}
);
}

/**
public override void OnAircraftTookOff (int missionNumber, string shortName, AiAircraft aircraft) {
base.OnAircraftTookOff (missionNumber, shortName, aircraft);
...
}
**/
}


for instance, lets say you want an ongoing war, how are you going to stop it from going into the night?

I think just like in real life you order (with a script) your units to rtb when it is getting dark. Then they have a rest till early morning.


But as we dont know how to do this via scipt, i was woundering is we could do it through the .mis file...

I think you can stop mission with a script like you can stop real life: kill all units, stop time and that's it.

Quote a Dev:
Выгрузить - это сложно, миссия же может по скрипту кого-то нарожать, что-то в себя подгрузить и т.д
"To unload (a mission) - it is difficult, because a mission can give birth to something using scripts, upload smth into itself, etc."

My guess is you can switch server off, but you can not unload a mission as you can not unload life as it gives birth to smth :grin: This is not a game this is real life simulator.

FG28_Kodiak
04-28-2011, 10:35 PM
Problem with exploding fuel tanks could be that other players also get damaged.

Flashman
04-29-2011, 09:42 AM
Hi Guys, im having some fun with this scripting business and have finally got a script that works, however I could do with some help with the timing commands:

I know that 1800 ticks = 1 minute but im not entirely sure what these two number cause to happen. From my script file:

if (Time.tickCounter() % 126000 == 18000)

When this counts down a mission is launched but im unsure as to the significane of the two timings:

does the 126000 give the time between each repeat operation of the operation?

I have found the second number, 18000 in this case appears to set the time for the first operation. Is this correct?

SO, if i want the operation (in this case a mission starts within themain mission and planes spawn) to repeat every 2 hours, but the first operation is 10 minutes after the main mission begins would this be correct?

if (Time.tickCounter() % 216000 == 18000)

Thanks!

mcler002
04-29-2011, 09:49 AM
1st number = repeat i.e if it was 108000 - the map/ mission should load every 1hour...

2nd number = start time i.e. if it was 18000 = the map/mission should start within 10 minutes of the game start, or repeat interval...

But i dont think it works 100%... but as i have been told 1800 ticks "roughly" equals a minute...

Flashman
04-29-2011, 10:24 AM
1st number = repeat i.e if it was 108000 - the map/ mission should load every 1hour...

2nd number = start time i.e. if it was 18000 = the map/mission should start within 10 minutes of the game start, or repeat interval...

But i dont think it works 100%... but as i have been told 1800 ticks "roughly" equals a minute...

Cool, thanks.

I actually did some offline testing and set the timings to minutes adn sped things up! It appears to work roughly as you say... it will do for now!

mcler002
04-29-2011, 10:30 AM
Cool, thanks.

I actually did some offline testing and set the timings to minutes adn sped things up! It appears to work roughly as you say... it will do for now!

Yea i did offline testin as well... but x16 is just not fast enough lol! only went a couple of hours in...

mcler002
04-29-2011, 12:15 PM
Ive tested and tested... its not working :S

Help !

Ataros
04-30-2011, 01:58 AM
Just to have it all in one thread


public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () =>
{
AiAircraft CurAircraft = player.Place() as AiAircraft;
AiAircraft PrevAircraft = actor as AiAircraft;
if (CurAircraft != PrevAircraft)
{ (actor as AiAircraft).Destroy(); }
});
}

Ataros
04-30-2011, 02:09 AM
Hi Ataros,

Hopefully I will be a little more clear this time!

I used the in-game script system using a Trigger to cause an Action to happen. Eg in my missions if a plane I select is shot down, it triggers the spawn of another plane.

EDIT>Script

Trigger: Walrus 1= Target Group destroyed (Walrus flying boat selected)
Action: Walrus 1= Air spawn group (second walrus selected)

This system works in single player, so that when the first walrus is shot down a second spawns at a preselected place. However, when I include the scripts you guys have been developing to despawn empty aircraft (for use online) the ingame script above does not work in either single or multiplayer.

Any ideas what i am doing wrong?

Checked ingame trigger system. Did not work with external scrips but it is by itself just fantastic! I think it is possible to achieve what I tried to do loading sub-missions into a mission with this trigger system only. I'll switch to it for a while from scripting as I do not know C#. Very helpful thread on this http://forum.1cpublishing.eu/showthread.php?t=20995&highlight=builder&page=2

However we should try:

1) make a mission with internal triggers without script
2) make a mission with script that loads the first mission in.
3) load more missions when needed.
I will not have time to try this for a couple of days however ((

Alternatively you can program all the triggers in a script by hand. Check links in the 1st message of this thread for examples.

e.g. / / $ Reference Campaign.dll
/ / - $ Debug
using System;
using maddox.game;
using maddox.game.world;

public class Mission: maddox.game.campaign.Mission {

public override void OnTrigger (int missionNumber, string shortName, bool active)
{
if ("trigger". Equals (shortName) & & active)
{
GamePlay.gpHUDLogCenter ("Triggers trigger");
}
}

} using System;
using maddox.game;
using maddox.game.world;


class Mission: maddox.game.AMission
{
public override void OnActorDead (int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List <DamagerScore> damages)
{
base.OnActorDead (missionNumber, shortName, actor, damages);
AiAction action = GamePlay.gpGetAction ("TestAction");
if (action! = null)
{
action.Do ();
}
}
}

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : maddox.game.AMission
{
private List<AiAction> actions = new List<AiAction>();
private int round = 1;
private bool completed = false;

public override void OnBattleStarted()
{
AiAction action = GamePlay.gpGetAction("startGroup2");
if (action != null) actions.Add(action);
action = GamePlay.gpGetAction("startGroup3");
if (action != null) actions.Add(action);
GamePlay.gpHUDLogCenter(String.Format("Раунд {0}", round));
}

public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)
{
base.OnActorDead(missionNumber, shortName, actor, damages);
if (!(actor is AiAircraft))
return; // Не самолет

int army = (actor as AiAircraft).Group().Army();
if (army == 1)
{
if (!completed)
{
bool fail = (actor as AiAircraft).AirGroup().DiedAircrafts >= (actor as AiAircraft).AirGroup().InitNOfAirc;
if (fail)
{
GamePlay.gpHUDLogCenter("Миссия провалена.");
}
}
}
else
{
bool next = (actor as AiAircraft).AirGroup().DiedAircrafts >= (actor as AiAircraft).AirGroup().InitNOfAirc;
if (next)
{
if (round == 3)
{
completed = true;
GamePlay.gpHUDLogCenter("Поздравляем, миссия пройдена!");
}
else
{
round++;
startNewRound();
}
}
}
}

private void startNewRound()
{
GamePlay.gpHUDLogCenter(String.Format("Раунд {0}", round));
if (actions.Count > 0)
{
actions[0].Do();
actions.RemoveAt(0);
}
}
}



http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=ru&tl=en&u=http%3A%2F%2Fwww.sukhoi.ru%2Fforum%2Fshowthread. php%3Ft%3D68369

Ive tested and tested... its not working :S

Help !


Would you tell us what exactly you are trying to do and what does not work. Run my script it loads missions on timing more or less. Does not always destroy planes on the server however.

mcler002
04-30-2011, 06:17 AM
I have pretty much copied and pasted your scripting ...

I always right click and compile to see if the script is OK, which it is ... So when ever I try and test it ... My ai bots are still flying

At the current time I am in the middle of making a new online map with less 'repeat mission' loading, and more internal triggers

But as you have posted above, I will need script for 'triggers' to flash messages on the screen about incoming planes etc ...

I shall give the above a try when I'm on my pc later!

Ataros
04-30-2011, 03:25 PM
So when ever I try and test it ... My ai bots are still flying

Ahh, if you mean bot removal script, it works on my PC when I create a server, but does not work on a dedi server somehow ((
The issue reported to the devs already.

Try the second script I copied from sukhoi.ru.

Just uploaded a new mission into missions thread. http://forum.1cpublishing.eu/showpost.php?p=276373&postcount=31

FG28_Kodiak
04-30-2011, 04:10 PM
Do you try ABattle and not AMission?

Ataros
04-30-2011, 05:19 PM
Do you try ABattle and not AMission?

This is the latest script I used. Do you mean I should change
public class Mission : AMission
to
public class Mission : ABattle
Should I?
Every script I have seen uses AMission I think.

// v.1.6.14

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{

// loads my sub-missions
public override void OnTickGame()
{

if (Time.tickCounter() % 72000 == 18000) // 40-10
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFv1_6Ground1.mis");
GamePlay.gpHUDLogCenter("Protect friendly shipping in the channel near France!");
}

if (Time.tickCounter() % 72000 == 71999) // 40-40
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFv1_6Bombers1.mis");
GamePlay.gpHUDLogCenter("Intel: Enemy bombers are heading to blue airfields!");
}

if (Time.tickCounter() % 72000 == 45000) // 40-25
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/128BoF/128BoFv1_6Bombers2.mis");
GamePlay.gpHUDLogCenter("Intel: Enemy bombers are heading to red airfields in France!");
}


}

// destroys aircraft abandoned by a player
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return; }

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if ((PlaneIsEmpty) && (actor as AiAircraft).IsAirborne())
{

(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sElevatorDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sAileronsDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Control sRudderDisabled);
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng0Tot alFailure);
//for 2mots
(actor as AiAircraft).hitNamed(part.NamedDamageTypes.Eng1Tot alFailure);

//then wait 10min
Timeout(600.0, () =>
{
if (actor is AiAircraft)
{
(actor as AiAircraft).Destroy();
}
});

}
else if (PlaneIsEmpty)
{
if (actor is AiAircraft)
{
(actor as AiAircraft).Destroy();
}
};
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
_DespawnEmptyPlane(actor);
}
// destroys crushlanded aircraft in 10 minutes
public override void OnAircraftCrashLanded(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftCrashLanded(missionNumber, shortName, aircraft);
Timeout(600, () =>

{
if (aircraft != null)
{
aircraft.Destroy();
}
});
}
}

ZaltysZ
04-30-2011, 05:30 PM
I am not sure it is possible to overload ABattle without creating your own add-in.

FG28_Kodiak
04-30-2011, 06:15 PM
Hm just try and error and see what happen, ABattle has mostly the same methods than AMission. The only examples i know are from the campaign directory and are only single missions.
I wish there where a documentation about scripting. :rolleyes:

No457_Squog
05-01-2011, 04:14 PM
Script for despawning planes without humans inside. Multicrew friendly.

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
{ return;}

Player[] Players = GamePlay.gpRemotePlayers();

bool PlaneIsEmpty = true;

foreach (Player i in Players)
{
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;
break;
}
}

if (PlaneIsEmpty)
{ (actor as AiAircraft).Destroy(); }
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () =>
{
_DespawnEmptyPlane(actor);
});
}
}
}

No457_Mako & myself tweaked this code so that the server is included in the workings. The Server isn't listed in the GamePlay.gpRemotePlayers() array.using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
return;
Player[] Players = GamePlay.gpRemotePlayers();
bool PlaneIsEmpty = true;
foreach (Player i in Players) {
if (((i.Place() as AiAircraft) == (actor as AiAircraft)) || ((GamePlay.gpPlayer().Place() as AiAircraft) == (actor as AiAircraft))) {
PlaneIsEmpty = false;
break;
}
}
if (PlaneIsEmpty) {
(actor as AiAircraft).Destroy();
}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex) {
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () => {
_DespawnEmptyPlane(actor);
});
}
}

Flashman
05-01-2011, 06:00 PM
HI Squoag,

I tried your version in nthe post above and it despawned the plane if I changed from pilot to a gunners position.

I tested this on my own 'server' and in single player. Obviously in MP this would not be desireable!

No457_Squog
05-01-2011, 10:26 PM
Hi Flashman,

Are you 100% sure that you used the second code block in my post and not the first? What you're seeing is very symptomatic of the first code block in my post. I put it there as a before/after for the original author but perhaps I should mark it more clearly...

SC/JG Matoni
05-02-2011, 12:47 PM
No457_Mako & myself tweaked this code so that the server is included in the workings. The Server isn't listed in the GamePlay.gpRemotePlayers() array.using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public void _DespawnEmptyPlane(AiActor actor)
{
if (actor == null)
return;
Player[] Players = GamePlay.gpRemotePlayers();
bool PlaneIsEmpty = true;
foreach (Player i in Players) {
if (((i.Place() as AiAircraft) == (actor as AiAircraft)) || ((GamePlay.gpPlayer().Place() as AiAircraft) == (actor as AiAircraft))) {
PlaneIsEmpty = false;
break;
}
}
if (PlaneIsEmpty) {
(actor as AiAircraft).Destroy();
}
}

public override void OnPlaceLeave(Player player, AiActor actor, int placeIndex) {
base.OnPlaceLeave(player, actor, placeIndex);
Timeout(1, () => {
_DespawnEmptyPlane(actor);
});
}
}

~S

Will test on Australian Skies tomorrow

EDIT: This works for me, thanks No457_Mako & No457_Squog, has helped with server stability. Ran 3 maps no worries, we were having issues with loading new maps before this

Worked with Position swap ONLINE in the bf 110 as well.

Matoni

Flashman
05-02-2011, 06:16 PM
Hi Flashman,

Are you 100% sure that you used the second code block in my post and not the first? What you're seeing is very symptomatic of the first code block in my post. I put it there as a before/after for the original author but perhaps I should mark it more clearly...

Hi Sqouag,

Im pretty sure I tried both but truth be told you have me wondering now.... I will try this again when I get the time and see if it works for me.

Please note: i tried this on my own 'server' not on the Syndicate server.

Ataros
05-03-2011, 09:01 AM
Script to destroy actors in a mission (e.g. before loading new one to server).

This kills mission (or submission) own actors. To kill all actors 'living' on a server (e.g. loaded by other missions) remove the lines put in blue color.

foreach (int army in GamePlay.gpArmies())
{
foreach (AiAirGroup group in GamePlay.gpAirGroups(army))
{
if (ActorName.MissionNumber(group.Name()).Equals(Miss ionNumber))
{
AiActor[] members = group.GetItems();
for (int i = members.Length - 1; i > -1; i--)
{
(members[i] as AiAircraft).Destroy();
}
}
}
foreach (AiGroundGroup group in GamePlay.gpGroundGroups(army))
{
if (ActorName.MissionNumber(group.Name()).Equals(Miss ionNumber))
{
AiActor[] members = group.GetItems();
for (int i = members.Length - 1; i > -1; i--)
{
(members[i] as AiGroundActor).Destroy();
}
}
}
}

Should solve "actor not destroyed" problem.

May need some testing and fine-tuning.

SC/JG Matoni
05-05-2011, 10:16 AM
~S

I would appear Beta 4 breaks all of these kill actor scripts... well it does 4 me

Blackrat
05-05-2011, 10:59 AM
~S

I would appear Beta 4 breaks all of these kill actor scripts... well it does 4 me

Phew its not just our server then, I rolled back to Beta 1 and the scripts work again.

Macka
05-05-2011, 02:35 PM
And it reintroduces the stutters online which I kinda missed .....NOT!....lol. Rolled client back to 14305 will try on Matoni's OGN later. :)

Ataros
05-05-2011, 10:38 PM
~S

I would appear Beta 4 breaks all of these kill actor scripts... well it does 4 me

Try this one. I think it worked today on patched Repka. (5 min timeout)
// v.1.6.17 trig NEW

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{

// destroys aircraft abandoned by a player
private bool isAiControlledPlane (AiAircraft aircraft)
{
if (aircraft == null)
{
return false;
}

Player [] players = GamePlay.gpRemotePlayers ();
foreach (Player p in players)
{
if (p != null && (p.Place () is AiAircraft) && (p.Place () as AiAircraft) == aircraft)
{
return false;
}
}

return true;
}

private void destroyPlane (AiAircraft aircraft) {
if (aircraft != null) {
aircraft.Destroy ();
}
}

private void explodeFuelTank (AiAircraft aircraft)
{
if (aircraft != null)
{
aircraft.hitNamed (part.NamedDamageTypes.FuelTank0Exploded);
}
}

private void destroyAiControlledPlane (AiAircraft aircraft) {
if (isAiControlledPlane (aircraft)) {
destroyPlane (aircraft);
}
}

private void damageAiControlledPlane (AiActor actor) {
if (actor == null || !(actor is AiAircraft)) {
return;
}

AiAircraft aircraft = (actor as AiAircraft);

if (!isAiControlledPlane (aircraft)) {
return;
}

if (aircraft == null) {
return;
}

aircraft.hitNamed (part.NamedDamageTypes.ControlsElevatorDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsAileronsDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsRudderDisabled);
aircraft.hitNamed (part.NamedDamageTypes.FuelPumpFailure);
aircraft.hitNamed (part.NamedDamageTypes.Eng0TotalFailure);
aircraft.hitNamed (part.NamedDamageTypes.Eng1TotalFailure);

/***Timeout (240, () =>
{explodeFuelTank (aircraft);}
);
* ***/

Timeout (300, () =>
{destroyPlane (aircraft);}
);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

public override void OnPlaceLeave (Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave (player, actor, placeIndex);
Timeout (1, () =>
{damageAiControlledPlane (actor);}
);
}

public override void OnAircraftCrashLanded (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftCrashLanded (missionNumber, shortName, aircraft);
Timeout (300, () =>
{ destroyPlane(aircraft); }
);
}
public override void OnAircraftLanded (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftLanded(missionNumber, shortName, aircraft);
Timeout(300, () =>
{ destroyPlane(aircraft); }
);
}


}

Ataros
05-06-2011, 08:46 AM
Sample shows moving frontline and changing spawnpoints from red to blue and vice versa based on trigger (flyby above an airfield).

Can someone program a small 3 airfields battle based on it? Say a middle airfield becomes red or blue based on which tanks remain alive after taking the airfield. Then spawn new groups of tanks in say 20 minutes for a new round.


using System;
using System.Collections;
using maddox.game;
using maddox.game.world;


public class Mission : AMission
{
internal class MissionMarker
{
internal double x;
internal double y;
internal int army;
internal MissionMarker(double x, double y, int army) { this.x = x; this.y = y; this.army = army; }
}



private MissionMarker[] MissionMarkers = new MissionMarker[]
{ new MissionMarker(17100.80,14515.20,2),
new MissionMarker(20428.80, 8934.40, 2),
new MissionMarker(12492.80, 17203.20, 1),
new MissionMarker(11801.60, 21555.20, 1)
};


internal ISectionFile CreateNewFrontLineMission(int markerNum, int newArmy)
{
MissionMarkers[markerNum].army = newArmy;
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (bp != null)
bp.destroy();

}
ISectionFile f = GamePlay.gpCreateSectionFile();
string sect;
string key;
string value;
sect = "FrontMarker";
for (int i = 0; i < MissionMarkers.Length; i++)
{
key = "FrontMarker" + i.ToString();
value = MissionMarkers[i].x.ToString(System.Globalization.CultureInfo.Invar iantCulture.NumberFormat) + " " + MissionMarkers[i].y.ToString(System.Globalization.CultureInfo.Invar iantCulture.NumberFormat) + " " + MissionMarkers[i].army.ToString();
f.add(sect, key, value);
}
sect = "BirthPlace";
for (int i = 0; i < MissionMarkers.Length; i++)
{
key = "BirthPlace_" + i.ToString();
value = " " + MissionMarkers[i].army.ToString() + " " + MissionMarkers[i].x.ToString(System.Globalization.CultureInfo.Invar iantCulture.NumberFormat) + " " + MissionMarkers[i].y.ToString(System.Globalization.CultureInfo.Invar iantCulture.NumberFormat) + " 0 10 1 0 . . .";
f.add(sect, key, value);
}

return f;
}

public override void OnTrigger(int missionNumber, string shortName, bool active)
{
base.OnTrigger(missionNumber, shortName, active);
for (int i = 0; i < MissionMarkers.Length; i++)
for (int j = 1; j < 3; j++)
{
string str = "changeArmy" + i.ToString() + "_" + (j).ToString();
if (str.Equals(shortName))
{
string armyOwner;
if (j == 1) { armyOwner = " Red army"; }
else { armyOwner = " Blue army"; }
GamePlay.gpHUDLogCenter("Airdrome: " + i.ToString() + " turn to " + armyOwner);
GamePlay.gpPostMissionLoad(CreateNewFrontLineMissi on(i, j));
}
}
AiAction action = GamePlay.gpGetAction(ActorName.Full(missionNumber, shortName));
if (action != null)
action.Do();

}
}

MadTommy
05-06-2011, 10:02 AM
... my head hurts trying to understand this..:grin:

Does anyone fancy writing a fuckwits guide to all this, err sorry i mean a dummies guide? It would be very much appreciated, i'd buy the 1st round or virtual beers!

I'm keen to create MP missions but trying to gain the level of understanding needed from these forums and google translations is rather daunting. And i suspect waiting for an official manual would be foolish, considering the flight manual produced.

But thanks for all the help provided here, it is appreciated.. just a bit confusing for a new mission builder.

Ataros
05-06-2011, 04:27 PM
... my head hurts trying to understand this..:grin:

Does anyone fancy writing a fuckwits guide to all this, err sorry i mean a dummies guide?

The guide is called C# for Dummies but you can start with the following. I do not know C# but have a lot of fun with this simple script. It is a huge step forward from original IL-2 online.

This is a sample script to create a small 'campaign' containing a main mission and 3 sub-missions.

Copy this script to Notepad and save it as sample.cs into the same folder your mission will be located, e.g.
C:\Users\%user%\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Multi\Dogfight\My_mis1\
Scripts have to be saved with .cs extension and have the same name as the main mission.

Create and edit your main mission in FMB. In this example the main mission name should be sample.mis because the script name is sample.cs.
Make sure you have both sample.mis and sample.cs in the following directory (on the drive you have your Documents folder):
C:\Users\%user%\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Multi\Dogfight\My_mis1\

Create and edit 3 missions you want to be loaded into the main mission with FMB.
Put these 3 missions in the same directory, name them as mission1.mis, mission2.mis and mission3.mis.
That's it.

In case you saved your mission files into other directory than Multi/Dogfight/Dogfight/My_mis1/ , then edit 3 filepaths in this file.
e.g. the line GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/My_mis1/mission1.mis" contains the path to the 1st sub-mission. *

Change message text after GamePlay.gpHUDLogCenter commands to whatever you like (usually mission objectives and their location on the map).
The text in this example is visible to both sides for simplicity.

You may wish to download and use Microsoft Visual Studio 2010 Express to open and edit .cs files. It is free and makes .cs files easy to read and understand.
Download link http://www.microsoft.com/express/Downloads/#2010-Visual-CS

All text after // marks are comments describing what the script does.
You may play your mission in MP or as a SP mission if you create a passworded server.

I hope to put up some missions using this script to Repka server soon.

/****
* Brief startup guide to scripting.
* This is a sample script to create a small 'campaign' containing a main mission and 3 sub-missions.
*
* Copy this script to Notepad and save it as sample.cs into the same folder your mission will be located, e.g.
* C:\Users\%user%\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Multi\Dogfight\My_mis1\
* Scripts have to be saved with .cs extension and have the same name as the main mission.
* Create and edit your main mission in FMB. In this example the main mission name should be sample.mis because the script name is sample.cs.
* Make sure you have both sample.mis and sample.cs in the following directory (on the drive you have your Documents folder):
* C:\Users\%user%\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Multi\Dogfight\My_mis1\
* Create and edit 3 missions you want to be loaded into the main mission with FMB.
* Put these 3 missions in the same directory, name them as mission1.mis, mission2.mis and mission3.mis.
* That's it.
*
* In case you saved your mission files into other directory than Multi/Dogfight/Dogfight/My_mis1/ , than edit 3 filepaths in the script file.
* e.g. the line GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/My_mis1/mission1.mis" contains the path to the 1st sub-mission. *
*
* Change message text after GamePlay.gpHUDLogCenter commands to whatever you like (usually mission objectives and their location on the map).
* The text in this example is visible to both sides for simplicity.
*
* You may wish to download and use Microsoft Visual Studio 2010 Express to open and edit .cs files. It is free and makes .cs files easy to read and understand.
* Download link http://www.microsoft.com/express/Downloads/#2010-Visual-CS
*
* All text after // marks are comments describing what the script does.
* You may play your mission in MP or as a SP mission if you create a passworded server.
* Have fun! and S! from 3GIAP
*
* Feel free to delete all the comments above and including this line from this file. ****/

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{

public override void OnTickGame()
{

// loads the 1st sub-mission in 10 min and repeates it every 60 min.
if (Time.tickCounter() % 108000 == 18000) // 108000 = 60 min repeat. 18000 = 10 min delay.
// pls. note!!! the 1st figure above must be always larger than 2nd!
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/My_mis1/mission1.mis");

// prints message on screen after mission load
GamePlay.gpHUDLogCenter("Hello, world! Mission1.mis loaded!");

// prints message on screen in 10 minutes / 600 seconds
double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("10 minutes into the 1st mission! Wow! It works!!!");
});

// prints message on screen in 5 minutes / 300 seconds
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Wholy s.. it works!!!");
});

}

// loads the 2nd sub-mission, etc. the same way
if (Time.tickCounter() % 108000 == 54000) // 108000 = 60 min repeat, 54000 = 30 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/My_mis1/mission2.mis");
GamePlay.gpHUDLogCenter("Mission2.mis loaded!");
double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Mission2 10 min message!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Mission2 15 min message!");
});
}

// loads the 3rd sub-mission
if (Time.tickCounter() % 108000 == 90000) // 60 min repeat, 50 min delay
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/My_mis1/mission3.mis");
GamePlay.gpHUDLogCenter("Mission3.mis loaded!");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Mission3 10 min message!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Now it really works! You are a genius! Have fun!");
});
}
}


}


upd. Corrected an error, replaced 1800 ticks with 18000 for 10 minutes.

MadTommy
05-06-2011, 05:55 PM
Ataros - http://www.barmans.co.uk/productimg/19450.jpg

Thanks for all the info here.. i'll try and get my head around this over the weekend, your help is very much appreciated.

Ataros
05-11-2011, 08:36 AM
The above script runs on Repka DS #1 server ATM loading 5 smaller missions into main mission with various time-cycles. Check it out.

ATAG_Bliss
05-11-2011, 09:58 AM
Ataros,

Thanks for all the info. We'll see if the latest kill actor script works with beta 1. We found the latest beta to be far to unstable for the server and have reverted back.

MadTommy
05-11-2011, 10:13 AM
What is the best script to remove empty & crash landed planes.. there seem to be many versions knocking about.

I've heard there are issues with these scripts & the latest patch.. some enlightenment would be much appreciated.

Looking at bob & bof 1.6 neither seem to have these scripts added..:confused:

Ataros
05-11-2011, 10:21 AM
What is the best script to remove empty & crash landed planes.. there seem to be many versions knocking about.

I've heard there are issues with these scripts & the latest patch.. some enlightenment would be much appreciated.

Looking at bob & bof 1.6 neither seem to have these scripts added..:confused:

Did you try this one? http://forum.1cpublishing.eu/showpost.php?p=279080&postcount=92

Runs on Repka server. I think it works (not 100% sure though of cause :grin: ) .

Ataros
05-12-2011, 09:23 AM
Great thread on searchlights and adding AA to trains and trucks

http://forum.1cpublishing.eu/showthread.php?t=22740&page=2

335th_GRAthos
05-13-2011, 12:58 PM
Great thread on searchlights and adding AA to trains and trucks

http://forum.1cpublishing.eu/showthread.php?t=22740&page=2



WOW!

I start getting depressed that flying at 400kmh, jinking like mad, the last thing I will want to do is looking a the detail of the AAA shooting at me.... :-)

It looks as if the mission builders will have as much fun as the pilots with this sim...

Great job, we will go throgh hell finding out about the details but, great job!


Nice week end to all !

Groundhog
05-13-2011, 05:46 PM
Ataros

thanks for all the scripting info.
I am trying your tmp script with three sub missions.
It gets as far as loading the first sub mission and then my plane explodes.
The text message is shown in cockpit then boom!
Please help.

Disregard..pilot error :)
GH

TheEnlightenedFlorist
05-14-2011, 10:16 PM
Thanks for the thread Ataros. Very helpful.

Is there a reason you guys are using "ticks" to measure time. C# has a few different ways of keeping track of time. Here's an example using the Stopwatch class. Don't get me wrong, modulus is great but this stopwatch is probably more accurate and it's a heck of a lot more readable. :)

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;
using System.Diagnostics; //contains Stopwatch class

public class Mission : AMission
{
int timesRun = 0; //count how many times sub-mission has been run

Stopwatch timer = new Stopwatch(); //timer. Counts... time...

public override void OnTickGame()
{

//if sub-mission has never been run, run it
if (timesRun == 0)
{
//start timer
timer.Start();

GamePlay.gpPostMissionLoad("missions/Multi/MyMissions/mission1.mis");
timesRun++;

// prints message on screen after mission load
GamePlay.gpHUDLogCenter("Hello, world! Mission1.mis loaded!");
}

//if five or more minutes have elapsed since the timer was started, run sub-mission
if (timer.Elapsed.Minutes >= 5)
{
GamePlay.gpPostMissionLoad("missions/Multi/MyMissions/mission1.mis");
timesRun++;

GamePlay.gpHUDLogCenter("Hello, world! Mission1.mis loaded!");

//reset timer to zero and restart it
timer.Restart();
}
}
}

ZaltysZ
05-14-2011, 10:58 PM
Don't get me wrong, modulus is great but this stopwatch is probably more accurate and it's a heck of a lot more readable. :)

The problem with external timing is that you will get time according to your system and not to game. Simulation can slow down because of lag, and external timer won't take that into account, i.e. briefing can say that bombers start at 9:00, however you may see that start greatly off its planned time (according to game clock), if you use external timer.

If you want to get rid of counting ticks, you can use this:

//Runs once, when mission is loaded
public override void Init(maddox.game.ABattle battle, int missionNumber)
{
base.Init(battle,missionNumber);
//Planned missions
MissionLoader(30,10,"missions/Multi/Dogfight/bombers1.mis"); // 10s from main mission start and repeatedly every 30s
MissionLoader(100,60,"missions/Multi/Dogfight/bombers2.mis"); // 60s from main mission start and repeatedly every 100s
}

public void MissionLoader(int period, int offset, string mission)
{
if (offset > 0)
Timeout(offset, () => {MissionLoader(period,0,mission);});
else
{
GamePlay.gpPostMissionLoad(mission);
Timeout(period, () => {MissionLoader(period,0,mission);});
}
}

TheEnlightenedFlorist
05-16-2011, 12:19 AM
Oh, I'm sorry. I thought that you guys wanted to base the intervals that missions run on on real time not on game time.

TheEnlightenedFlorist
05-16-2011, 08:09 AM
Okay. I think I've got a handle on how to create and manipulate "MissionMarkers" aka Front Markers in a script. I've attached a simple, commented example. Shoot down the bomber in front of you and the southwest airfield's front marker changes to blue.


Can someone program a small 3 airfields battle based on it? Say a middle airfield becomes red or blue based on which tanks remain alive after taking the airfield. Then spawn new groups of tanks in say 20 minutes for a new round.

I'm confident that if you gave me a mission with an appropriate trigger, I could move and change front markers, but I don't have much experience with the FMB. I've only created single player missions thus far. I don't know how to create an airfield where multiple players can choose an aircraft and spawn at, and I certainly don't know how to change who can spawn at an airfield in a script. Does the code you posted do this? I see mention of "BirthPlaces" in the script, but I don't see any "BirthPlaces" in the FMB.

Do you have a link to a tutorial on how to create multiplayer missions?

Ataros
05-16-2011, 12:42 PM
Does the code you posted do this? I see mention of "BirthPlaces" in the script, but I don't see any "BirthPlaces" in the FMB.

Do you have a link to a tutorial on how to create multiplayer missions?

MP missions are different from SP only by this FMB object called "birthplace" (at least in Russian version) or spawnpoint in English I guess. You find it in Object Browser the same way as other objects like an airfield or a tank. In its property window you can select side it belongs to and list of aircraft available for players. In a mission consisting of many submissions you place birthplaces in the 1st 'main' mission. See my mission as example attached.

When new submission is loaded it can contain a new moved frontline and a new birthplace (e.g. red one) in the location where the blue one used to be. The problem is the old birthplace is not removed by loading a new submission and blue aircraft still can be created in the newly captured red airfield. That is why you need to destroy an old blue birthplace with a script I guess:
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (bp != null)
bp.destroy();

}

E.g. in my Repka mission we have both red and blue airfields in D3. The main mission loads 3 (will be 4 soon) relatively big submissions in itself and 2 small ones.

Ideally I would like to move the frontline and change side of these 2 birthplaces based on results of a recent submission. Say if reds loose more aircrafts or tanks (or more then say 70%) in recent mission reds loose an airfield in D3. If they win next mission they take it back, etc. and repeat it forever.

In the future I believe this script can be used to move frontline across the whole map to create an ongoing war.

Please find a recent version of my mission attached.

Ataros
05-16-2011, 07:49 PM
Could some C# experts check this part of script for errors. Trying to randomize submission loading here. Thanks to Groundhog for idea.

Intended to run in cycle forever. Does not work for me (
Need help please.

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{


// loading sub-missions
public override void OnTickGame()
{

if (Time.tickCounter() % 54000 == 12600) // 54000=30 min repeat. 12600=7 min delay.
{
// randomly selects 1 of several submissions
Random RandomIncident = new Random();

switch (RandomIncident.Next(1, 3))
{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air01.mis");
// GamePlay.gpHUDLogCenter("mis1 loaded!");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
});
break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_sea01.mis");
// GamePlay.gpHUDLogCenter("mis2 loaded");

double initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
});
break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air02.mis");
// GamePlay.gpHUDLogCenter("mis3 loaded!");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
});
break;
}
}

///////////////////////

//loads small submissions w/o messages

if (Time.tickCounter() % 216000 == 108000) // 216000=120 min repeat. 108000=60 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_small01.mis");
}

if (Time.tickCounter() % 216000 == 215999) // 216000=120 min repeat. 215999=120 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_small02.mis");
}
}
}

TheEnlightenedFlorist
05-17-2011, 12:06 AM
Thanks for the help Ataros, I'll start experimenting with that right away.

As for your code, what exactly isn't working? I can tell you right now that case 3 will never run because the Next(int, int) method returns an integer greater than or equal to the smaller number, but only less than the larger number. In other words, it will never return three, just one or two. It should look like this:

switch (RandomIncident.Next(1, 4))

See here: http://msdn.microsoft.com/en-us/library/2dx6wyd4.aspx

Ataros
05-17-2011, 07:24 AM
It should look like this:

switch (RandomIncident.Next(1, 4))

See here: http://msdn.microsoft.com/en-us/library/2dx6wyd4.aspx

Thanks, changed this. Should there be a space between the figures or does not matter?

I am trying to run this script with reduced delays for testing purposes and it does not load any submission or prints any message at all.
Please try to run it if you have time to see. Mission is attached.



// v.1_17_05. script by oreva, zaltys, small_bee

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{


// loading sub-missions
public override void OnTickGame()
{

if (Time.tickCounter() % 1800 == 1000) // 54000=30 min repeat. 12600=7 min delay.
{
// randomly selects 1 of several submissions

Random RandomIncident = new Random();

switch (RandomIncident.Next(1,4))
{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air01.mis");
GamePlay.gpHUDLogCenter("mission 1 objectives loaded...");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
});
break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_sea01.mis");
GamePlay.gpHUDLogCenter("mission 2 objectives loaded...");

double initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
});
break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air02.mis");
GamePlay.gpHUDLogCenter("mission 3 objectives loaded...");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
});
break;
}
}

///////////////////////

//loads small submissions w/o messages

if (Time.tickCounter() % 216000 == 108000) // 216000=120 min repeat. 108000=60 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_small01.mis");
}

if (Time.tickCounter() % 216000 == 215999) // 216000=120 min repeat. 215999=120 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_small02.mis");
}

}
////////////////////////////////////////////////////////////////////////////////////////////////////

// destroys aircraft abandoned by a player.
private bool isAiControlledPlane (AiAircraft aircraft)
{
if (aircraft == null)
{
return false;
}

Player [] players = GamePlay.gpRemotePlayers ();
foreach (Player p in players)
{
if (p != null && (p.Place () is AiAircraft) && (p.Place () as AiAircraft) == aircraft)
{
return false;
}
}

return true;
}

private void destroyPlane (AiAircraft aircraft) {
if (aircraft != null) {
aircraft.Destroy ();
}
}

private void explodeFuelTank (AiAircraft aircraft)
{
if (aircraft != null)
{
aircraft.hitNamed (part.NamedDamageTypes.FuelTank0Exploded);
}
}

private void destroyAiControlledPlane (AiAircraft aircraft) {
if (isAiControlledPlane (aircraft)) {
destroyPlane (aircraft);
}
}

private void damageAiControlledPlane (AiActor actor) {
if (actor == null || !(actor is AiAircraft)) {
return;
}

AiAircraft aircraft = (actor as AiAircraft);

if (!isAiControlledPlane (aircraft)) {
return;
}

if (aircraft == null) {
return;
}

aircraft.hitNamed (part.NamedDamageTypes.ControlsElevatorDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsAileronsDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsRudderDisabled);
aircraft.hitNamed (part.NamedDamageTypes.FuelPumpFailure);

int iNumOfEngines = (aircraft.Group() as AiAirGroup).aircraftEnginesNum();
for (int i = 0; i < iNumOfEngines; i++)
{
aircraft.hitNamed((part.NamedDamageTypes)Enum.Pars e(typeof(part.NamedDamageTypes), "Eng" + i.ToString() + "TotalFailure"));
}

/***Timeout (240, () =>
{explodeFuelTank (aircraft);}
);
* ***/

Timeout (300, () =>
{destroyPlane (aircraft);}
);
}

//////////////////////////////////////////

public override void OnPlaceLeave (Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave (player, actor, placeIndex);
Timeout (1, () =>
{damageAiControlledPlane (actor);}
);
}

public override void OnAircraftCrashLanded (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftCrashLanded (missionNumber, shortName, aircraft);
Timeout (300, () =>
{ destroyPlane(aircraft); }
);
}
public override void OnAircraftLanded (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftLanded(missionNumber, shortName, aircraft);
Timeout(300, () =>
{ destroyPlane(aircraft); }
);
}


//////////////////////////////////////////////////////////////////////////////////////////////////

//Listen to events of every mission
public override void Init(maddox.game.ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
MissionNumberListener = -1; //Listen to events of every mission
}

//////////////////////////////////////////////////////////////////////////////////////////////////

//Ground objects (except AA Guns) will die after 55 min when counted from their birth

public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);
//Ground objects (except AA Guns) will die after 55 min when counted from their birth
if (actor is AiGroundActor)
if ((actor as AiGroundActor).Type() != maddox.game.world.AiGroundActorType.AAGun)
Timeout(3300, () =>
{
if (actor != null)
{ (actor as AiGroundActor).Destroy(); }
}
);
}

/****
//Ground objects will die after 55 min when counted from their birth

public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);

//Ground objects will die after 55 min when counted from their birth
if (actor is AiGroundActor)
Timeout(3300, () =>
{
if (actor != null)
{ (actor as AiGroundActor).Destroy(); }
}
);
}
****/
}

TheEnlightenedFlorist
05-17-2011, 10:54 AM
Thanks, changed this. Should there be a space between the figures or does not matter?

I am trying to run this script with reduced delays for testing purposes and it does not load any submission or prints any message at all.
Please try to run it if you have time to see. Mission is attached.


The space does not matter. "Whitespace is ignored", as they say.

I'm not at my desktop so I can't run your mission, but I can't see why that code wouldn't work.

FG28_Kodiak
05-17-2011, 01:51 PM
@Ataros


switch (RandomIncident.Next(1,4))
{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air01.mis");
GamePlay.gpHUDLogCenter("mission 1 objectives loaded...");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
});
break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_sea01.mis");
GamePlay.gpHUDLogCenter("mission 2 objectives loaded...");

double initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
});
break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air02.mis");
GamePlay.gpHUDLogCenter("mission 3 objectives loaded...");

double initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
});
break;

Made the declaration double initTime = 0.0 before the switch case and only onetimes. Then your script should work.

It should look like:

public override void OnTickGame()
{

double initTime;

if (Time.tickCounter() % 1800 == 1000) // 54000=30 min repeat. 12600=7 min delay.
{
// randomly selects 1 of several submissions

Random RandomIncident = new Random();

switch (RandomIncident.Next(1,4))
{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air01.mis");
GamePlay.gpHUDLogCenter("mission 1 objectives loaded...");

initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
});
break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_sea01.mis");
GamePlay.gpHUDLogCenter("mission 2 objectives loaded...");

initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
});
break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air02.mis");
GamePlay.gpHUDLogCenter("mission 3 objectives loaded...");

initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
});
break;
}
}

Ataros
05-17-2011, 02:50 PM
Made the declaration double initTime = 0.0 before the switch case and only onetimes. Then your script should work.

It should look like:

Thank you very much!! Works great!

Would it be hard to exclude the last mission flown from random selection for the next round? As I am getting case #3 like 4 times in a row, than case 2 2 times. It can become boring for players. (I am planning to add more various missions to it in the future.)

We will test the script on Repka 2 for some time and then move it to Repka 1.

Welcome to our servers!

FG28_Kodiak
05-17-2011, 04:39 PM
It's possible to avoid repeating of last mission:


public class Mission : AMission
{
int LastMissionLoaded=0;

// loading sub-missions
public override void OnTickGame()
{

if (Time.tickCounter() % 1800 == 1000) // 54000=30 min repeat. 12600=7 min delay.
{
// randomly selects 1 of several submissions

Random RandomIncident = new Random();
int CurrentMissionSelected;

do
{
CurrentMissionSelected = RandomIncident.Next(1,4);
}
while (LastMissionLoaded == CurrentMissionSelected);

LastMissionLoaded = CurrentMissionSelected;

switch (CurrentMissionSelected)
{

bigchump
05-17-2011, 05:47 PM
I use C# everyday and I can't imagine using any of the .NET stuff to code a flight sim.

Ataros
05-17-2011, 07:04 PM
It's possible to avoid repeating of last mission:



Thank you so much again! I love this beautiful C# language. I had only some very limited acquaintance with Basiс long time ago (

Tested offline and now put up on Repka 2 for online test. Randomization will give us possibility to add more missions and overlap them randomly in time to make the airwar environment absolutely unpredictable.

I consider Repka server as a sandbox or a demo for the game-engine possibilities hoping that more people from community would be involved in mission-building and even in creation of online wars like ADW, Bellum or AFW as soon as they see how far the engine allows them to go compared to limited IL-2 COOPs or Dogfights. Unfortunately I do not have enough knowledge in C# myself.

Your help is highly appreciated.

Complete code as of today for Repka 2.
// v.1_17_05. script by FG28_Kodiak, ZaltysZ, oreva, small_bee

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{

int LastMissionLoaded = 0;

double initTime;

// loading sub-missions
public override void OnTickGame()
{
if (Time.tickCounter() % 45000 == 9000) // 45000=25 min repeat. 9000=5 min delay.
{
// randomly selects 1 of several submissions excluding the recent one

Random RandomIncident = new Random();
int CurrentMissionSelected;

do
{
CurrentMissionSelected = RandomIncident.Next(1, 4);
}
while (LastMissionLoaded == CurrentMissionSelected);

LastMissionLoaded = CurrentMissionSelected;

switch (CurrentMissionSelected)

{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air01.mis");
GamePlay.gpHUDLogCenter("mission objectives updated.");
//600
initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
});
break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_sea01.mis");
GamePlay.gpHUDLogCenter("mission objectives updated..");
//500
initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
});
break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_air02.mis");
GamePlay.gpHUDLogCenter("mission objectives updated...");
//600
initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
});
break;
}
}

///////////////////////

//loads small submissions w/o messages

if (Time.tickCounter() % 216000 == 108000) // 216000=120 min repeat. 108000=60 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_small01.mis");
}

if (Time.tickCounter() % 216000 == 215999) // 216000=120 min repeat. 215999=120 min delay.
{
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/BoF1/BoF1_small02.mis");
}

}
////////////////////////////////////////////////////////////////////////////////////////////////////

// destroys aircraft abandoned by a player.
private bool isAiControlledPlane (AiAircraft aircraft)
{
if (aircraft == null)
{
return false;
}

Player [] players = GamePlay.gpRemotePlayers ();
foreach (Player p in players)
{
if (p != null && (p.Place () is AiAircraft) && (p.Place () as AiAircraft) == aircraft)
{
return false;
}
}

return true;
}

private void destroyPlane (AiAircraft aircraft) {
if (aircraft != null) {
aircraft.Destroy ();
}
}

private void explodeFuelTank (AiAircraft aircraft)
{
if (aircraft != null)
{
aircraft.hitNamed (part.NamedDamageTypes.FuelTank0Exploded);
}
}

private void destroyAiControlledPlane (AiAircraft aircraft) {
if (isAiControlledPlane (aircraft)) {
destroyPlane (aircraft);
}
}

private void damageAiControlledPlane (AiActor actor) {
if (actor == null || !(actor is AiAircraft)) {
return;
}

AiAircraft aircraft = (actor as AiAircraft);

if (!isAiControlledPlane (aircraft)) {
return;
}

if (aircraft == null) {
return;
}

aircraft.hitNamed (part.NamedDamageTypes.ControlsElevatorDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsAileronsDisabled);
aircraft.hitNamed (part.NamedDamageTypes.ControlsRudderDisabled);
aircraft.hitNamed (part.NamedDamageTypes.FuelPumpFailure);

int iNumOfEngines = (aircraft.Group() as AiAirGroup).aircraftEnginesNum();
for (int i = 0; i < iNumOfEngines; i++)
{
aircraft.hitNamed((part.NamedDamageTypes)Enum.Pars e(typeof(part.NamedDamageTypes), "Eng" + i.ToString() + "TotalFailure"));
}

/***Timeout (240, () =>
{explodeFuelTank (aircraft);}
);
* ***/

Timeout (300, () =>
{destroyPlane (aircraft);}
);
}

//////////////////////////////////////////

public override void OnPlaceLeave (Player player, AiActor actor, int placeIndex)
{
base.OnPlaceLeave (player, actor, placeIndex);
Timeout (1, () =>
{damageAiControlledPlane (actor);}
);
}

public override void OnAircraftCrashLanded (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftCrashLanded (missionNumber, shortName, aircraft);
Timeout (300, () =>
{ destroyPlane(aircraft); }
);
}
public override void OnAircraftLanded (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftLanded(missionNumber, shortName, aircraft);
Timeout(300, () =>
{ destroyPlane(aircraft); }
);
}


//////////////////////////////////////////////////////////////////////////////////////////////////

//Listen to events of every mission
public override void Init(maddox.game.ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
MissionNumberListener = -1; //Listen to events of every mission
}

//////////////////////////////////////////////////////////////////////////////////////////////////

//Ground objects (except AA Guns) will die after 55 min when counted from their birth

public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);
//Ground objects (except AA Guns) will die after 55 min when counted from their birth
if (actor is AiGroundActor)
if ((actor as AiGroundActor).Type() != maddox.game.world.AiGroundActorType.AAGun)
Timeout(3300, () =>
{
if (actor != null)
{ (actor as AiGroundActor).Destroy(); }
}
);
}

/****
//Ground objects will die after 55 min when counted from their birth

public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);

//Ground objects will die after 55 min when counted from their birth
if (actor is AiGroundActor)
Timeout(3300, () =>
{
if (actor != null)
{ (actor as AiGroundActor).Destroy(); }
}
);
}
****/
}

C_G
05-17-2011, 08:01 PM
I can understand this thread just enough to get excited by the possibilities for online wars. Otherwise you guys might as well be doing voodoo for all I can tell :D
Great stuff!
I may one day even move myself to borrow a C# for Dummies!

TheEnlightenedFlorist
05-18-2011, 05:11 AM
Well, I've been messing around with changing spawn points for a while and I've got it mostly working except for one huge problem. The new spawn points don't update until I switch teams. For example, if I'm on red team and BirthPlace_1 switches to blue, I can still spawn there until I switch to blue and then back to red. I suspect it has something to do with the first mission still running after the second one is started, or the code isn't destroying BirthPlaces properly. It destroys "AiBirthPlaces". Do players use "AiBirthPlaces", or is that only for the AI. I saw no way to get a list of player "BirthPlaces".

Here's the code and the missions attached. If anybody sees any problems with it, please tell me. The spawn points and front lines will change sixty seconds after the mission starts.

using System;
using System.Collections;
using maddox.game;
using maddox.game.world;


public class Mission : AMission
{
// MissionMarker class. Equivalent to "Front Markers" in FMB
internal class MissionMarker
{
internal double x; //x coordinate
internal double y; //y coordinate
internal int army; //army that "owns" the marker. 1 is red. 2 is blue.

internal MissionMarker(double x, double y, int army) { this.x = x; this.y = y; this.army = army; }
}

//create mission markers
private MissionMarker[] MissionMarkers = new MissionMarker[]
{ new MissionMarker(12741, 16068, 1),
new MissionMarker(17372, 11070, 1),
new MissionMarker(23349, 23045, 2),
new MissionMarker(29122, 22331, 2)
};

//wheter or not markers have been initialized
bool markersNotInitialized = true;

public override void OnTickGame()
{
//if markers are not initialized, they won't show up on the player's map
if (markersNotInitialized)
{
//just setting the markers army equal to it's current army
for (int i = 0; i < MissionMarkers.Length; i++)
GamePlay.gpPostMissionLoad(CreateNewFrontLineMissi on(i, MissionMarkers[i].army));

markersNotInitialized = false;
}
}

internal ISectionFile CreateNewFrontLineMission(int markerNum, int newArmy)
{
//change the mission markers army to the new army
MissionMarkers[markerNum].army = newArmy;

//destroy all existing BirthPlaces/SpawnPoints, but only if the markers have been initialized
if (!markersNotInitialized)
{
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (bp != null)
bp.destroy();
}
}

//?? This must be the code that turns MissionMarkers into FrontMarkers
ISectionFile f = GamePlay.gpCreateSectionFile();
string sect;
string key;
string value;
sect = "FrontMarker";
for (int i = 0; i < MissionMarkers.Length; i++)
{
key = "FrontMarker" + i.ToString();
value = MissionMarkers[i].x.ToString(System.Globalization.CultureInfo.Invar iantCulture.NumberFormat) + " " + MissionMarkers[i].y.ToString(System.Globalization.CultureInfo.Invar iantCulture.NumberFormat) + " " + MissionMarkers[i].army.ToString();
f.add(sect, key, value);
}

return f;
}

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

//if the trigger that was called is the trigger that we're looking for
if (shortName.Equals("trigger1") && active)
{
GamePlay.gpHUDLogCenter("Trigger1");

//change the mission marker at 0 to blue army
GamePlay.gpPostMissionLoad(CreateNewFrontLineMissi on(0, 2));

//load new mission to change base ownership
GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/triggerTest/changeBase.mis");

}

//not sure what this does either. Do some action. From where?
AiAction action = GamePlay.gpGetAction(ActorName.Full(missionNumber, shortName));
if (action != null)
action.Do();
}
}

ZaltysZ
05-18-2011, 06:38 AM
I suspect it has something to do with the first mission still running after the second one is started, or the code isn't destroying BirthPlaces properly.

Mission loading is additive. This means that previous missions will still be running when you load the next one. This is why it is important to do clean up objects, if you don't need them anymore.

I suspect that BirthPlace has not much to do with creating planes, except as mean for UI making decision where it should show spawn points on map. Probably, we won't be able to handle this nicely until we get access to client UI (i.e. force refresh of UI).

It destroys "AiBirthPlaces". Do players use "AiBirthPlaces", or is that only for the AI. I saw no way to get a list of player "BirthPlaces".

I don't think "Ai" is artificial intelligence in this case. Players should use AiBirthPlaces.

Ataros
05-18-2011, 10:11 AM
Well, I've been messing around with changing spawn points for a while and I've got it mostly working except for one huge problem.

Do you mean this code does not destroy a birthplace for players who already use it?

foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (bp != null)
bp.destroy();
}

Probably there is a variable in code that stores player's recent bp. Can we access and change it with a script? Or onActorDead | placeExit (or what it is called) force a player to a default bp making him to select a desired bp again?


If we can change the frontline just by loading a new submission with moved frontline, why would we need the first part of the script defining the markers? I am a bit lost.

I came to a simple practical idea to prevent spawning after AF is lost:

1) set trigger starting final an attack on the airfield only when all ground units on it are killed
2) load tanks attacking the af
3) load submission containing new forntline and new bp based on trigger (tanks reached af)
4) spawn arty and tanks to patrol the af.
5) anyone from the side that lost the af spawning on it is killed by arty or tanks and learns a lesson to check the frontline position before spawning.

Not elegant but brutally practical. Did not have time to test it yet.

Anyway we have to find out how to solve the issue in a more user-friendly way ...or ...isn't it a brutal military sim?

klem
05-18-2011, 10:30 AM
Sample shows moving frontline and changing spawnpoints from red to blue and vice versa based on trigger (flyby above an airfield).

Can someone program a small 3 airfields battle based on it? Say a middle airfield becomes red or blue based on which tanks remain alive after taking the airfield. Then spawn new groups of tanks in say 20 minutes for a new round.

......................................

Hi Ataros

I'm slowly getting to grips with this :D

I have a script for generating sub-missions, messages etc., and want to start a later flight in the same mission to make a second later attack on a convoy in the same mission but I can't seem to set a later start time in FMB Object Viewer. There's no way to change it from the main mission start time of 12:00 (which seems a bit daft). Can I script a start time for a planned mission or perhaps a spawn, aircraft. waypoints etc? I tried to follow your moving front line and army changes but I can't see how to make it work for a new flight.

Ataros
05-18-2011, 10:44 AM
to start a later flight in the same mission to make a second later attack on a convoy in the same mission but I can't seem to set a later start time in FMB Object Viewer. There's no way to change it from the main mission start time of 12:00 (which seems a bit daft). Can I script a start time for a planned mission or perhaps a spawn, aircraft. waypoints etc?

I load delayed groups only with this submission loading script and do not know a better solution yet. http://forum.1cpublishing.eu/showpost.php?p=279416&postcount=95

You can try setting both a timedelay trigger and action (with the same name as trigger) in FMB in script menu but it did not work for me if I used other scripts with this mission.

Maybe you can set only an "action" in FMB in script menu and then run it with a script with action.Do as in this example but delayed in time. Just guessing here.
AiAction action = GamePlay.gpGetAction(ActorName.Full(missionNumber, shortName));
if (action != null)
action.Do();

It was a revelation for me that triggers (and probably actions) are stored in a mission file but not in a script. My bad :grin:

TheEnlightenedFlorist
05-18-2011, 11:12 AM
Do you mean this code does not destroy a birthplace for players who already use it?

Not exactly. It doesn't matter if I've ever spawned from that particular base or not. If I was on red team before the switch, I can still spawn that base after the switch. On the contrary, if I was on blue team before the switch, I can't spawn at the new base after the switch. Of course, this all only applies to me as the host of the server. I can't confirm that the same is true of a client connected to a server.

Now that I think about it, I don't know what happens if I choose my army after the switch. It probably appears correctly then.


If we can change the frontline just by loading a new submission with moved frontline, why would we need the first part of the script defining the markers? I am a bit lost.

We can't load a new frontline by loading a new submission because as far as I know, there is no way to delete front markers that were created in a mission file. Basically, because we create the front markers ourselves in code, it's easier to keep track of them and change them. If you open my mission in the FMB, you'll see that there are no mission markers in the .mis file. I add these in code as soon as the mission is loaded.

The reason that we can change spawn points by loading a new mission is because we can get all of the birthplaces and destroy them one by one, then let the ones in the new mission replace them.

We can also create spawn points in code too, but I wanted to do that with a new mission because it was simpler. I'll try doing this tomorrow and see if it fixes my problem.

Ataros
05-18-2011, 11:12 AM
//not sure what this does either. Do some action. From where?
AiAction action = GamePlay.gpGetAction(ActorName.Full(missionNumber, shortName));
if (action != null)
action.Do();

Attached is original mission. It is supposed to do as follows: on a flyby above an airfield a new enemy aircraft is spawn there and the af changes color to friendly.
Actions are listed in the mission file not the script. A surprise of the month for me! lol

TheEnlightenedFlorist
05-18-2011, 11:22 AM
The method I used to delay the start of a flight is as follows. There could very well (and probably is) be a better way.

1. Create a trigger that fires after the desired amount of time in the FMB.

2. Create an action that spawns the aircraft you want in the FMB.

3. Put code like this in the script file. Specifically in the OnTrigger() method.

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

//if the trigger that was called is the trigger that we're looking for
if (shortName.Equals("triggerName") && active)
{
AiAction action = GamePlay.gpGetAction("actionName"));
if (action != null)
action.Do();

}

"triggerName" and "actionName" are the names that you gave the trigger and action in the FMB.

TheEnlightenedFlorist
05-18-2011, 11:27 AM
Attached is original mission. It is supposed to do as follows: on a flyby above an airfield a new enemy aircraft is spawn there and the af changes color to friendly.
Actions are listed in the mission file not the script. A surprise of the month for me! lol

Thanks. I'll look at that tomorrow. It's 4:30 in the morning here! :grin:

Ataros
05-18-2011, 11:34 AM
We can't load a new frontline by loading a new submission because as far as I know, there is no way to delete front markers that were created in a mission file. Basically, because we create the front markers ourselves in code, it's easier to keep track of them and change them.

IIRC the devs mentioned that frontline is replaced automatically. I experimented with it 2 weeks ago and it moved, again IIRC. Try it. I thought I mentioned this in my previous posts. I can be mistaken of cause, will try to find my test missions later.

The reason that we can change spawn points by loading a new mission is because we can get all of the birthplaces and destroy them one by one, then let the ones in the new mission replace them.

Great idea! I thought that we have to delete only one bp and that gave me headache ))
Later I think it will be possible to script removal of 1-2 af only.

BTW the greatest solution would be to have bp side changed automatically if a submission loads new frontline leaving the bp to enemy! That would be an excellent piece of code! C# geniuses are called for help :)

We can also create spawn points in code too, but I wanted to do that with a new mission because it was simpler. I'll try doing this tomorrow and see if it fixes my problem.

I think placing everything in code gives more flexibility for a larger war/campaign where everything has to be automated (many battles for many cities and airfields). But adds complexity to coding. For a small mission with 5-8 submissions it would be easier to use FMB imho both for frontline and spawnpoints if possible.

It's 4:30 in the morning here! :grin::shock::shock::shock:

Where are you located?

Ataros
05-18-2011, 12:14 PM
Attached my test mission.

Frontline moves in 1800 ticks then tanks clear the captured AF from remaining enemy arty.

2 spawnpoints are placed at the same spot. Do not work as intended yet iirc.

TheEnlightenedFlorist
05-19-2011, 12:02 AM
IIRC the devs mentioned that frontline is replaced automatically. I experimented with it 2 weeks ago and it moved, again IIRC. Try it. I thought I mentioned this in my previous posts. I can be mistaken of cause, will try to find my test missions later.


Just tried it. You are correct. That makes things a little bit simpler.

BTW the greatest solution would be to have bp side changed automatically if a submission loads new frontline leaving the bp to enemy! That would be an excellent piece of code! C# geniuses are called for help

I saw a method that looks like it could tell me which side of the front a particular point is on so this is probably very possible. Just one more thing I need to experiment with. :grin:

Where are you located?

Salt Lake City, Utah, USA. Opposite side of the planet. :grin:

TheEnlightenedFlorist
05-19-2011, 12:35 AM
Attached is original mission. It is supposed to do as follows: on a flyby above an airfield a new enemy aircraft is spawn there and the af changes color to friendly.
Actions are listed in the mission file not the script. A surprise of the month for me! lol

Just tried this mission. It exhibits the same behavior as mine. :(

Edit:

This code will loop through all BirthPlaces and print a message to the screen if a BirthPlace is on the opposite side of the front line.

foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (GamePlay.gpFrontArmy(bp.Pos().x, bp.Pos().y) != bp.Army())
GamePlay.gpHUDLogCenter("Front and BirthPlace do not match!");
}

I'm having fun. :)

Ataros
05-19-2011, 08:13 AM
Salt Lake City, Utah, USA. Opposite side of the planet. :grin:

The planet becomes smaller and smaller )
Moscow, Russia here.


This code will loop through all BirthPlaces and print a message to the screen if a BirthPlace is on the opposite side of the front line.

So we can change bp army if we find such a contradiction. Just great!


Another idea I have:

If we can track a ground group position we can simplify ground mission creation to the following:

- submission loads group of tanks with waypoints
- script reads current frontmarker positions from the mission
- every minute the game tracks tanks position and moves a frontmarker to this pos with say 3 minutes delay. if all tanks are killed within this 3 minutes the marker is not moved.
- thus several groups of tanks will move the frontline in real time
- enemy tanks will do the same pushing it backward
- if tanks are dead a new group is spawn on trigger in some distance behind frontlines
- tank battle will go on forever if players do not kill tanks themselves
- after a frontline moves further than an enemy airfield the airfield turns to friendly in say 10 minutes (to allow recapture within this period) and then AAA and new tanks spawn near it to patrol it killing enemy players if spawned there (new submission loaded)


If the above is possible a mission maker would have to manually create say only 10-20 tank spawning missions to have a huge battle for 10-20 cities/airfields.

I think we have to place tanks waypoints manually at this point because there are no bridges at some rivers and tanks may get stuck in some villages/cities making it impossible for tanks to get from one waypoint to another if the waypoints are generated 100% automatically. But I am sure a solution to this problem can be found in the future.

Have you heard of mission generator for original IL-2 by Starshoy (http://www.google.com/webhp?hl=en#sclient=psy&hl=en&safe=off&site=webhp&source=hp&q=Starshoy%E2%80%99s+IL2+Campaign+Generator&aq=&aqi=&aql=&oq=&pbx=1&bav=on.2,or.r_gc.r_pw.&fp=9982c75a6c5bd35)? It automatically created online missions for IL-2 and was used in the majority of online war projects. I do not know if it is possible to convert it to C# to be used with CloD. At least some ideas can be borrowed for now I think.

And another one for offline I think http://www.lowengrin.com/news.php?90

Ataros
05-19-2011, 10:06 AM
Some help from the devs.

File here http://www.sukhoi.ru/forum/attachment.php?attachmentid=134622&d=1305794840

Link http://www.sukhoi.ru/forum/showthread.php?t=68774&p=1622955&viewfull=1#post1622955
Try, if you want to mission with the movement of the front line and the seizure of airfields:
CTF_cross_roundel.rar

There are four airfields on the map. They are your primary capture locations.
An aircraft is considered captured once the opposing sides armor enters its perimeter. The airfield perimeter is defended with artillery and flak. Once attacking armor is destroyed, a new group of armor will be spawned to continue the assault. Destroyed artillery and flak are not restored.
Once an airfield is captured, the front line will move and the airfield will change sides allowing the new owner to spawn there. Defending artillery will also spawn for the new owner, while the old owner will spawn an attacking armor group. Finally, capturing an airfield will spawn an AI-controlled aircraft group for the enemy, attacking both air and ground targets.
Capturing the most airfields is the overall objective for this mode.
The score system is simple. Capturing an airfield awards 10 points to the victorious side. Defending an airfield, that is, destroying an enemy armor group, awards 1 point.

To work correctly, the archive should be unpacked in the folder \ missions \ Multi \ Dogfight, whose mission should be run - \ missions \ Multi \ Dogfight \ CTF_cross_roundel.mis.
Podmissii are located in CTF_submissions.

MadTommy
05-19-2011, 10:30 AM
Great thread.. very helpful. Personally not really interested in any capture the flag kind of gameplay, just not my thing, but i am playing with the random mission selection.

To this i have a question.

How do i alter ths code to add a case? I could guesses and i'm sure i would get there through trial & error, but i'm sure someone here can show me ;)

Can someone add a case to the below script so i can see how it is done? Thanks!

// randomly selects 1 of several submissions excluding the recent one

Random RandomIncident = new Random();
int CurrentMissionSelected;

do
{
CurrentMissionSelected = RandomIncident.Next(1, 4);
}
while (LastMissionLoaded == CurrentMissionSelected);

LastMissionLoaded = CurrentMissionSelected;

switch (CurrentMissionSelected)

{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/15Sept1940/15Sept1940_R1.mis");
/*
GamePlay.gpHUDLogCenter("mission objectives updated.");
//600
initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
})*/
;

break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/15Sept1940/15Sept1940_R2.mis");
/*
GamePlay.gpHUDLogCenter("mission objectives updated..");
//500
initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
})*/
;

break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/15Sept1940/15Sept1940_R3.mis");
/*
GamePlay.gpHUDLogCenter("mission objectives updated...");
//600
initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
})*/
;

break;
}

(i'm not using the message system presently)

FG28_Kodiak
05-19-2011, 11:22 AM
it is easy



switch (CurrentMissionSelected)

{
case 1:
GamePlay.gpPostMissionLoad("missions/Multi/15Sept1940/15Sept1940_R1.mis");
/*
GamePlay.gpHUDLogCenter("mission objectives updated.");
//600
initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E3!");
});
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Help is needed at E3/D4!");
})*/
;

break;
case 2:
GamePlay.gpPostMissionLoad("missions/Multi/15Sept1940/15Sept1940_R2.mis");
/*
GamePlay.gpHUDLogCenter("mission objectives updated..");
//500
initTime = 0.0;
Timeout(initTime += 500, () =>
{
GamePlay.gpHUDLogCenter("Attention! Cover your shipping at C4!");
});

Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! Ships are under attack at C4!");
})*/
;

break;
case 3:
GamePlay.gpPostMissionLoad("missions/Multi/15Sept1940/15Sept1940_R3.mis");
/*
GamePlay.gpHUDLogCenter("mission objectives updated...");
//600
initTime = 0.0;
Timeout(initTime += 600, () =>
{
GamePlay.gpHUDLogCenter("Attention! Enemy activity is expected at E2!");
});
Timeout(initTime += 300, () =>
{
GamePlay.gpHUDLogCenter("Attention! All airgroups please proceed to E2/D3!");
})*/
;

break;

case 4:
//your code
break;

case 5:
//your code
break;


}

Ataros
05-19-2011, 11:54 AM
And in this line you put number of your cases+1

do
{
CurrentMissionSelected = RandomIncident.Next(1, 4);
}

4 for 3 cases
5 for 4 cases
etc

Ataros
05-19-2011, 11:55 AM
Some help from the devs. Sorry no time to translate now.

File here http://www.sukhoi.ru/forum/attachment.php?attachmentid=134622&d=1305794840

Text googletranslated.
Link http://www.sukhoi.ru/forum/showthread.php?t=68774&p=1622955&viewfull=1#post1622955

Runs on Repka #3 now. just have a look ))

Flashman
05-20-2011, 08:36 AM
Im having a bit of trouble with the command to load a new submission, and for it to load repeatedly. Here is the particular bit of script (pinched from an earlier Ataros script):

public override void OnTickGame()
{

if (Time.tickCounter() % 216000 == 27000)
{

GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/RaBv7/bomberred1_0.mis");
GamePlay.gpHUDLogCenter("Intel: British Bomber Formation, E13 at 4000 metres heading SE");
}



its this part that doesn't seem to work:
if (Time.tickCounter() % 216000 == 27000)

As i understand it this means that every 216000 tick (120 mins) the action should happen (spawns bombers and shows a message), but it is postponed for 27000 ticks (15 mins).

However when I run the mission what happens is after 15 minutes the bombers spawn and the message shows, but it never happens again. I have checked through the logs of various runs of this mission and it is always the same, it only runs once.

Am i doing something wrong, or am I mistunderstanding the settings? What I want to happen is this:

Server starts>at 15 mins-mission and message loads>2hrs after first mission loads (i.e. 2-15 server time)-mission reloads>2 hours later mission loads again... and so on as long as the main mission runs.

ANy help appreciated!

klem
05-20-2011, 08:44 AM
Well, I've been messing around with changing spawn points for a while ..........

Hi TheEnlightenedFlorist

I'm pretty new to this but I see in your code you are playing with Spawn points. I see you creating new Mission markers (front line markers) but only destroying BirthPlaces, not creating them. I want to create a new BirthPlace, a Stuka Unit and waypoints including a shipping attack to an existing mission.

All this stems from the fact that I can't seem to set a delayed start time for a second sortie in FMB, I can't even see a start time for it in the .mis file, just the overall mission start time.

Ataros has suggested loading a second FMB mission at the appropriate time but I don't see how I can tie that to an existing mission i.e. an existing Convoy route that receives a second attack later on. It seems I would have to show the convoy route in the new mission to include the Attack and that would duplicate the one in the first misson.

Do you know the code for creating a new BirthpPlace and a Sortie in an existing mission?

Thanks

TheEnlightenedFlorist
05-20-2011, 09:12 AM
Ataros has suggested loading a second FMB mission at the appropriate time but I don't see how I can tie that to an existing mission i.e. an existing Convoy route that receives a second attack later on. It seems I would have to show the convoy route in the new mission to include the Attack and that would duplicate the one in the first misson.

Hi klem, I think the best way to accomplish that would be to use a trigger, action, and a script. You would set a trigger to fire off after how ever many seconds you want, then create an airgroup to attack the convoy. In the airgroup's properties I believe you have to click a check box that says something like "script spawn only".

After that, create an action that will spawn the airgroup you just created. You could even make the action spawn the original airgroup if you want the second attack force to be exactly the same as the first. Just remember to uncheck "script spawn only" so that the airgroup spawns at the start of the mission like normal.

The script will look like this:

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public override void OnTrigger(int missionNumber, string shortName, bool active)
{
//call base classes OnTrigger method.
base.OnTrigger(missionNumber, shortName, active);

//if the trigger that was called is the trigger that we're looking for
if (shortName.Equals("attackConvoyDelay") && active)
{
AiAction action = GamePlay.gpGetAction("attackConvoy"));
if (action != null)
action.Do();

}
}

So if you put this code into the mission's script file, it will trigger your action whenever your trigger... triggers.

Note that I've named the trigger "attackConvoyDelay" and the action "attackConvoy". You can change them to whatever you want, just make sure they are the same in both the mission and the script.

I hope this helps. :grin:

klem
05-20-2011, 10:57 AM
Hi klem, I think the best way to accomplish that would be to use a trigger, action, and a script..................

Thanks! I think I even understand that. Simpler than I expected :)

I've set up the Trigger, Action and Script, just got to add the rest of the waypoints. I'll finish it tonight and try it out.

Cheers

SYN_Flashman
05-20-2011, 11:16 AM
I have just had a thought about scripts that start submissions.... can the submissions themselves have scripts? I think they can: when first testing the submission script i accidentally left a script in one of the submissions and it took ages for me to work out what the hell was going on!

Im at work so I can't test this but here is an idea to allow a mission to repeat every 2 hours or so. A few posts up I related how im having trouble doing this with the repeat part of the script but an alternative method might be this:

MAIN MISSION SCRIPT: Spawn bombergroup1 submission after 15 mins server time. NO repeats

15 mins main server time > bombergroup1 submission starts. It has a script itself which says: Spawn bombergroup 1 after 2 hours (i.e. it starts itself again)

2hr 15 min main server time> bombergroup1 submission starts again...

If this works correctly then so long as the server is running every two hours the bombergroup1 submission will spawn.

the bombergroup1 submission will last approx 90 mins plus however long it takes to despawn the landed/crashed planes (using Atatos et als script..which works well!). In other words it should finish and the aircraft despawn BEFORE it starts again.

Questions:

1) has anyone tried this? (I will later... damn I hate work!!)

2) when the submission starts, does it start its own tickcount from its creation, or does it 'read' the master mission tick count?

This is important because if it starts its own tickcount then the second time the bomber group spawns it will be 2 hours after the first. If however it uses the master mission tickcount it might start after 2 hours server time, but this is only 1 hr 45 after the first submission starts. This might mean that the next subsequent submission will not start at all.

3) Am i making any sense whatsoever?

PS I know that the tickcount isn't truly accurate with regards to time, but its close enough for my needs.

ZaltysZ
05-20-2011, 11:26 AM
1) has anyone tried this? (I will later... damn I hate work!!)


Yes.

2) when the submission starts, does it start its own tickcount from its creation, or does it 'read' the master mission tick count?

I am at work too, so not sure, but I think Time comes from Battle and not from Mission. Basically Battle has its own OnTickGame() which iterates through all missions and calls their OnTickGame().


I3) Am i making any sense whatsoever?

Depends on what you want to do. :)

Ataros
05-20-2011, 01:18 PM
its this part that doesn't seem to work:
if (Time.tickCounter() % 216000 == 27000)


Try reducing timings for testing purposes setting e.g. 3 min repeat 1 min delay and see what happens.

SYN_Flashman
05-20-2011, 01:31 PM
Try reducing timings for testing purposes setting e.g. 3 min repeat 1 min delay and see what happens.

Should have mentioned this earlier.... I did test it with lower fihures and it worked.

probably should have mentioned that...

Ataros
05-20-2011, 01:42 PM
Than it should work with bigger figures if you set the 1st figure greater than the 2nd in all cases. Try showing the complete code maybe someone finds a mistake in another part that influences this part. It helped me 2 times at least.

klem
05-21-2011, 08:38 AM
I am using the following script to send an immediate message to the player when he enters the cockpit (picked up earlier from this thread):


//SEND MESSAGE TO PLAYER WHEN THEY ENTER THE COCKPIT

public override void OnPlaceEnter(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceEnter(player, actor, placeIndex);
AiAircraft aircraft = actor as AiAircraft;

if (aircraft != null)
{
switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] {player},"Get Organised! Attack briefed targets. Get escorts where possible!"); }
else
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Get Organised! Watch for Radar Controller information, plan your tactics and meet the enemy! Provide escort for bombers where possible."); }
break;
case 2:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Get Organised! Attack briefed targets. Get escorts where possible!"); }
else
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Get Organised! Escort our Bombers or locate and engage enemy fighters in Frei Jagd"); }
break;
}
}
}


Will all players see that or only the new player? If all will see it and I only want the new player to see it do I fit in something like the following?......

if (aircraft.Name (). Equals (GamePlay.gpPlayer (). Place (). Name ()))

edit:
And sorry to be so dumb but I want to get a carriage return/line feed into the longer messages. I tried:
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Get Organised! Watch for Radar Controller information. \r\n Plan your tactics and meet the enemy! Provide escort for bombers where possible."); }
but it doesn't like it. Any ideas?

Ataros
05-21-2011, 11:34 AM
I think you should add Divebomber type to this script as stated here
http://forum.1cpublishing.eu/showpost.php?p=275321&postcount=63

Can not answer other questions.

klem
05-21-2011, 04:06 PM
I think you should add Divebomber type to this script as stated here
http://forum.1cpublishing.eu/showpost.php?p=275321&postcount=63

Can not answer other questions.

Thanks, I have done that :)

Flashman
05-23-2011, 07:12 PM
Im trying different things with these scripts by picking through other peoples. I have been trying various methods to ensure missions repeat, though so far they only repeat once for some reason.

Anyway instead of using the tick counter i have been looking at the init time settings people have been using. If i understand it correctly this allows a certaqin number of seconds to pass before carrying out whatever command you set.

This is a test script I am having problems with:

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public override void OnTickGame()
{
double initTime = 0.0;

Timeout(initTime += 60, () =>

{ GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/Channelv1/BM2/sb1d.mis");
GamePlay.gpHUDLogCenter("Intel: Stuka raid 1XXX inbound at Angels 13, heading W");
});

}
}


The purpose of the script is to run this mission (sb1d) 60 seconds after the script starts. It also has to only run the mission once. In this case the mission consists of a single AI stuka spawning, flying and then landing. Like I say, a simple test mission.

However when I test the mission, endless stukas spawn and blow each other up, in other words far more than 1!!!!

I have no idea about scripts, I have been picking bits out of other peoples, inserting them, hitting 'compile' and then testing the effects in game. I would be grateful if anyone can have a look and see where I am going wrong.

ZaltysZ
05-23-2011, 08:09 PM
Flashman,

OnTickGame() is called 30 times in second and every second, so your script 30 times in second schedules a mission loading, and repeats that endlessly. You are abusing your computer :)

Put this into Init(), not in OnTickGame().

Flashman
05-23-2011, 09:03 PM
Flashman,

OnTickGame() is called 30 times in second and every second, so your script 30 times in second schedules a mission loading, and repeats that endlessly. You are abusing your computer :)

Put this into Init(), not in OnTickGame().


Hi Zaltys,

Thanks for your help, however please excuse my ignorance. I have tried putting Init() in carious places but I can't work it out. ANy chance you can edit my previous file and put it in the correct place so I can see how it should work? I really have no idea what im doing......

Thanks

ZaltysZ
05-23-2011, 09:14 PM
using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public override void Init(maddox.game.ABattle battle, int missionNumber)
{
base.Init(battle,missionNumber);
Timeout(60, () =>

{ GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/Channelv1/BM2/sb1d.mis");
GamePlay.gpHUDLogCenter("Intel: Stuka raid 1XXX inbound at Angels 13, heading W");
});

}
}


If you forget base.Init(battle,missionNumber); in Init(), script won't work.

Flashman
05-23-2011, 09:22 PM
using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public override void Init(maddox.game.ABattle battle, int missionNumber)
{
base.Init(battle,missionNumber);
Timeout(60, () =>

{ GamePlay.gpPostMissionLoad("missions/Multi/Dogfight/Channelv1/BM2/sb1d.mis");
GamePlay.gpHUDLogCenter("Intel: Stuka raid 1XXX inbound at Angels 13, heading W");
});

}
}


If you forget base.Init(battle,missionNumber); in Init(), script won't work.

Thanks, that now works as I had hoped!

I had worked out I was missing the (battle, mission....) part but it still didn't work. it was the base.init part that made it function correctly, and I wouldn't have a clue about that.

Cheers!

klem
05-24-2011, 08:20 AM
This sample script made for fun disables player controls. Maybe someone can use it to disable AI controls for say 10 minutes before destroying AI

using System;
using maddox.game;
using maddox.game.world;

public class Mission: maddox.game.AMission
{
/ / Override the method that is invoked when some of the planes will take off ...
public override void OnAircraftTookOff (int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftTookOff (missionNumber, shortName, aircraft); / / call the base method (you never know ...)
if (GamePlay.gpPlayer ()! = null) / / check if we have a player.
{
if (GamePlay.gpPlayer (). Place ()! = null) / / check that the player is sitting somewhere and not hanging out on the rag.
{
if (aircraft.Name (). Equals (GamePlay.gpPlayer (). Place (). Name ())) / / if the plane took off - a player, then ...
{
aircraft.hitNamed (part.NamedDamageTypes.ControlsElevatorDisabled); / / ... disables elevators ...
aircraft.hitNamed (part.NamedDamageTypes.ControlsAileronsDisabled); / / ... aileron ...
aircraft.hitNamed (part.NamedDamageTypes.ControlsRudderDisabled); / / ... rudder.
/ / Have a nice flight!
}
}
}
}
}

More scripts here http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=ru&tl=en&u=http%3A%2F%2Fwww.sukhoi.ru%2Fforum%2Fshowthread. php%3Ft%3D68369

Can anyone see what's wrong with the following? I get the first test message at about +45 seconds while still in the hangar (engine on or engine off), repeated every 20 seconds (which is strange) until about mission start +3mins but I never get the second test message or the messages that follow in the "if" statement:


//SEND MESSAGE TO PLAYER WHEN THEY HAVE TAKEN OFF

public override void OnAircraftTookOff(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftTookOff(missionNumber, shortName, aircraft);

GamePlay.gpHUDLogCenter("Takeoff messages start."); //Test/debug Message

if (aircraft.Name() == GamePlay.gpPlayer().Place().Name()) // if the plane took off - a player, then ...
{

GamePlay.gpHUDLogCenter("Switch section reached"); //Test/debug Message

switch (aircraft.Army())
{
case 1:
if ((aircraft.Type() == AircraftType.Bomber) || (aircraft.Type() == AircraftType.DiveBomber)) // if Bomber or Divebomber
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Remember, Get Organised! Attack briefed targets!"); }
else
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Organise Escorts and protect Convoy moving from Beachy Head to the Thames Estuary!"); }
break;
case 2:
if ((aircraft.Type() == AircraftType.Bomber) || (aircraft.Type() == AircraftType.DiveBomber)) // if Bomber or Divebomber
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Remember, Get Organised and attack briefed Targets!"); }
else
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Remember, Get Organised and protect our bombers by Escort or Frei Jagd!"); }
break;
}

}

} //end public override void OnAircraftTookOff

Iku_es
05-24-2011, 12:08 PM
Hi,

I have never tried scripting for Clod, but as a C# programer, I'm going to make an educated guess:

Try changing this line:

if (aircraft.Name() == GamePlay.gpPlayer().Place().Name() )

for this one:

if ( aircraft.Name().Equals(GamePlay.gpPlayer().Place() .Name()) )

I'm not sure of this because I don't know the types of the objects involved in the comparison (strings?), but try it anyway.

(Check this for more info about why: C# Value Type vs Reference Type (http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx))

Also you should check that aircraft is not null, and that GamePlay.gpPlayer().Place() is not null, for security reasons in order to avoid NullReference exceptions.

ZaltysZ
05-24-2011, 02:18 PM
klem,

OnAircraftTookOff(() does not currently work for planes spawned at BirthPlaces. It should work for FMB planes with waypoints. I guess, you get first message showed because you have AI taking off.

ZaltysZ
05-24-2011, 02:26 PM
Instead of;

if (aircraft.Name() == GamePlay.gpPlayer().Place().Name())

try

if (aircraft == GamePlay.gpPlayer().Place())

By the way, GamePlay.gpPlayer() returns player of offline mission. This won't return a client player in MP, so if you are doing MP mission, this won't work.

klem
05-24-2011, 03:45 PM
Instead of;

if (aircraft.Name() == GamePlay.gpPlayer().Place().Name())

try

if (aircraft == GamePlay.gpPlayer().Place())

By the way, GamePlay.gpPlayer() returns player of offline mission. This won't return a client player in MP, so if you are doing MP mission, this won't work.

Thanks guys.

It was for MP and for a BirthPlace so a double fail :(

btw I had it report aircraft.Name() and GamePlay.gpPlayer().Place().Name() and they were the same string so 'If == ' should have worked ok.

klem
05-24-2011, 03:56 PM
Hi klem, I think the best way to accomplish that would be to use a trigger, action, and a script..........................

The script will look like this:

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission
{
public override void OnTrigger(int missionNumber, string shortName, bool active)
{
//call base classes OnTrigger method.
base.OnTrigger(missionNumber, shortName, active);

//if the trigger that was called is the trigger that we're looking for
if (shortName.Equals("attackConvoyDelay") && active)
{
AiAction action = GamePlay.gpGetAction("attackConvoy"));
if (action != null)
action.Do();

}
}

So if you put this code into the mission's script file, it will trigger your action whenever your trigger... triggers.

Note that I've named the trigger "attackConvoyDelay" and the action "attackConvoy". You can change them to whatever you want, just make sure they are the same in both the mission and the script.

I hope this helps. :grin:

Thought I'd report back on this, I eventually got the following to work:

public override void OnTrigger(int missionNumber, string shortName, bool active)

{
//call base classes OnTrigger method.
base.OnTrigger(missionNumber, shortName, active);
GamePlay.gpHUDLogCenter("shortname = " + shortName);
//if the trigger that was called is the trigger that we're looking for
if (shortName.Equals("AttackConvoy2Delay1"))
{
AiAction action = GamePlay.gpGetAction("AttackConvoy2_1") ;
if (action != null)
{ action.Do(); }
}


}

The '&& active' didn't work because:
1. It seems it should be + not &&
2. You can see I tested for the shortname and of course ("AttackConvoy2Delay1" + active) isn't equal to "AttackConvoy2Delay1". I don't know what 'active' comes back as but it would make the strings unequal.

Also, I put { } around the if(action != null) output as { action.Do(); } although that may not havebeen necessary.

Anyway it works !

Thanks for the help TheEnlightenedFlorist.

ZaltysZ
05-24-2011, 04:09 PM
"active" is boolean (logical true or false). You should check "active" to see if trigger is active.

if (shortName.Equals("attackConvoyDelay") && active)

means: if trigger name is "attackConvoyDelay" AND (&&) this trigger is active, then do something...

klem
05-24-2011, 04:54 PM
Aaahh! Got it. Thanks

Ataros
05-24-2011, 08:41 PM
This code will loop through all BirthPlaces and print a message to the screen if a BirthPlace is on the opposite side of the front line.

foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
{
if (GamePlay.gpFrontArmy(bp.Pos().x, bp.Pos().y) != bp.Army())
GamePlay.gpHUDLogCenter("Front and BirthPlace do not match!");
}

I'm having fun. :)

Getting back to moving frontline.
Does GamePlay.gpFrontArmy(bp.Pos().x, bp.Pos().y) work at any point of map or only at frontline/border?

Where can I see the complete list of such commands/functions like GamePlay.gpFrontArmy(bp.Pos().x, bp.Pos().y)? Should I add some game files to my project in Visual Studio? Till now I only opened separate .cs files with it.

TheEnlightenedFlorist
05-25-2011, 12:18 AM
Getting back to moving frontline.
Does GamePlay.gpFrontArmy(bp.Pos().x, bp.Pos().y) work at any point of map or only at frontline/border?

Where can I see the complete list of such commands/functions like GamePlay.gpFrontArmy(bp.Pos().x, bp.Pos().y)? Should I add some game files to my project in Visual Studio? Till now I only opened separate .cs files with it.

Yes, it should work for any point on the map.

Visual Studio will let you see all of the methods in roundabout way. Try this:

1. File >> New >> Project Type in a name and solution name at the bottom. Don't worry about what kind of project you create.

2. On the right side under "Solution Explorer", right click on "References", "Add Reference..."

3. Click on the "Browse" tab, navigate to "Steam/steamapps/common/il-2 sturmovik cliffs of dover/parts/core"

4. Go through each .dll file in that list and try to add it. Some will give you an error, just skip those.

After you've added all the .dll files, right click on the name of your project and do "Add Existing Item". Find one of your script files and add it. Now Visual Studio will show you all the possible methods as you're typing your code. You can also go to View >> Object Browser and have a look in there.

Important: When you import an existing item, Visual Studio makes a copy of the file so any changes you make won't be reflected in the original file, you'll have to copy the new one over it. If anybody knows how to change this, I'd be quite grateful.

Ataros
05-25-2011, 08:34 AM
Thanks a lot for detailed explanation.

BTW did you see the scripting in this mission from the devs http://forum.1cpublishing.eu/showpost.php?p=285348&postcount=133

I was reading it yesterday and it just blows my mind away. There are some great pieces everyone should use:

- airfield capture with removal of old arty
- generating triggers names with variables (string str = "changeArmy" + i.ToString() + "_" + (j).ToString();)
- generating waypoints for bombers to attack the most close ground target
- scoring system
etc.

I'll try to convert this mission to the Channel map when I have time. Probably will need a lot of help on C# ))

Devs confirmed that there is a bug not allowing to use captured airfields before switching sides. They are working on it.

TheEnlightenedFlorist
05-25-2011, 08:51 AM
Devs confirmed that there is a bug not allowing to use captured airfields before switching sides. They are working on it.

Cool. All of this would be in vain otherwise.:grin:

I've only glanced at that mission, but I've already learned a few things that will make things easier.

klem
05-25-2011, 08:57 AM
I'm having trouble giving messages to a particular side under OnTickGame because I don't know how to find out which side I am on (" 'aircraft' is not valid in this context"). Any ideas please?


public override void OnTickGame()

{

if (Time.tickCounter() % 115200 == 1980) // Testing, reduced to 1 min. 1980 = 60secs delay.
{
GamePlay.gpHUDLogCenter("1 minute Timetick message.");
//issue message after further 30 seconds (test)
double initTime = 0.0;
Timeout(initTime += 30, () =>
if (aircraft != null) //error the name aircraft does not exist in the current context
{
switch (aircraft.Army()) {
case 1:
{ GamePlay.gpHUDLogCenter("Red side message."); }
break;
case 2:
{ GamePlay.gpHUDLogCenter("Blue side message"); }
break;
}
});
}

}

hc_wolf
06-18-2011, 05:23 AM
I am trying to build a Falcon 4 type game where Germans advance towards cahnnel and English must drive them back.

SNAFU
06-21-2011, 01:48 PM
Hi all, and sorry Klem, I can´t help you...:(

I started now with my attempt to get familar with scripting and C#... :-P:rolleyes:

I read through this thread a several times and copied some samples of the outlined scripts.

The problem at hand now, is that I want to include a script in the submissions, which will be loaded into a main, basic-map. This submission script shall contain

Sec 1- the trigger messages,

Sec 2-the instruction messages for new players and players which just took off (WIP:Message shall only be shown, if trigger is not activated yet)

Sec 3- a count of trigger states, so very time a victory-trigger is set to true a counter raises the number for the side, which activated the trigger

Sec 4- clean up procedure at a certain time from begin of submission, removing all AI loaded into the basic map with the submission

Following questions appeared now at this stage:

(A) I already found out how to theoretically get the trigger messages running, still have to get it right, how to show the message only if the otherside (red/blue) has not activated their trigger yet.
Is thiss possible by something like this?

if (<Trigger Red won> == active || <Trigger Blue won> == acitve)
<message red won>

(B) How do I get rid off of all the AI loaded on the basic map, when the submission has done its job?

I wanted to try following script sample to remove the AI after an hour into the submission:

//////////////// Section 4: get rid off all AI loaded with submission

//mod-start by SNAFU -> ZIEL: nach 1h AI-Flieger entfernen

public override void OnTickGame()
{
double initTime;

if (Time.tickCounter() % 108000 == 10799) // 108000=1h
{
//mod-end by SNAFU

foreach (int army in GamePlay.gpArmies())
{
foreach (AiAirGroup group in GamePlay.gpAirGroups(army))
{
if (ActorName.MissionNumber(group.Name()).Equals(Miss ionNumber)) /// <- delete line to kill all
{
AiActor[] members = group.GetItems();
for (int i = members.Length - 1; i > -1; i--)
{
(members[i] as AiAircraft).Destroy();
}
}
}
foreach (AiGroundGroup group in GamePlay.gpGroundGroups(army))
{
if (ActorName.MissionNumber(group.Name()).Equals(Miss ionNumber)) /// <- delete line to kill all
{
AiActor[] members = group.GetItems();
for (int i = members.Length - 1; i > -1; i--)
{
(members[i] as AiGroundActor).Destroy();
}
}
}
}
}

(C) I now loaded a briefing message into the basic map, so every player joining and taking off, will be briefed into the actual ongoing submission. The basic map listens to all events introduced with the submissions, ok. But...

If the the submission is over, how does the main script notice the that the submissions states, messages (f.e. the briefing messages) are not valid anymore? Ist that the "puplic override" I see everywhere?

Here the template for the submission script and sorry for all the silly questions: :rolleyes:
using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;

public class Mission : AMission

//////////////////////////////////////////////////////////////////////////////////////
///////////Section 1: Trigger messages

///to copy into

/////////////////////////////////////////////////Section 3: Briefing for new players

///WIP if (<Trigger missions success red/blue> = false) /////WIP: Trigger Condition for Mission red/blue != true

{
public override void OnPlaceEnter(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceEnter(player, actor, placeIndex);
AiAircraft aircraft = actor as AiAircraft;

if (aircraft != null)
switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber) /////////////Nachricht für neue Spieler
{ GamePlay.gpHUDLogCenter(new Player[] {player},"Red Bomber Task"); } /////////roter Bomber
else { GamePlay.gpHUDLogCenter(new Player[] { player }, "Red Fighter Task"); } ///////////roter Jäger
break;
case 2:
if (aircraft.Type() == AircraftType.Bomber)
{ GamePlay.gpHUDLogCenter(new Player[] { player }, "Blue Bomber Task"); } ////////////blauer Bomber
else { GamePlay.gpHUDLogCenter(new Player[] { player }, "Blue Fighter Task"); } //////////// blauer Jäger
break;

}
}

public override void OnAircraftTookOff(int missionNumber, string shortName, AiAircraft aircraft)
{
base.OnAircraftTookOff(missionNumber, shortName, aircraft);

if (GamePlay.gpPlayer().Place() != aircraft)
return;

switch (aircraft.Army())
{
case 1:
if (aircraft.Type() == AircraftType.Bomber) /////////////Nachricht für neue Spieler
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Bomber Task"); } /////////roter Bomber
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Fighter Task"); } ///////////roter Jäger
break;
case 2:
if ((aircraft.Type() == AircraftType.Bomber) || (aircraft.Type() == AircraftType.DiveBomber))
{ GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Blue Bomber Task"); } ////////////blauer Bomber
else { GamePlay.gpHUDLogCenter(new Player[] { GamePlay.gpPlayer() }, "Red Bomber Task"); } //////////// blauer Jäger
break;

}
}

///WIP }

//////////////////////////////////////////////////////////////////////////////////////
//////////////// Section 3: Trigger count for overall win condition


// still no idea


//////////////////////////////////////////////////////////////////////////////////////
//////////////// Section 4: get rid off all AI loaded with submission

//mod-start by SNAFU -> ZIEL: nach 1h AI-Flieger entfernen

public override void OnTickGame()
{
double initTime;

if (Time.tickCounter() % 108000 == 10799) // 108000=1h
{
//mod-end by SNAFU

foreach (int army in GamePlay.gpArmies())
{
foreach (AiAirGroup group in GamePlay.gpAirGroups(army))
{
if (ActorName.MissionNumber(group.Name()).Equals(Miss ionNumber)) /// <- delete line to kill all
{
AiActor[] members = group.GetItems();
for (int i = members.Length - 1; i > -1; i--)
{
(members[i] as AiAircraft).Destroy();
}
}
}
foreach (AiGroundGroup group in GamePlay.gpGroundGroups(army))
{
if (ActorName.MissionNumber(group.Name()).Equals(Miss ionNumber)) /// <- delete line to kill all
{
AiActor[] members = group.GetItems();
for (int i = members.Length - 1; i > -1; i--)
{
(members[i] as AiGroundActor).Destroy();
}
}
}
}
}