Ил-2 Штурмовик: Битва за Британию. Скрипты. FAQ — различия между версиями

Материал из АвиаВики
Перейти к: навигация, поиск
(Использование класса List(Of T) вместо массивов)
(Как удалить все юниты подмиссии)
Строка 244: Строка 244:
  
 
== Как удалить все юниты подмиссии ==
 
== Как удалить все юниты подмиссии ==
::'''Вопрос:''' ''1.   Есть загруженная подмиссия с неизвестным номером. Как удалить все юниты именно этой подмиссии не перебирая в циклах всю наземку? Или может быть просто можно подмиссию выгрузить?''
+
::'''Вопрос:''' ''  Есть загруженная подмиссия с неизвестным номером. Как удалить все юниты именно этой подмиссии не перебирая в циклах всю наземку? Или может быть просто можно подмиссию выгрузить?''
 
::'''Ответ:'''
 
::'''Ответ:'''
::1. Никак.
+
::  Никак.
 
Что бы миссия не была неизвестной, надо перед ее загрузкой запомнить след. номер (NextMissionNumber или как то так).
 
Что бы миссия не была неизвестной, надо перед ее загрузкой запомнить след. номер (NextMissionNumber или как то так).
 
Частичное решение состоит в переборе наземных и воздушных групп для всех представленных армий и сверке запомненного номера миссии с номером, заключенном в полном имени юнита (формат примерно такое - номер миссии, двоеточие, shortName). Полное имя получается через AiActor.Name().
 
Частичное решение состоит в переборе наземных и воздушных групп для всех представленных армий и сверке запомненного номера миссии с номером, заключенном в полном имени юнита (формат примерно такое - номер миссии, двоеточие, shortName). Полное имя получается через AiActor.Name().

Версия 15:44, 26 октября 2011

Содержание

Инструменты отладки при работе со скриптами и .dll

Вопрос: В случае более-менее сложного скрипта, какие инструменты отладки можно использовать?
Ответ:
К сожалению, похоже, что кроме собственной головы - никаких. Если кто найдет обратное, буду очень признателен.
Почти наверняка влияет вот эта строчка - //-$debug, но я с ней пока не экспериментировал.
Я делаю так - запускаю студию, новый проект любой C#. Прилинковал к проекту:
...\Steam\SteamApps\common\il-2 sturmovik cliffs of dover\parts\core\part.dll
...\Steam\SteamApps\common\il-2 sturmovik cliffs of dover\parts\core\maddox.dll
...\Steam\SteamApps\common\il-2 sturmovik cliffs of dover\parts\core\gameWorld.dll
...\Steam\SteamApps\common\il-2 sturmovik cliffs of dover\parts\core\gamePlay.dll
...\Steam\SteamApps\common\il-2 sturmovik cliffs of dover\parts\bob\Campaign.dll
Подозреваю, что не все эти сборки необходимы, но особо туда не лез, пусть будут. Последняя же нужна только для миссий из кампании.
Создал класс, в using прописал необходимый минимум
using System;
using maddox.game;
using maddox.game.world;
После код просто копирую в игру. Единственное убираю неймспейс моего проекта. Не самая удобная штука, но писать вполне можно.

Обозначение групп с номерами I и V

Вопрос: Как определить, имеется ли самолет какой-либо группы в данный момент или нет? У немцев названия группы содержат знаки (|, ||, |||, |V, V, V|) и так далее. Но, при написании скрипта игра подобные знаки игнорирует. С англичанами проблем нет, у них обозначения цифровые, например 218Sqn. А вот у немцев обозначения типа JG51_| и игра их не видит
Ответ:
Пример из игры -"BoB_LW_JG53_I"
1 - латинская буква "I", 5 -латинская "V".

Как отслеживать статики?

Вопрос: Как отследить статики? Они не являются AiActor (по крайней мере события на них не реагируют - уничтожен, поврежден и т.д.). Ни в Battle, ни в GamePlay методов никаких похожих тоже нет. GamePlay.gpActorByName("StaticName") тоже ничего не дает. Отследить уничтожение статика(ов) удалось только повесив на них триггер.
Ответ:
Да, статики, это не акторы, у них нет "мозга", и они для красоты стоят, событий не вызывают.

MissionNumberListener и присвоение номера миссии

Вопрос: Что есть поле MissionNumberListener? Пробовал присваивать номер свежезагруженной миссии - вообще всякие события вызывать перестало (в этой миссии).
Ответ:
Это поле, которое показывает события какой миссии скрипт миссии слушает - при загрузке миссии в это поле ставится её номер - т.е. она "слышит" только свои события. Если выставить номер другой миссии - будет "слушать" только её, чтобы все миссии слышать - поле в меньше нуля выставить надо (то есть "-1").

Как убирать с земли самолеты, которые сели на вынужденную или разбились?

Вопрос: Как убирать с земли самолеты, которые сели на вынужденную, разбились не долетев до посадки?
Ответ:
public override void OnAircraftCrashLanded(int missionNumber, string shortName, AiAircraft aircraft)
   {
       base.OnAircraftCrashLanded(missionNumber, shortName, aircraft);
       Timeout(5, () =>
       {
           aircraft.Destroy();
       });
   }
Подробнее здесь. 

Что такое airport.cpp

Вопрос: Если увеличить радиус airport.cpp до 10000, будет ли это убирать обломки с земли/самолеты на вынужденной во всем радиусе действия? Чем грозит такое увеличение радиуса? Каков верхний предел? 50000, 100000 будет работать?
Ответ:
naryv: airport.cpp не убирает самолёты и обломки, он должен машинки к севшим самолётам подвозить, но не уверен что работает, это очень старый скрипт, как реликт скорее всего остался.

Отправка сообщений для заданной армии и типа самолета(истребитель/бомбардировщик)

Вопрос: Как видоизменить код, чтобы надписи в момент подгрузки под-миссий были разные для синей и для красной стороны, а также для истребителей и бомбардировщиков?
Ответ:
Определить армию игрока и выдавать ему соответствующее сообщение:
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;
       }
Подробнее здесь.

Имена групп

Вопрос: Имена групп. Проигрывается одна и та же миссия, получаем имя группы (например, убитого самолета)- в одних случаях получается имя как прописано в миссии, в других на том же самом самолете имя группы становится NoName. Игрок всегда определяется правильно. Запустить группу по action.Do() тоже получается как-то загадочно. В одной и той же миссии, не трогая ни саму миссию, ни скрипта, то стартует, то не стартует. Гарантированно лечится заходом в полный редактор, переназначением имени группы и переназначением стартуемой группы в действиях.
Ответ:
Группа, которая стартует скриптом (с помощью действия, скажем), по сути относится уже к другой миссии. Попробуйте во-первых, назначить переменной MissionNumberListener значение -1, примерно вот так:
public override void OnBattleStarted()
{
    base.OnBattleStarted();
    MissionNumberListener = -1;
}
Во-вторых, имя группы состоит из собственно имени группы и префикса "принадлежности к миссии" (номер миссии с двоеточием). Получить правильно полное имя группы (например для использования в GamePlay.gpActorByName()) можно примерно вот так:
public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
   base.OnActorCreated(missionNumber, shortName, actor);
   string fullName = ActorName.Full(missionNumber, shortName);
}
В любом событии, относящемся к акторам, в первых двух параметрах передаются собственно номер миссии, где произошло событие, и короткое имя актора (как указано в файле миссии). Из двух этих параметров мы и получаем полное имя актора.

Удаление спауна группы (BirthPlaces)

Вопрос: Как средствами редактора удалить старый спаун? Он же уже подгружен в миссию, нужен инструмент, чтобы его удалить.
Ответ:
Средствами редактора это невозможно, скриптом так:
foreach (AiBirthPlace bp in GamePlay.gpBirthPlaces())
       {
           if (bp != null)
               bp.destroy();         
       }

Как во время миссии пересадить игрока в другой самолет?

Вопрос: Как во время миссии пересадить игрока в другой самолет?
Ответ:
Находим группу, в цикле перебираем самолеты группы и сажаем игрока в первый же самолет, где есть кабина пилота.
   AiActor actor = GamePlay.gpActorByName(ActorName.Full(MissionNumber, "BoB_LW_LG2_I.01"));
           if (actor is AiAirGroup && GamePlay.gpPlayer() != null)
           {
               Player player = GamePlay.gpPlayer();
               foreach (AiAircraft airc in (actor as AiAirGroup).GetItems())
               {
                   bool isFound = false;
                   for (int i = 0; i < airc.Places(); i++)
                   {
                       if (airc.ExistCabin(i))
                       {
                           if (airc.CrewFunctionPlace(i).Equals(CrewFunction.Pilot))
                           {
                               player.PlaceEnter(airc, i);
                               isFound = true;
                               break;
                           }
                       }
                   }
                   if (isFound) break;
               }
           }

Как задать периодические загрузки миссии без использования TickCounter()?

Вопрос: Как во время миссии пересадить игрока в другой самолет?
Ответ:
Периодические загрузки миссии без использования TickCounter() осуществляются через MissionLoader:
//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);});
    }
}

Какие параметры у GamePlay.gpHUDLogCenter?

Вопрос: Как можно настраивать GamePlay.gpHUDLogCenter , чтобы писать мельче, другим цветом (ярко-синим, например) и внизу экрана. Как можно возврат каретки / перенос вставить, менять длительность показа?
Ответ:
GamePlay.gpHUDLogCenter("",123) ,где 123 - длительность отображения надписи. Также можно показывать сообщение определённым игрокам, по остальным вопросам - пока никак, возможно позже добавится более широкое управление.

Относятся ли корабли к AiGroundActor?

Вопрос: Относятся ли корабли к AiGroundActor?
Ответ:
Да, корабль - это AiGroundActor и AiGroundGroup ,с типом Ship , всех кораблей страны найти можно так:
foreach (AiGroundGroup gg in GamePlay.gpGroundGroups(army))
{
if (gg.Type == AiGroundGroupType.Ship)
   {// тут делаем с ними что нам нужно, например
        if (gg != null)
        (gg 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);        
       GamePlay.gpLogServer(null, "{0} actor dead, 1st killer is {1} ", new object[] { actor.Name(),damages[0].initiator.Actor.Name()});
   }

Как открыть подмиссию, чтобы в ней отображались все объекты?

Вопрос: При открытии подмиссий в полном редакторе не появляются ни танки, ни самолеты, ни точки маршрута (открывается чистая карта), хотя в тексте миссии они есть, если открыть ее блокнотом. Почему это происходит?
Ответ:
Секция с описанием карты, времени и пр. начальных условий миссии не нужна в подмиссии - ведь она загружается к уже запущенной миссии - поэтому такую секцию я удалил - так подмиссия чуть-чуть, но быстрее грузится. Если надо в редакторе открыть - можно просто из основной эту секцию скопировать в файл подмиссии :
[PARTS]
 core.100
 bob.100
 [MAIN]
 MAP Land$Online_Cross_v_Roundel
 BattleArea 6000 6000 26000 26000 1000
 TIME 16
 WeatherIndex 0
 CloudsHeight 1000
 BreezeActivity 10
 ThermalActivity 10

Как можно суб-скрипт загружать из другого скрипта, на загружая .mis файл суб-миссии?

Вопрос: Как можно суб-скрипт загружать из другого скрипта, на загружая .mis файл суб-миссии? Хочется разбивать большие скрипты на тематические кусочки, чтобы править только те, которые нужно.
Ответ:
Создавать пустые подмиссии, в которых будут только нужные куски скрипта.

DamagerScore - параметры

Вопрос: 1. В DamagerScore из maddox.game.world есть две числовые переменные score и time. Score - степень повреждения и в чем она измеряется?
2. Если смотреть список инициаторов сбитого самолета (как акторов ) по функции OnActorDead (из AMission), то в нем всегда есть сам убитый актор, у которого score больше нуля. Как это понять? Типа повреждения, которые наносятся не напрямую противником, записываются на самого актора. Например, противник повредил систему охлаждения (записано противнику), из-за поврежденной системы охлаждения накрывается двигатель (а это уже пишут самому актору). Или на убитого актора просто записывают очки повреждения от самого падения?
3. Что показывает параметр time? Как я понимаю это время нанесения последнего повреждения для инициатора?
Ответ:
1. Score - это степень участия инициатора в демадже, т.е. если игроки вдвоём пилили один самолёт, убили его и нанесли одинаковые повреждения, у score будет по 0.5, если dтроём с тем же результатом - по 0.3(3) ну и т.д., если поврежедния не одинаковые - то у кого повреждения более значительные, у того и score больше.
2. На убитого актора записывают оставшийся демадж от падения, если взорвать его в воздухе - ему ничего не запишется. Т.е. мы сломали ему мотор нам записали, допустим 0.6 демаджа, дальше он упал и разбился - ему 0.4 запишут.
3. Да, именно так.

Z_VelocityIAS и подобные - единицы измерения

Вопрос: 1. В каких единицах возвращается значение по запросу Z_VelocityIAS и подобные? Получал с subtype=-1. Значение в среднем ниже на 2,36, если ориентироваться по прибору в км/ч на 500-х метрах.
2. Так как не совсем ясно, в каких единицах возвращается значение по вопросу выше, пробовал получать по Z_VelocityMach. Стало похоже на правду, но возник еще вопрос: конкретное значение ск. звука зависит от температуры воздуха?
Ответ:
1. В метрах/секунду все подобные параметры.
2. Да, зависит.

Использование класса List(Of T) вместо массивов

Вопрос: Есть массив данных, как заменить его на List?
Ответ:
Было:
//Параметры меню
string[] descMainMenu;    //Описание пунктов главного меню
descMainMenu = new string[] { "Тест системы сообщений", "Конвои" };
private void setMainMenu( Player player )
   {
       GamePlay.gpSetOrderMissionMenu( player, false, 0, descMainMenu, new bool[] { false, true } );
   }
Стало:
   List<string> descMainMenu = new List<string>();
   descMainMenu.Add("Тест системы сообщений");
   descMainMenu.Add("Конвои");
   private void setMainMenu( Player player )
   {
       GamePlay.gpSetOrderMissionMenu( player, false, 0, descMainMenu.ToArray(), new bool[] { false, true } );
   }

Как удалить все юниты подмиссии

Вопрос: Есть загруженная подмиссия с неизвестным номером. Как удалить все юниты именно этой подмиссии не перебирая в циклах всю наземку? Или может быть просто можно подмиссию выгрузить?
Ответ:
Никак.

Что бы миссия не была неизвестной, надо перед ее загрузкой запомнить след. номер (NextMissionNumber или как то так). Частичное решение состоит в переборе наземных и воздушных групп для всех представленных армий и сверке запомненного номера миссии с номером, заключенном в полном имени юнита (формат примерно такое - номер миссии, двоеточие, shortName). Полное имя получается через AiActor.Name(). Почему частичное? Перебором групп ты не найдешь юнитов, которые групп не имеют (артиллерия и стат. корабли как минимум), т.е. по OnActorCreated надо еще и их запоминать. Похожее решение используется в морском льве. Домики, ящички и все что в разделе статический и т.д. не удалишь вообще никак.

Формат GamePlay.gpSetOrderMissionMenu

Вопрос: 1. Интересует формат GamePlay.gpSetOrderMissionMenu
Ответ:
1.
gpSetOrderMissionMenu( Player player, bool thisSubMenu, int ID, string[] keys, bool[] bSubMenu ); 

Player player - игрок которому выдаётся кастомное меню

bool thisSubMenu - является ли данный набор пунктов подменю

int ID - ID пункта по которому его можно идентифицировать

string[] keys массив строк-пунктов меню

bool[] bSubMenu массив bool показывающий есть ли у каждого пункта подменю