Приветствую Вас Гость | RSSГлавная | Миссия моей мечты, часть 4 - Форум | Регистрация | Вход
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Страница 1 из 11
Форум » Статьи » Создание миссий » Миссия моей мечты, часть 4 (Периодичный десант, условия, таймеры, рандом)
Миссия моей мечты, часть 4
RaseriДата: Воскресенье, 10.11.2013, 18:16 | Сообщение # 1
Темный Клинок
Группа: Добрый Модератор
Сообщений: 779
Награды: 23  +
Репутация:  ±
Замечания:  ±
Статус: Offline
Всем привет smile
Перечитав прошлые части статьи, я заметил, что до сих пор ничего не рассказал вам про такие важные в создании миссии штуки, как условные операторы и таймеры smile
И, чтобы рассказать вам об этом, да ещё и на интересных примерах, я поведаю в этой статье о том, как сделать периодичную высадку вражеских подкреплений.

Для начала взглянем на код миссии, на функцию Breakthrough:UpdateActivity()



Именно в этой функции мы и будем писать код периодичного спавна врагов.
Но для начала, нам нужно сделать кое-какие приготовления.

Во-первых, сбрасывать десант нужно не абы куда, а над базой врага (и лучше всего прямо внутрь бункера, через шахту), так что мы должны каким-либо образом получить координаты появления кораблей.
Можно это сделать тем способом, который давался во второй части статьи.

Во-вторых, если у противника будет командир, то логично, что его будут пытаться всеми силами защитить, что хотя бы часть войск будет направлена вниз, к его комнате.
Для этого нам потребуется расставить в коридорах и комнатах несколько зон, которые солдаты будут занимать.
Как размещать зоны, написано тоже во второй части smile

Немножко покопавшись с редакторами сцен и зон, я получил координаты вражеского корабля (Х == 1000) и расставил зоны следующим образом:



Как вы могли заметить, одной зоне соответствует несколько прямоугольников.
Выбрав название зоны, я просто добавлял и добавлял новые "боксы", пока ими не оказались покрыты все подходящие места.
Также, я окружил зоной комнату с командиром:



Если игрок подберётся тем или иным образом достаточно близко к вражескому командиру, то ВСЕ вражеские войска получат приказ ломануться вниз, на выручку.

В StartActivity присваиваю зоны переменным и под комментарием указываю координату (чтоб не забыть), также я решил сразу создать таймер:

Код
-- присваиваем переменным зоны
           self.ZoneOutpost = SceneMan.Scene:GetArea("Outpost");
           self.ZoneAlarm = SceneMan.Scene:GetArea("ZoneAlarm"); -- зона для проверки проникновения войск игрока вглубь базы
           self.DefPosTop = SceneMan.Scene:GetArea("DefPosTop"); -- позиции для прибывших подкреплений
           self.DefPosDown = SceneMan.Scene:GetArea("DefPosDown");
                  
           self.TimerReinf = Timer(); -- создаём таймер
           self.TimerReinf:Reset(); -- сбрасываем, начиная отсчёт


В UpdateActivity начинаю прописывать код спавна.
Вот, кстати, полная форма условного оператора:

Код
function Breakthrough:UpdateActivity()

           self:ClearObjectivePoints();
                  
           if self.TimerReinf:IsPastSimMS(30000) and (MovableMan:GetMOIDCount() < 200) then
               -- создаём корабль
                        
               for i = 1,3 do
                   -- создаём трёх солдат коалиции, даём им оружие и суём в корабль
               end
                      
               -- спавним корабль
               -- сбрасываем таймер (если это не сделать, корабли будут спавнится бесконечной лавиной)
                      
           end
                  
           self:YSortObjectivePoints();
                  
end

    Важное замечание:
Если на карте единовременно окажется слишком много акторов, ИИ начнёт жестоко лагать.
Чтобы такого не происходило, в условие спавна добавляется "MovableMan:GetMOIDCount() < 200".
В том случае, если на игровом уровне находится и без того достаточно войск, код просто "подождёт", пока их количество не убудет.


А вот как я написал код спавна:

Код
function Breakthrough:UpdateActivity()

           self:ClearObjectivePoints();
                  
           if self.TimerReinf:IsPastSimMS(30000) and (MovableMan:GetMOIDCount() < 200) then
               -- создаём корабль
               local ship = CreateACDropShip("Drop Ship MK1" , "Base.rte");        
               ship.Pos = Vector (1000, -20);
               ship.Team = 1;
               ship:SetControllerMode(Controller.CIM_AI, -1);
                      
               -- создаём трёх солдат коалиции, даём им оружие и суём в корабль
               for i = 1,3 do
                   local soldier = CreateAHuman("Soldier Light","Coalition.rte");
                   soldier.Team = 1;
                   soldier:AddInventoryItem(CreateHDFirearm("Compact Assault Rifle","Coalition.rte"));
                   ship:AddInventoryItem(soldier);
               end
                      
               -- спавним корабль
               MovableMan:AddActor(ship);        
               -- сбрасываем таймер
               self.TimerReinf:Reset();
           end
                  
           self:YSortObjectivePoints();
                  
end


Единственное, что тут ещё не указано, это режим ИИ для вражеских солдат.
Решил его организовать я так (кстати, можете посмотреть здесь на вложенные условия):

Код
function Breakthrough:UpdateActivity()

           self:ClearObjectivePoints();
                  
           if self.TimerReinf:IsPastSimMS(30000) and (MovableMan:GetMOIDCount() < 200) then
               -- создаём корабль
               local ship = CreateACDropShip("Drop Ship MK1" , "Base.rte");        
               ship.Pos = Vector (1000, -20);
               ship.Team = 1;
               ship:SetControllerMode(Controller.CIM_AI, -1);
                      
               -- создаём трёх солдат коалиции, даём им оружие и суём в корабль
               for i = 1,3 do
                   local soldier = CreateAHuman("Soldier Light","Coalition.rte");
                   soldier.Team = 1;
                   soldier:AddInventoryItem(CreateHDFirearm("Compact Assault Rifle","Coalition.rte"));
                          
                   local AI;
                   AI = math.random(); -- переменной AI присваивается случайное значение от 0 до 1 (в виде дроби)

                   if AI >= 0.5 then -- в половине случаев охотится за мозгом игрока
                       soldier.AIMode = Actor.AIMODE_BRAINHUNT;
                   elseif AI > 0.25 then -- в четверти случаев занимает позиции вверху
                       soldier.AIMode = Actor.AIMODE_GOTO;
                       soldier:ClearAIWaypoints();
                       soldier:AddAISceneWaypoint(Vector(self.DefPosTop:GetRandomPoint().X , self.DefPosTop:GetRandomPoint().Y));
                   else -- в четверти случаев занимает позиции внизу
                       soldier.AIMode = Actor.AIMODE_GOTO;
                       soldier:ClearAIWaypoints();
                       soldier:AddAISceneWaypoint(Vector(self.DefPosDown:GetRandomPoint().X , self.DefPosDown:GetRandomPoint().Y));
                   end
                          
                   ship:AddInventoryItem(soldier);
               end
                      
               -- спавним корабль
               MovableMan:AddActor(ship);        
               -- сбрасываем таймер
               self.TimerReinf:Reset();
           end
                  
           self:YSortObjectivePoints();
                  
end

Теперь, нам нужно сделать так, чтобы при вторжении солдат игрока в self.AlarmZone, все вражеские войска направились вниз, на выручку.

Немного отступив от кода периодичного спавна, я пишу:
     
Код
local actor;
       for actor in MovableMan.Actors do -- перебираем всех акторов (солдат, крабов, корабли, т.д.)
           if (actor.Team == 0) and self.ZoneAlarm:IsInside(actor.Pos) then -- если принадлежит игроку и пересекает зону
               --приказываем двигаться вниз
           end
       end

Теперь подробнее распишу код, в котором мы прикажем всем врагам тащиться вниз.
Во-первых, с помощью "for actor in MovableMan.Actors" нам снова нужно перебрать всех акторов (чтобы найти тех, кто принадлежит врагу).
Во-вторых, всем им нужно приказать идти в точку... мм... ну, скажем, ту самую, где стоял в самом начале дрон коалиции, т.е. по координатам (1100, 854).

Получаем:
     
Код
local actor;
       for actor in MovableMan.Actors do -- перебираем всех акторов (солдат, крабов, корабли, т.д.)
           if (actor.Team == 0) and self.ZoneAlarm:IsInside(actor.Pos) then -- если принадлежит игроку и пересекает зону
              
               local actor
               for actor in MovableMan.Actors do
                   if actor.Team == 1 then
                       actor.AIMode = Actor.AIMODE_GOTO;
                       actor:ClearAIWaypoints();
                       actor:AddAISceneWaypoint(Vector(1100, 854));
                   end
               end
               break; -- прерываем внешний цикл, продолжать поиск вторгнувшихся войск игрока нет смысла
                  
           end
       end

Хорошо, теперь нам нужно сделать ещё две вещи с этим многострадальным кусочком кода.

Во-первых, нам нужно запретить выполнение этого кода после того, как он будет один раз уже выполнен.
Ну, вы понимаете, если мы это не сделаем, то каждый раз, как какой-то солдат игрока окажется в зоне, каждые несколько миллисекунд все враги снова и снова будут получать приказ двигаться вниз.
Нам это не надо.

Во-вторых, проверка по всем акторам штука весьма ресурсоёмкая, поэтому проводить ещё слишком часто было бы нерационально.
Из-за этого мы добавим таймер, который будет запускать проверку... скажем, раз в полторы секунды.

В StartActivities прописываем новую переменную и таймер:
    
Код
self.Alarm = 0; -- "0" позволяет проводить проверку; "1" - эту проверку отключает
      self.AlarmTimer = Timer();
      self.AlarmTimer:Reset();

А код тревоги дополняем таким образом:

    
Код
if self.Alarm == 0 then
          if self.AlarmTimer:IsPastSimMS(1500) then
              local actor;
              for actor in MovableMan.Actors do -- перебираем всех акторов (солдат, крабов, корабли, т.д.)
                  if (actor.Team == 0) and self.ZoneAlarm:IsInside(actor.Pos) then -- если принадлежит игроку и пересекает зону
                      for actor in MovableMan.Actors do
                          if actor.Team == 1 then
                    actor.AIMode = Actor.AIMODE_GOTO;
                    actor:ClearAIWaypoints();
                    actor:AddAISceneWaypoint(Vector(1100, 854));
                          end
                      end
                      self.Alarm = 1; -- прекращаем выполнение куска кода
                      break; -- прерываем внешний цикл, продолжать поиск вторгнувшихся войск игрока нет смысла
                
                  end
              end
                
              self.AlarmTimer:Reset();
          end
      end


Надеюсь, я не слишком запутал и запугал вас этими горами текста smile
Мне показалось, что несколько этапов написания кода помогут вам получше разобраться, что тут к чему smile

Возможно, это покажется вам самой сложной частью статьи, но это, пожалуй, и одна из самых важных её частей.
Разобравшись и освоив то, про что тут идёт речь, вы уже сможете с лёгкостью программировать "сюжет" миссии, который сможет включать в себя передвижение войск и создание в нужных местах нужных акторов (в том числе и десантных кораблей с десантом), также из этой статьи можно выдернуть режим ИИ, позволяющий приказать охотится за вражеским мозгом.

К посту снова прикрепляю миссию - смотрите, разбирайтесь, задавайте в комментариях вопросы smile

Если потребуется помощь, вы можете выложить сюда свою миссию и обрисовать характер затруднения - я запрограммирую вам нужную часть (дав к коду подробные комментарии) или помогу исправить ошибки.

Мне очень важно, выглядят ли мои объяснения здесь, в статье, достаточно понятными, поэтому прошу отписаться и рассказать, как вам показалась "на вкус" эта часть smile
Прикрепления: 9686894.png(25Kb) · 8387764.png(122Kb) · 0143052.png(146Kb) · 6263674.png(137Kb) · Breakthrough.rt.rar(18Kb)
 
puksusДата: Воскресенье, 10.11.2013, 22:41 | Сообщение # 2
Пукс
Группа: Модераторы
Сообщений: 931
Награды: 0  +
Репутация:  ±
Замечания:  ±
Статус: Offline
Идея о том, что если один пересекает область, то и все шпарят туда, мне очень понравилась.Также, можно уничтожать лежащее на поле боя оружие в случае, если количество моидов зашкаливает (оружие ведь относится к моидам, да?)
И вопрос: как поведёт себя солдат, который во время перестрелки с противником получил приказ валить вниз? Забудет про соперника и будет игнорировать его стрельбу до первого попадания(или вообще всё будет игнорировать?) или сначала убьёт(если убьёт) соперника и уже потом пойдёт вниз?

Статья отличная, хватило ж терпения всё разжовывать до мелочей...
 
RaseriДата: Понедельник, 11.11.2013, 00:08 | Сообщение # 3
Темный Клинок
Группа: Добрый Модератор
Сообщений: 779
Награды: 23  +
Репутация:  ±
Замечания:  ±
Статус: Offline
>>как поведёт себя солдат, который во время перестрелки с противником получил приказ валить вниз?
Сначала рыпнется выполнять новый приказ, потом увидит врага / услышит выстрел и вернётся к своему прежнему занятию, а после победы (если победит, конечно) продолжит движение smile

>>Также, можно уничтожать лежащее на поле боя оружие в случае, если количество моидов зашкаливает
Эмм... ну да, в принципе можно, но я так никогда не делал ))
Мне кажется, было бы довольно печально потерять таким образом крутые пушки, выпадающие со своих или вражеских солдат.
Вполне вроде хватает ограничения по десанту для врагов.

НО если это реквест, то я напишу скрипт, мне не сложно smile
 
Форум » Статьи » Создание миссий » Миссия моей мечты, часть 4 (Периодичный десант, условия, таймеры, рандом)
Страница 1 из 11
Поиск:
Статистика Форума
Последние темы Читаемые темы Последние зарегистрированные пользователи
Imperial Lost [Xterian]

Компания ронинов Escape - v.1.2.0 {B32} [Xterian]

Комиксы по моду Imperial Lost [Xterian]

Выход 24 билда. [Xterian]

23 Билд [Xterian]

Coalition Heavy Mount Turret [Xterian]

BAW [Xterian]

Подразделение Анти Зомби [Xterian]

Happy New Year [Xterian]

Corporation of Improbable Researches v0.7.5 [Xterian]

[1]>Флудильня! [5131]

[2]>Свалка арта. [879]

[3]>Фан-арт по Cortex Command [386]

[4]>игра обломи предыдущего [330]

[5]>Black Ravens v.0.8.8 {B27} [284]

[6]>Выход 24 билда. [281]

[7]>[UNITED TERRAN FORCES] [274]

[8]>Улучшения форума [270]

[9]>Песенки или музыка. [269]

[10]>Russian Combat Small Arms {B24-B27} [263]

lorderplay [06.09.2017|15:21]

gergeswael855 [01.09.2017|19:40]

leva_soot [25.08.2017|11:46]

Sanidze [20.08.2017|11:14]

kapustyansahsa [24.07.2017|16:08]

tema4ka123 [24.07.2017|15:49]

troller [21.07.2017|12:30]

watttt311 [17.07.2017|21:06]

popsalida [13.07.2017|18:12]

mihaildmitriev2016 [12.07.2017|05:58]


Вверх
Русский Фан Сайт Cortex Command © 2017.