Код:
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using maddox.GP;
using System.Collections.Generic;
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 List <MissionMarker> MissionMarkers = new List<MissionMarker> ();
string BPMaxPlanesAllowed = "3"; // количество макс. возможно создаваемых самолётов на спаунточке
string BPSpawnParked = "1"; // рожать ли самолёты на спауне запаркованными 1 - да, 0 - нет
int MissionsCount = 1; // счётчик миссий - для вычисления полных имён стат. объектов, например артиллерии
int NextMissionNum = 2; // флажок номера следующей миссии - для рефреша спаун точек, после смены линии фронта
int ScoreRed = 0; // "счёт"
int ScoreBlue = 0;
private string[] RedPlanesSet = new string[] // описание наборов самолётов на спаунточках разных стран
{ "Aircraft.SpitfireMkIIa",
"Aircraft.SpitfireMkI",
"Aircraft.BlenheimMkIV",
"Aircraft.SpitfireMkIa",
"Aircraft.DH82A",
"Aircraft.HurricaneMkI_dH5-20",
"Aircraft.HurricaneMkI"
};
private string[] BluePlanesSet = new string[]
{ "Aircraft.Bf-110C-7",
"Aircraft.Bf-110C-4",
"Aircraft.Bf-109E-3B",
"Aircraft.Ju-88A-1",
"Aircraft.G50",
"Aircraft.He-111P-2",
"Aircraft.He-111H-2",
"Aircraft.Bf-109E-3",
"Aircraft.BR-20M",
"Aircraft.Ju-87B-2"
};
public ISectionFile triggersFile ; // объявление файла для генерации миссии с триггерами смены линии фронта
public override void Init(ABattle battle, int missionNumber)
{
base.Init(battle, missionNumber);
ISectionFile missFile = GamePlay.gpLoadSectionFile("missions\\Multi\\Dogfight\\xxxxx.mis"); // загружаем в missFile основную миссию, для того, чтобы найти в ней маркеры фронта
triggersFile = GamePlay.gpCreateSectionFile(); //заодно создаём файл для генерации миссии с триггерами
string section, key, value;
string sectionTr, keyTr, valueTr;
section = "FrontMarker";
sectionTr = "Trigger";
int n = missFile.lines(section); // определяем, сколько маркеров фронта в миссии
for (int i = 0 ; i < n; i++)
{ // в этом цикле пробегаем по всем маркерам
key = "FrontMarker"+i.ToString();
if (missFile.exist(section,key)) // проверяем, что маркер есть
{
value = missFile.get(section, key);
string[] strs = value.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); // и парсим строку с маркером, берём его координаты и страну
if (strs.Length == 3)
{
double x; double.TryParse( strs[0], out x);
double y; double.TryParse( strs[1], out y);
int army; int.TryParse( strs[2], out army);
MissionMarker mMarker = new MissionMarker(x,y,army);
MissionMarkers.Add(mMarker); // добавляем в список маркеров MissionMarkers проверенный маркер
keyTr = "changeArmy" + i.ToString()+"_1"; // попутно на маркере делаем два триггера - для каждой стороны
valueTr = " TPassThrough 3 1 " + strs[0] + " " + strs[1] + " 500"; // "TPassThrough 3" - триггер сработает при заезде в него наземки, "1" красной, strs[0] + " " + strs[1] координаты, "500"- радиус триггера
triggersFile.add(sectionTr, keyTr, valueTr); // сохраняем триггер в файле триггерной миссии
keyTr = "changeArmy" + i.ToString() + "_2"; // то же самое для синей стороны
valueTr = " TPassThrough 3 2 " + strs[0] + " " + strs[1] + " 500";
triggersFile.add(sectionTr, keyTr, valueTr); // сохраняем триггер в файле триггерной миссии
}
}
}
}
public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1; // ставим MissionNumberListener = -1 , чтобы основная миссия "слышала" все триггеры и события в битве
GamePlay.gpPostMissionLoad(triggersFile); // подгружаем миссию с триггерами созданую раньше, в Init
RefreshBirthPlaces(); // и запускаем рефреш спаунов - чтобы они рассчитались
}
private void RefreshBirthPlaces()
{
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces()) // сначала - очистим существующие спауны
{
if (bp != null)
bp.destroy();
}
ISectionFile f = GamePlay.gpCreateSectionFile(); // создаём файл миссии в котором переопределим спауны в соответствии с линиями фронта
string sect;
string key;
string value;
for (int i = 0; i < GamePlay.gpAirports().Length; i++) // сделаем спауны на всех аэродромах карты
{
Point3d airpPos = GamePlay.gpAirports()[i].Pos(); // координаты аэродрома
int armyAtPos = GamePlay.gpFrontArmy(airpPos.x, airpPos.y); // текущая армия в точке с аэродромом
sect = "BirthPlace";
key = "BirthPlace_" + i.ToString(); // дальше заполняем инфо для спаунов
string Country = ".";
if (armyAtPos == 1) Country = "gb";
if (armyAtPos == 2) Country = "de";
value = " " + armyAtPos.ToString() + " " + ((int)airpPos.x).ToString() + " " + ((int)airpPos.y).ToString() + " 0 " + BPMaxPlanesAllowed + " " + BPSpawnParked + " 0 " + Country + " . .";
f.add(sect, key, value);
sect = "BirthPlace" + i.ToString(); // и для каждого заполняем списком разрешённых самолётов
string[] PlaneSet = new string[0];
if (armyAtPos == 1)
PlaneSet = RedPlanesSet;
if (armyAtPos == 2)
PlaneSet = BluePlanesSet;
if (PlaneSet.Length > 0)
for (int j = 0; j < PlaneSet.Length; j++)
{
key = PlaneSet[j];
value = "";
f.add(sect, key, value);
}
}
GamePlay.gpPostMissionLoad(f); // загружаем новые спауны
}
private void DestroyEnemyAtCaptured(int markerNum, int army)
{ // если надо уничтожить всех врагов на захваченном маркере - уничтожаем в этой процедуре
Point3d AirportPos;
AirportPos.x = MissionMarkers[markerNum].x;
AirportPos.y = MissionMarkers[markerNum].y;
AirportPos.z = 1;
foreach (AiGroundGroup gg in GamePlay.gpGroundGroups(army))
{
if (gg != null)
if (gg.Pos().distance(ref AirportPos) < 2000) // 2000 это расстояние от маркера на котором уничтожим врагов
{
string triggerName = gg.Name().Substring(0,gg.Name().IndexOf(":"))+":"+markerNum.ToString()+"_" + army .ToString()+ "_attack";
AiTrigger trigger = GamePlay.gpGetTrigger(triggerName);
if (trigger != null) trigger.Enable = false;
foreach (AiActor ggActor in gg.GetItems())
{ if ((ggActor as AiGroundActor) != null)
(ggActor as AiGroundActor).Destroy();
}
}
}
for (int i = 0; i < MissionsCount; i++)
{
AiGroundActor curActor;
for (int j = 0; j < 10; j++)
{
string nameActor = i.ToString() + ":Static" + j.ToString();
curActor = GamePlay.gpActorByName(nameActor) as AiGroundActor;
if (curActor != null)
{
if ( (curActor.Army() == army) &&
(curActor.Pos().distance(ref AirportPos) < 2000) &&
((curActor.Type() == AiGroundActorType.AAGun)||(curActor.Type() == AiGroundActorType.Artillery) )
)
{
curActor.Destroy();
}
}
}
}
}
internal ISectionFile CreateNewFrontLineMission(int markerNum, int newArmy) // создаём новый файл миссии с фронтмаркерами
{
DestroyEnemyAtCaptured(markerNum, MissionMarkers[markerNum].army); // если надо - уничтожаем врагов
MissionMarkers[markerNum].army = newArmy; // в списке маркеров задаём новую армию на захваченном маркере
ISectionFile f = GamePlay.gpCreateSectionFile();
string sect;
string key;
string value;
for (int i = 0; i < MissionMarkers.Capacity; i++) // и для всего списка маркеров пробегаем и записываем в файл их координаты и армии
{
sect = "FrontMarker";
key = "FrontMarker" + i.ToString();
value = MissionMarkers[i].x.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + MissionMarkers[i].y.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + " " + MissionMarkers[i].army.ToString();
f.add(sect, key, value);
}
return f;
}
public override void OnMissionLoaded(int missionNumber)
{
base.OnMissionLoaded(missionNumber);
MissionsCount++; // счётчик миссий обновляем
if (missionNumber == NextMissionNum) // проверяем флажок номера следующей миссии - для рефреша спаун точек, после смены линии фронта
RefreshBirthPlaces(); // и обновляем спауны если надо
}
public override void OnTrigger(int missionNumber, string shortName, bool active) // обрабатываем триггеры сработавшие
{
base.OnTrigger(missionNumber, shortName, active);
int n = MissionMarkers.Capacity; //пробегаем по списку маркеров, чтобы выяснить - не сработал ли наш триггер на смену линии фронта
for (int i = 0; i < n; i++)
{
for (int j = 1; j < 3; j++)
{
string str = "changeArmy" + i.ToString() + "_" + (j).ToString();
if (str.Equals(shortName)) // если сработал - тогда обрабатываем его - счёт обновляем, пишем что фрмия сменилась
{
if (MissionMarkers[i].army != j)
{
string armyOwner;
if (j == 1)
{
armyOwner = " Red army";
ScoreRed += 10;
}
else
{
armyOwner = " Blue army";
ScoreBlue += 10;
}
GamePlay.gpHUDLogCenter("Front turn to " + armyOwner + " at sector " + GamePlay.gpSectorName(MissionMarkers[i].x, MissionMarkers[i].y).ToString() + "; Red " + ScoreRed.ToString() + ":" + ScoreBlue.ToString() + " Blue");
NextMissionNum = GamePlay.gpNextMissionNumber(); // ставим флажок номера следующей миссии - чтобы после загрузки новых линий фронта пересчитались спауны
GamePlay.gpPostMissionLoad(CreateNewFrontLineMission(i, j)); // грузим миссию с обновлёнными маркерами ЛФ
// ну и можно как в предыдущей версии загрузить подмиссию на изменённый маркер, у меня это были подмиссии с защищающимися артами вида "x_y_defend.mis", где x - номер маркера, y - защищающаяся страна :
GamePlay.gpPostMissionLoad("missions\\Multi\\Dogfight\\CTF_submissions\\" + i.ToString() + "_" + (j).ToString() + "_defend.mis");
}
break;
}
// ну и заодно проверяем не уничтожили ли атакующих из подмиссий в каждой такой подмисси был триггер вида "x_y_attack" срабатывавший на уничтожение атакующей группы
str = i.ToString() + "_" + (j).ToString() + "_attack";
string addStr = " ground group eliminated at sector " + GamePlay.gpSectorName(MissionMarkers[i].x, MissionMarkers[i].y).ToString();
if (str.Equals(shortName)) // соответственно если сработал такой триггер, обрабатываем его , счёт меняем, пишем что группу уничтожили и запускаем ещё одну атакующую миссию
{
if (j == 2)
{
ScoreRed++;
addStr = "Blue" + addStr;
}
else
{
ScoreBlue++;
addStr = "Red" + addStr;
}
GamePlay.gpHUDLogCenter(addStr + ",and the score is Red " + ScoreRed.ToString() + ":" + ScoreBlue.ToString() + " Blue");
GamePlay.gpPostMissionLoad("missions\\Multi\\Dogfight\\CTF_submissions\\" + str + ".mis");
break;
}
// если логика битвы другая , тогда этот блок с проверкой убираем
}
}
}
}