PDA

View Full Version : Feature Request: Despawn AI aircraft Command


Flashman
05-19-2011, 11:29 AM
I've been struggling to get to grips with the FMB. Not so much the placement of objects (I made many IL2 missions) but its the scripting and related subjects. I am only interested in MP and producing maps for MP servers and at the moment I am finding it difficult to get the desired effects and there is one majoy stumbling block for me (and I think many others): Removing unwanted AI objects, especially flying AI aircraft from the mission/server.

I have a simple request: I want to be able to set a command to an AI object or group (be it aircraft, vehicles or ships.... anything AI) that will automatically despawn it. This could after a set time and/or when it reaches a set waypoint.

My preference would be that it would simply be one of the Options available in Properties>Waypoint>Action. So you would set the aircrafts route, target etc and when it reaches the final waypoint it simply despawns and is removed from the server.

I would also ask for an additional setting which sets the maximum time that the AI object/group is alive for. This would be useful is an object doesn't reach its final waypoint (it might be damaged or its route blocked or another propblem) or say if you want an aircraft group to loiter until a set time. I understand that its possible to remove ground object via a script but not flying AI aircraft.

I believe this would be a crucial and much welcomed addition to the FMB. Even with my limited knowledge of scripts (and in reality I borrow other people...thanks Ataros!) I can see the potential but at the moment the big handicap that I see is that we cannot reliably despawn AI objects once they are no longer useful.

If we can have a working, reliable, trusted method of despawning AI then the potential for multiday unpredictable missions (utilising the sub-mission system with scripts) is huge. It would mean you could have essentially a massive mission spread over a wide are with multiple objectives, but with clever mission making the actual number of AI etc in game would be smaller than the whole.

Ataros
05-19-2011, 11:51 AM
+1
I hope one day we have this integrated into FMB.

Another thing that we probably need is a sort of Mission Creation Toolkit including set of useful scripts for various purposes and then some add-ons that can be used to create a mission without knowledge of C#. Ideally a mission builder could just drop several script-files to his mission folder and add their names to a sort of mission.ini file and that is it. I remember how scary it was to open a C# file for the 1st time :grin:

Very often C# programmers and mission designers happen to be different people :grin: If programmers can deliver such a Toolkit mission builders would quicker produce more interesting missions.

Many people with knowledge of C# helped me a lot in creation of the script for Repka server. Thank you!

TheEnlightenedFlorist
05-19-2011, 10:07 PM
I have a simple request: I want to be able to set a command to an AI object or group (be it aircraft, vehicles or ships.... anything AI) that will automatically despawn it. This could after a set time and/or when it reaches a set waypoint.

I think I've got something pretty similar to this working. This whole thing is base on a method called OnActorTaskCompleted(). This is called whenever an actor completes it's well... task. I can't tell you exactly what an actor is, if it includes human players or just AI, and I can't tell you exactly what a task is.

I can tell you that this method is called when a Spitfire and a tank reach their final waypoints. :grin:

Anyway, here's the script. This is the code that I wrote. You won't have this in your script, although you might have some code in the OnActorTaskCompleted() method.

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

//destroy it if it's an aircraft
damageAiControlledPlane(actor);

//destroy it if it's a grond object
destroyGroundActor(actor);
}

private void destroyGroundActor(AiActor actor)
{

//loop through all of the ground groups from both armies
foreach (AiGroundGroup g in GamePlay.gpGroundGroups(1))
{
//if we find our actor in the ground group...
if (g.Name() == actor.Name())
{
//Destroy them! Destroy them all!
foreach (AiActor a in g.GetItems())
(a as AiGroundActor).Destroy();
}
}

foreach (AiGroundGroup g in GamePlay.gpGroundGroups(2))
{
//if we find our actor in the ground group...
if (g.Name() == actor.Name())
{
//Destroy them! Destroy them all!
foreach (AiActor a in g.GetItems())
(a as AiGroundActor).Destroy();
}
}
}

My code also depends on some of the code in this script.

http://forum.1cpublishing.eu/showpost.php?p=279080&postcount=92

You probably already have this because this is the code people are using to destroy aircraft that players abandon.

And finally, here's the script in it's entirety so you can see how it all fits together.

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


public class Mission : AMission
{

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

//destroy it if it's an aircraft
damageAiControlledPlane(actor);

//destroy it if it's a grond object
destroyGroundActor(actor);
}

private void destroyGroundActor(AiActor actor)
{

//loop through all of the ground groups from both armies
foreach (AiGroundGroup g in GamePlay.gpGroundGroups(1))
{
//if we find our actor in the ground group...
if (g.Name() == actor.Name())
{
//Destroy them! Destroy them all!
foreach (AiActor a in g.GetItems())
(a as AiGroundActor).Destroy();
}
}

foreach (AiGroundGroup g in GamePlay.gpGroundGroups(2))
{
//if we find our actor in the ground group...
if (g.Name() == actor.Name())
{
//Destroy them! Destroy them all!
foreach (AiActor a in g.GetItems())
(a as AiGroundActor).Destroy();
}
}
}

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 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.ControlsEl evatorDisabled);
aircraft.hitNamed(part.NamedDamageTypes.ControlsAi leronsDisabled);
aircraft.hitNamed(part.NamedDamageTypes.ControlsRu dderDisabled);
aircraft.hitNamed(part.NamedDamageTypes.FuelPumpFa ilure);
aircraft.hitNamed(part.NamedDamageTypes.Eng0TotalF ailure);
aircraft.hitNamed(part.NamedDamageTypes.Eng1TotalF ailure);


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

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

}


I hope this helps.

SEE
05-20-2011, 02:27 AM
+1 for the despawn waypoint.

I currently have a major headache with the script Trigger-Action Commands. I need an AI ac to land and for that ac to spawn another AI to take off. That results (or would) in a unwanted ground object doing nothing and showing up on the map if icons are enabled (despawn would be nice and simple for me). It should be possible to do this using the 'Group' and Passthorugh (an area on the runway) to act as a trigger but there appears to be a bug in that anything that lands automatically taxis to the same spawn point needed for the newly spawned ac - so it doesn't spawn! If you place an object on the runway and destroy the ac on the runway - the new ac spawns. You can use group and all the other commands with 'passthrough' to spawn Airgroups except a 'group' with a landing waypoint!

So, if there is a script please let me know or alternatively, can we also have a 're-arm' way point for AI ac to 'land - wait - and takeoff'!


Having spent hours on this problem I selected every available ac to land and they all appear to use the same algorithm for landing irrrespective of the FM for that ac........which may explain why some go 'tits up' on landing and others are OK! If you want to spawn a new AI - use the Anson....it can't land without going 'arse over tip' and your new AI spawns in its Hanger (and the Anson despawns!).....:grin:

Ataros
05-20-2011, 04:41 AM
I think you can destroy an AC onAircraftLanding or do some damage to it, e.g. kill engine preventing it taxiing to a parking slot.

ZaltysZ
05-20-2011, 05:05 AM
I think you can destroy an AC onAircraftLanding or do some damage to it, e.g. kill engine preventing it taxiing to a parking slot.

OnAircraftLanded() is called only after plane stops. In case of AI, plane stops only after it reaches parking spot.

Flashman
05-20-2011, 07:18 AM
+1 for the despawn waypoint.

I currently have a major headache with the script Trigger-Action Commands. I need an AI ac to land and for that ac to spawn another AI to take off. That results (or would) in a unwanted ground object doing nothing and showing up on the map if icons are enabled (despawn would be nice and simple for me). It should be possible to do this using the 'Group' and Passthorugh (an area on the runway) to act as a trigger but there appears to be a bug in that anything that lands automatically taxis to the same spawn point needed for the newly spawned ac - so it doesn't spawn! If you place an object on the runway and destroy the ac on the runway - the new ac spawns. You can use group and all the other commands with 'passthrough' to spawn Airgroups except a 'group' with a landing waypoint!

So, if there is a script please let me know or alternatively, can we also have a 're-arm' way point for AI ac to 'land - wait - and takeoff'!


Having spent hours on this problem I selected every available ac to land and they all appear to use the same algorithm for landing irrrespective of the FM for that ac........which may explain why some go 'tits up' on landing and others are OK! If you want to spawn a new AI - use the Anson....it can't land without going 'arse over tip' and your new AI spawns in its Hanger (and the Anson despawns!).....:grin:

I dont know if you are trying to use the ACTION and TRIGGER settings as well as adding a script, but so far I have found that having a script disables the trigger and action setting, i.e. they just don't work. For that reason I dont use them at the moment and also we need the despawn script for MP.

But if you are using both that might help you find your solution.

Flashman
05-20-2011, 07:20 AM
Hi EnlightenedFLorist,

I will have a look at that, though I have no knowledge of C++ and so far my scripts consist of hacking up other peoples and hoping they work!

Im really hoping 1C can include this Despawn idea as a setting in the FMB, it would be most helpful.

Anyhoo, I will have a look, do some swearing, and will see what I can come up with.

Cheers

TheEnlightenedFlorist
05-20-2011, 07:49 AM
so far I have found that having a script disables the trigger and action setting, i.e. they just don't work. For that reason I dont use them at the moment and also we need the despawn script for MP.

I think what might be happening is that when you add a script, the game expects you to deal with triggers and actions in the script. They work fine with my scripts. I actually don't know how to use triggers or actions without a script. :grin:

If you need help writing a script, you can post it on the forum and I'm sure there'll be plenty of people willing to help you out.

Also, scripts are written in C#, not C++. C# is very much like Java and way easier to work with than C++. I don't want you to go learning C++ when you should be learning C#. :)

SYN_Flashman
05-20-2011, 10:22 AM
Also, scripts are written in C#, not C++. C# is very much like Java and way easier to work with than C++. I don't want you to go learning C++ when you should be learning C#. :)

Now worries on that score, I wasn't planning on learning either, my brain isn't big enough! I learn just enough to make it appear i know what im doing when in fact I haven't a bloody clue. Mcuh like the rest of my life really....

I will have a look at using triggers and actions within the script itself as some are quite useful. I did have a mission where if one plane was shot down another would spawn... lots of potential with that one.

There is a lot to learn, but equally there is a lot we can do that is really interesting.

I will post up my next daft script and see what people think later on when im home. Cheers!

Ataros
05-20-2011, 12:01 PM
If you want to destroy aircraft loaded by submissions do not forget to include
//////////////////////////////////////////////////////////////////////////////////////////////////

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

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

I made that mistake. Thanks to ZaltysZ for correcting it in my script!

SYN_Flashman
05-20-2011, 12:22 PM
If you want to destroy aircraft loaded by submissions do not forget to include
//////////////////////////////////////////////////////////////////////////////////////////////////

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

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

I made that mistake. Thanks to ZaltysZ for correcting it in my script!

How do I use this piece of script, do I just copy and paste it into mt script or do I need to make any changes?

Ataros
05-20-2011, 12:27 PM
@ Flashman
Just copy and past anywhere you like. You can always check out my recent script in Online Missions go here thread.


@all
It seems like this script I use does not destroy ships loaded by a submission. Other ground units are destroyed as intended. What can be wrong? IIRC ships belong to AiGroundActor

//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(); }
}
);
}


Complete code here http://forum.1cpublishing.eu/showpost.php?p=283765&postcount=41

335th_GRAthos
05-20-2011, 09:09 PM
I think you got lucky guys....
(I can only think because I do not undestand the language you write in this thread... :-) )

From the Hotfix:

MULTIPLAYER
Improved server and client stability and performance;
Improved statistics;
Improved user interface;
Made parked planes disappear after a certain period of time so as not to clutter the airfields;
Fixed phantom crewmembers occasionally appearing in place of dropped planes;
Made sure airborne planes are created with sufficient airspeed in online games (born speed now tied to the plane's top speed);
Conversion settings should properly synchronize between all players;
Fixed the weapon selection grid in online games requiring an extra click to save;
Made sure all players see the same time of day in an online server.

Ataros
05-22-2011, 10:07 AM
It seems like this script I use does not destroy ships loaded by a submission. Other ground units are destroyed as intended. What can be wrong? IIRC ships belong to AiGroundActor

//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(); }
}
);
}


Complete code here http://forum.1cpublishing.eu/showpost.php?p=283765&postcount=41

Confirmed, the script does not destroy ships. What can be the reason?
This is what happens in 3-4 hours after starting a mission.
https://lh4.googleusercontent.com/_SFUSvzV-UZg/TdjfUKArvZI/AAAAAAAABA8/VtHaur3Ztvk/2011-05-21_00016.jpg

ZaltysZ
05-22-2011, 10:52 AM
Confirmed, the script does not destroy ships. What can be the reason?

Somehow game does not see ships as AiGroundActor. Ask naryv about this.

Ataros
05-25-2011, 10:44 AM
Looks like the script we are running on Repka and Syndicate is not 100% compatible with multicrew aircraft.

if you change positions in multicrew planes ONLINE (and only ONLINE !) the game sets the engine temperature to ZERO.
In the Blenheim for example, the causes the engines to stop.....

Can someone help to change the code in order not to damage engines and controls if a player remains inside an aircraft and only changes his position to gunner or navigator?

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

// 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); }
);
}


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

ZaltysZ
05-25-2011, 11:13 AM
Ataros,

are there problems with Ju88 ar He111? I ask because it might be not a despawn problem, but separate bug. If I recall correctly there was (or still is) a problem with Br.20: engines cout out as player switches pilot positions (there are 2 piliots in Br.20).

Ataros
05-25-2011, 11:39 AM
I did not try it myself yet. Will be able to test only tomorrow.

People report all bombers as far as I understand. This guy flies red side only i.e. Blenheims http://www.sukhoi.ru/forum/showthread.php?t=68697&p=1625736&viewfull=1#post1625736

Flashman
05-25-2011, 04:46 PM
Ataros,

are there problems with Ju88 ar He111? I ask because it might be not a despawn problem, but separate bug. If I recall correctly there was (or still is) a problem with Br.20: engines cout out as player switches pilot positions (there are 2 piliots in Br.20).

There are problems with all muticrew aircraft if the player moves position. Would be nice if it could be fixed.

Ataros
05-25-2011, 06:09 PM
This code checks if plane is empty completely I guess. But this script worked only from a client PC used as server and did not work on a dedi server at least before the latest beta patch. That is why it was replaced with currently used script which works on dedi server.

We have to find out how to integrate this
if ((i.Place() as AiAircraft) == (actor as AiAircraft))
{
PlaneIsEmpty = false;

into currently working script shown above in my previous message.
// 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();
});
}
}