Ил-2 Штурмовик: Битва за Британию. Скрипты. Скрипты для чайников. Часть 4 - Загрузка подмиссий

Материал из АвиаВики
Перейти к: навигация, поиск
Автор: FG28_Kodiak
Ссылка: Перейти (перевод Google)

Скачать оригиналы миссий:

Samples.zip

Скачать примеры с Sukhoi.ru:

Samples.zip

In the last lesson we have so busy trying to load a single SubMission to 30sec and monitors all the vehicles destroyed using the method OnActorDestroyed () to count. With this lesson we will randomly select and load each one of multiple submissions and. We are also building a small trap for the player, namely friendly vehicles. Is one of those destroyed by the player, the mission is a failure. The player will learn to look more closely and we will learn how the Army finds a membership Actors, then both of them what . In addition, we no longer count the total number of vehicles but only those of the Enemy.

So prepare for the first submissions, the primary mission remains unchanged. We open the SubMission from last time, change the vehicle and then saves the mission under another name. Here as an example once befriended our vehicle:

Sfdp4-1.jpg


Overall, I've created the next from last time, three other submissions, including one friend with a vehicle. The code for this example mission

using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;
public class Mission : AMission
{
   enum MissionCondition {Neutral, Success, Failure}    
   MissionCondition AktuelleMissionCondition = MissionCondition.Neutral;
   AiAircraft PlayerPlane;
   const int MaxAnzahlFeindlicheFahrzeuge = 10;
   int Zeitspanne = 4000; 
   int AnzahlFeindlicheFahrzeuge = 0;
   int ZerstoerteZiele = 0;    
   public override void OnBattleStarted()
   {
       base.OnBattleStarted();
       MissionNumberListener = -1;
       PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place();
   }    
   private void serverMessage(string msg)
   {
       GamePlay.gpLogServer (null, msg, new object [] {msg});
   }    
   public override void OnTickGame()
   {
       if (AktuelleMissionCondition == MissionCondition.Neutral)
       {    
           if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge))  //ca. alle 30sek die Karte laden
           {
               Zeitspanne += 1000;  // Bei jedem neuen Fahrzeug 30 sekunden zur GesamtZeit hinzu
               Random ZufaelligesFahrzeug = new Random();            
               switch (ZufaelligesFahrzeug.Next(1,5))
               {
                   case 1:
                       GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub1.mis");
                   break;
                   case 2:
                       GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub2.mis");
                   break;
                   case 3:
                       GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub3.mis");
                   break;
                   case 4:
                       GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub4.mis");
                   break;
                   default:
                       serverMessage("Mission nicht gefunden");
                   break;
               }
           }            
           if (Time.tickCounter() > Zeitspanne && AktuelleMissionCondition != MissionCondition.Success)     
           {
               GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlFeindlicheFahrzeuge.ToString() + " Fahrzeugen zerstört" );
               AktuelleMissionCondition = MissionCondition.Success;
           }
       }
   }    
   public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
   {
       base.OnActorCreated(missionNumber, shortName, actor);        
       if (actor is AiGroundActor)
       {
           GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});//Testmeldung            
           if (actor != null && actor.Army() == 1)   // 1 steht für Rote Seite 2 würde für Blaue Seite stehen
           {
               AnzahlFeindlicheFahrzeuge++;   // Wird nur gezählt wenn gegnerische Seite
           }          
           Timeout(75, () => {
               if (actor != null)
               { 
                   (actor as AiGroundActor).Destroy(); 
               }
           });
       }
   }    
   public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)
   {
       base.OnActorDead(missionNumber, shortName, actor, damages);        
       string KilledName;         
        KilledName = missionNumber.ToString()+ ":0_Chief";         
        if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name()))
        {             
            if (actor != null && actor.Army() == 2)   // 2 steht für Rote Seite 1 würde für Blaue Seite stehen
           {
               GamePlay.gpHUDLogCenter("Sie haben eines ihrer eigenen Fahrzeuge zerstört - <<<Mission fehlgeschlagen>>>" );
               AktuelleMissionCondition = MissionCondition.Failure;
           }
            ZerstoerteZiele++;
        }
   }
}


First, back in the mission globally valid between variables: mission condition enum {neutral, Success, Failure} mission condition condition = MissionCondition.Neutral current mission; As we once again have a termination condition, we use a lesson from the past already known enumeration

const int MaxAnzahlFeindlicheFahrzeuge = 10; Since this time we want to consider only the total number of enemy vehicles, a more meaningful variable name was chosen. int period = 4000; With this variable we consider that the last vehicle still needs some time to find their way back down. This variable is later raised in the code for each newly added SubMission to 1000 because we can not know how many vehicles have made friends at the end of the road. int count = 0 enemy vehicles; Here is the current number of enemy vehicles stored. The rest does not change the previous lesson.

OnBattleStarted () and server message (string msg) also remain unchanged.


public override void OnTickGame () { if (condition == current mission MissionCondition.Neutral) { if (Time.tickCounter ()% 1000 == 0 & & (number of enemy vehicles <MaxAnzahlFeindlicheFahrzeuge)) / / about 30sec load all the map { Time + = 1000; / / For each new vehicle 30 seconds added to the total time ZufaelligesFahrzeug random = new Random ();

switch (ZufaelligesFahrzeug.Next (1,5)) { case 1: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub1.mis"); break; case 2: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub2.mis"); break; case 3: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub3.mis"); break; case 4: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub4.mis"); break; default: server message ("Mission not found"); break; } }

if (Time.tickCounter ()> interval) { GamePlay.gpHUDLogCenter ("You" + "destroyed vehicles" ZerstoerteZiele.ToString () + "from" + AnzahlFeindlicheFahrzeuge.ToString () +); current mission condition = MissionCondition.Success; } } }

In contrast, if the method was OnTickGame ().

if (condition == MissionCondition.Neutral current mission) is first queried first whether the mission is still neutral status. So the mission was already a failure by a friendly target to be destroyed, no new submissions are more loaded.

if (Time.tickCounter ()% 1000 == 0 & & (number of enemy vehicles <MaxAnzahlFeindlicheFahrzeuge)) The query is executed when are passed about 30sec and has already spawned the number of enemy vehicles have not reached the maximum number. If the query is so true can be the first time around 1000 increased the amount of time + = 1000 as a one time = time + 1000 to write. The + = (just as there are -=, *= and / =) is shorthand for lazy writing (Ok not quite ). ZufaelligesFahrzeug random = new Random () we hereby create a new object with the name ZufaelligesFahrzeug from the Random class, this class will put us through. Net is available and provides us with pseudo-random numbers. Pseudo-states under the same conditions will always produce the same numbers. But for our purposes, ranging from this type of random numbers (where there is more information about this.).

switch (ZufaelligesFahrzeug.Next (1,5)) { case 1: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub1.mis"); break; case 2: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub2.mis"); break; case 3: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub3.mis"); break; case 4: GamePlay.gpPostMissionLoad ("missions \ \ music \ \ samples \ \ test submissions \ \ MissionNachladen6Sub4.mis"); break; default: server message ("Mission not found"); break; }

To determine what is loaded SubMission we use a switch .. case statement. It is checked whether the listed behind switch expression, either an integer or a string must be consistent with the stated case behind constants. This will in turn proceed therefore first checks whether the first case is true, then if the second, etc. You can in C # does not specify the area behind the case, things like first case .5: are not possible in C #. Makes a case for, all instructions are to break; executed. By default, you can define a branch which is executed in any case, if no case is true. But as we look at the switch -. Statement of our script to switch closer (ZufaelligesFahrzeug.Next (1,5)) With ZufaelligesFahrzeug.Next (..,..) we produce with the help of the Random object is an integer random number. The first value in parentheses indicates the minimum value, this is including the second value indicates the maximum value, this is exclusive, which means the maximum value is not generated by the random number generator, the minimum value on the other hand already. If you want to, for example, random numbers 1 to 10 would have. Next specify (1.11). In our example, we currently have 4 missions so we need the numbers from 1 to 4, so we need to define. Next (1.5). The random number was generated, compares the switch statement case all cases were found to the right and then loads the specified there SubMission. Had we accidentally. Next (1,6) as specified random number range, would be produced also from time to time the number 5, but there is no case scenario, so there would be the default active area and this gives us a brief message in the chat bar.

With if (Time.tickCounter ()> time), we check whether the time has already expired, if yes, we give a "winning message" and to evaluate current condition = MissionCondition.Success mission and the mission a success.

public override void OnActorCreated (int mission number, string ShortName, AiActor actor) { base.OnActorCreated (mission number, short name, actor);

if (actor is AiGroundActor) { GamePlay.gpLogServer (null, "Car: {0} n \.", New object [] {(actor as AiGroundActor) InternalTypeName ()});// test message

if (actor! = null & & actor.Army () == 1) / / 1 stands for Red to Blue page 2 would stand side { number of enemy vehicles + + / / If only counted when opposing side }

Timeout (75, () => { if (actor! = null) { (As actor AiGroundActor) Destroy ().; } }); } }

OnActorCreated were added to the method following instructions: GamePlay.gpLogServer (null, "Car: {0} s \", new object [] {(actor as AiGroundActor) InternalTypeName ()});. With the help of. InternalTypeName () can retrieve the output internal name of a game or AiGroundActors. The output looks like this:

Sfdp4-2.jpg


if (actor! = null & & actor.Army () == 1) is queried with the If statement whether the actor is present and whether it belongs to the opposing army. Army () returns an integer value for the Army, this one stands in the Red Cliffs of Dover on page 2 and blue for the page. So the actor belongs to the Red side of enemy vehicles will be increased by one.

public override void OnActorDead (int mission number, string ShortName, AiActor actor, System.Collections.Generic.List <DamagerScore> damages) { base.OnActorDead (mission number, short name, actor, damages);

Killed string name;

Killed missionNumber.ToString name = () + ": 0_Chief";

if ((damages.Count! = 0) & & (PlayerPlane.Name (). Equals (damages [0]. initiator.Actor.Name ())) & & KilledName.Equals (actor.Name ())) {

if (actor! = null & & actor.Army () == 2) / / 2 stands for Blue side { GamePlay.gpHUDLogCenter ("You have destroyed one of their own vehicles - <<<Mission failed>>>"); current mission condition = MissionCondition.Failure; }

ZerstoerteZiele + +; } }


Compared to the mission from the last lesson, this If statement was inserted: if (actor! = null & & actor.Army () == 2) / / 2 stands for Blue side { GamePlay.gpHUDLogCenter ("You have destroyed one of their own vehicles - <<<Mission failed>>>"); current mission condition = MissionCondition.Failure; } You from asking whether the actor is present and by actor.Army () == 2 if it belongs to the blue (ie our) side, this is the case, a message is displayed and updated mission set to failure condition, so the mission was a failure.

Sfdp4-3.jpg


When testing the above mission, is a relatively quick notice that some vehicles do not come to the second camouflage netting, before they disappear. These vehicles are too slow and therefore need more time until they reach their destination. One could, of course, now simply increase the time after which the vehicles Destroy () will be removed. But then there would be any traffic jams at the destination, which would be an easy target for the player.

To avoid this, you can also write a method that checks where an actor is straight and when this reaches a certain point, it is simply removed from the game. Such a method might look like this:

private void DestroyGroundActorAtPosition (double x, double y, double radius destroy) { Point3d DestroyPos; DestroyPos.x = x; DestroyPos.y = y; DestroyPos.z = 1;

for (int i = 0; i <count mission; i + +) { AiGroundActor curActor; for (int j = 0; j <10; j + +) { string name actor = i.ToString () + ": 0_Chief" + j.ToString (); curActor GamePlay.gpActorByName = (name actor) as AiGroundActor; if (curActor! = null) { if (curActor.Pos (). distance (ref DestroyPos) <destroy radius) { curActor.Destroy (); } }

} } }

Let's look closer. private void DestroyGroundActorAtPosition (double x, double y, double radius destroy) As transfer values ​​required by this self-written method, the X and Y coordinates of the target point and a radius around the point, so that you can specify the distance to the point at which an actor can be ground away. Point3d DestroyPos; DestroyPos is declared as a Point3D, Point3D is an internal data structure of Cliffs of Dover. Access to this structure, we get the result we maddox.GP the namespace by using maddox.GP; load at the beginning of our script. Point3d contains 3 double values, one each for x, y and z are, therefore, all the information a localization in a 3rd dimensional space is required. DestroyPos is with. X = x and. Y = y by the method of transfer values ​​and through. Z = 1 determined by us, the Z-value we define by 1 because we want to disappear leaving only ground targets. To ensure that all actors can be considered from all these missions you will be using the method OnMissionLoaded (), these count from the game called whenever a mission is reloaded. First, we still need to introduce an additional global variable int count = 1 mission, this mission will be increased in OnMissionLoaded count by one. public override void OnMissionLoaded (int mission number) { base.OnMissionLoaded (mission number); mission count + +; }

So back to DestroyGroundActorAtPosition is there with the help of a for - loop for (int i = 0; i <count mission; i + +) The mission number incremented inside the loop then declares a new name with AiGroundActor curActor. Then we need a second loop for (int j = 0; j <10; j + +), with the help of two loops, we set then all currently possible Actress name by string name actor = i.ToString () + ": 0_Chief" + j. ToString (); together, it is necessary to always "caught" the Actor is correct. With curActor GamePlay.gpActorByName = (name actor) as AiGroundActor, we then assign the variables with the help of curActor gpActorByName. With if (curActor! = Null) then we check whether this exists and if Actor (curActor.Pos (). Distance (ref DestroyPos) <destroy radius), we note whether the actor is already close to our point. With curActor.Pos () we get the current location of our Actors supplied as Point3D, from this position we can determine distance (ref DestroyPos) the distance to our previously specified point. distance is a method of Point3D and expected as the transfer value is a reference to the target point. Is the actor close enough to the target point with the Actor Destroy () will be removed.

DestroyGroundActorAtPosition we bring the end of the method under OnTick DestroyGroundActorAtPosition (16761.94, 14817.99, 10.0), the XY values ​​I've taken from the submission file, the value of 10.0 for the distance from the target point is sufficient. DestroyGroundActorAtPosition we will be expanding in a later lesson, so that we "clean up" after using this method for a whole range of Actors can.

Here's the whole script:

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


public class Mission : AMission { enum MissionCondition {Neutral, Success, Failure}

MissionCondition AktuelleMissionCondition = MissionCondition.Neutral; AiAircraft PlayerPlane; const int MaxAnzahlFeindlicheFahrzeuge = 10; int Zeitspanne = 4000; // Zeitspanne bis letztes Fahrzeug sicher verschwunden ist. int AnzahlFeindlicheFahrzeuge = 0; int ZerstoerteZiele = 0; int MissionsCount = 1;

public override void OnMissionLoaded(int missionNumber) { base.OnMissionLoaded(missionNumber); MissionsCount++; }

public override void OnBattleStarted() { base.OnBattleStarted(); MissionNumberListener = -1; PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place(); }

private void serverMessage(string msg) { GamePlay.gpLogServer (null, msg, new object [] {msg}); }

private void DestroyGroundActorAtPosition(double x, double y, double destroyRadius) { Point3d DestroyPos; DestroyPos.x = x; DestroyPos.y = y; DestroyPos.z = 1;

for (int i = 0; i < MissionsCount; i++) { AiGroundActor curActor; for (int j = 0; j < 10; j++) { string nameActor = i.ToString() + ":0_Chief" + j.ToString(); curActor = GamePlay.gpActorByName(nameActor) as AiGroundActor; if (curActor != null) { if (curActor.Pos().distance(ref DestroyPos) < destroyRadius) { curActor.Destroy(); } }

} } }

public override void OnTickGame() { if (AktuelleMissionCondition != MissionCondition.Failure && AktuelleMissionCondition != MissionCondition.Success) { if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge)) //ca. alle 30sek die Karte laden { Zeitspanne += 1000; // Bei jedem neuen Fahrzeug 30 sekunden zur GesamtZeit hinzu Random ZufaelligesFahrzeug = new Random();

switch (ZufaelligesFahrzeug.Next(1,5)) { case 1: GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub1.mis"); break; case 2: GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub2.mis"); break; case 3: GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub3.mis"); break; case 4: GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub4.mis"); break; default: serverMessage("Mission nicht gefunden"); break; } }

if (Time.tickCounter() > Zeitspanne && AktuelleMissionCondition != MissionCondition.Success) { GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlFeindlicheFahrzeuge.ToString() + " Fahrzeugen zerstört" ); AktuelleMissionCondition = MissionCondition.Success; } }

DestroyGroundActorAtPosition(16761.94, 14817.99, 10.0);

}

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

if (actor is AiGroundActor) { GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});//Testmeldung

if (actor != null && actor.Army() == 1) // 1 steht für Rote Seite 2 würde für Blaue Seite stehen { AnzahlFeindlicheFahrzeuge++; // Wird nur gezählt wenn gegnerische Seite } } }

public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages) { base.OnActorDead(missionNumber, shortName, actor, damages);

string KilledName;

KilledName = missionNumber.ToString()+ ":0_Chief";

if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name())) {

if (actor != null && actor.Army() == 2) // 2 steht für Blaue Seite { GamePlay.gpHUDLogCenter("Sie haben eines ihrer eigenen Fahrzeuge zerstört - <<<Mission fehlgeschlagen>>>" ); AktuelleMissionCondition = MissionCondition.Failure; }

ZerstoerteZiele++; } } }


Для установки миссий-примеров скопируйте их в папку:
..\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Single

Загрузка подмиссий (автор FG28_Kodiak)

Оригинальные темы см. на форуме sturmovik.de(перевод от Google):