Sail: Podwójny Laser

Wszelkie pytania na temat SAIL'a i modowania OW.
Post Reply
User avatar

Topic author
0dd1
ArCamp Developer
Posts: 225
Joined: Tue Jul 01, 2014 3:01 pm

Sail: Podwójny Laser

#1

Post by 0dd1 » Sat Aug 12, 2017 11:05 pm

Funkcja w założeniu ma działać jak ComAttackUnit dla podwójnych laserów. Jednak z racji na ich wyjątkowość musi być używana bez przerwy, przez cały czas trwania ataku. Dodatkowo zadziała na całą listę laserów i wrogów - funkcja sama dobiera lasery do celów.

Podanie Area przy użyciu funkcji jest opcjonalne - oznacza obszar do którego lasery mają NIE wchodzić, jeśli akurat jest taka potrzeba.

Ostatnia wartość oznacza preferowaną odległość laserów od ich celu. Dozwolone wartości: 0 - lasery otaczają cel jak najciaśniej, 1 - pośrednia odległość (w większości przypadków najbardziej rozsądna), 2 - lasery będą rozstawiać się podczas ataku jak najszerzej.

Code: Select all

Function DoubleLaserAttack(LaserList, AllTargets, Area, val);
var Lasers, LaserGroups, L1, L2, Target, temp_target_list, TargetX, TargetY;
var hex_list1, hex_list2, hex1, hex2, temp_hex, choosen_hexes, temp_list_x, temp_list_y, chosen_list;
var i, j, un, temp, temp_list, dist, dist1, dist2, common_hex;
var dir0_x, dir0_y, dir1_x, dir1_y, dir2_x, dir2_y, dir3_x, dir3_y, dir4_x, dir4_y, dir5_x, dir5_y, dir6_x, dir6_y, dir7_x, dir7_y, dir8_x, dir8_y, dir9_x, dir9_y, dir10_x, dir10_y, dir11_x, dir11_y;
begin
     if AllTargets <= 0 then
        exit;

     temp_list = UnitFilter(LaserList, [f_not,[f_weapon,us_double_laser]]);

     if temp_list > 0 then                         
        ComAttackUnit(temp_list, AllTargets[1]);   //Jednostki inne niż podwójne lasery po prostu atakują pierwszy cel z listy

     Lasers = UnitFilter(LaserList, [f_weapon,us_double_laser]);

     if Lasers < 2 then
     begin                                         
          ComAttackUnit(Lasers, AllTargets[1]);    //To samo dotyczy pojedyńczego lasera
          exit;
     end
     else
         begin
              LaserGroups = [];

              //Dobieranie laserów w pary. Jeśli zostanie jeden ekstra to będzie robił to samo co drugi laser w ostatniej parze
              while Lasers > 1 do
              begin
                   temp = [Lasers[1], Lasers[2]];
                   Lasers = Lasers diff temp;

                   if Lasers = 1 then
                      temp = temp ^ Lasers[1];

                   LaserGroups = LaserGroups ^ [temp];
              end;
         end;

     if val < 0 then
        val = 0;

     if val > 2 then
        val = 2;


     //Przy każdym celu (T) przyjmuje się zestaw hexów które tworzą kilka okręgów wokój jego pozycji. Składa się to z 7 teoretycznych hexów odchodzących w prostej linii od celu, w każdym z 12 kierónków
     //Dir0 tutaj to to samo co kierunek 0 w edytorze, Dir1 idzie pomiędzy kierunkiem 0 i 1 w edytorze, Dir2 odpowiada kierunkowi 1 i tak dalej
     // *  *  *  *  *
     //   * * * * *
     //     *****
     // * * * T * * *
     //     *****
     //   * * * * *
     // *  *  *  *  *

     //Poniżej coordynaty względem pozycji celu
     Dir0_X = [0, 0, 0, 0, 0, 0, 0];    Dir0_Y = [-3, -5, -7, -9, -11, -13, -15]; Dir1_X = [2, 3, 4, 5, 6, 7, 8];     Dir1_Y = [-2, -3, -4, -5, -6, -7, -8];
     Dir2_X = [3, 5, 7, 9, 11, 13, 15]; Dir2_Y = [0, 0, 0, 0, 0, 0, 0];           Dir3_X = [4, 6, 8, 10, 12, 14, 16]; Dir3_Y = [2, 3, 4, 5, 6, 7, 8];
     Dir4_X = [4, 5, 7, 9, 11, 13, 15]; Dir4_Y = [4, 5, 7, 9, 11, 13, 15];        Dir5_X = [2, 3, 4, 5, 6, 7, 8];     Dir5_Y = [4, 6, 8, 10, 12, 14, 16];
     Dir6_X = [0, 0, 0, 0, 0, 0, 0];    Dir6_Y = [3, 5, 7, 9, 11, 13, 15];        Dir7_X = [-2, -3, -4, -5, -6, -7, -8]; Dir7_Y = [2, 3, 4, 5, 6, 7, 8];
     Dir8_X = [-3, -5, -7, -9, -11, -13, -15]; Dir8_Y = [0, 0, 0, 0, 0, 0, 0];    Dir9_X = [-4, -6, -8, -10, -12, -14, -16]; Dir9_Y = [-2, -3, -4, -5, -6, -7, -8];
     Dir10_X = [-3, -5, -7, -9, -11, -13, -15]; Dir10_Y = [-3, -5, -7, -9, -11, -13, -15]; Dir11_X = [-2, -3, -4, -5, -6, -7, -8]; Dir11_Y = [-4, -6, -8, -10, -12, -14, -16];

     temp_list_x = [dir0_x, dir1_x, dir2_x, dir3_x, dir4_x, dir5_x, dir6_x, dir7_x, dir8_x, dir9_x, dir10_x, dir11_x];
     temp_list_y = [dir0_y, dir1_y, dir2_y, dir3_y, dir4_y, dir5_y, dir6_y, dir7_y, dir8_y, dir9_y, dir10_y, dir11_y];

     temp_target_list = 0;

     for un in LaserGroups do
     begin
          common_hex = [(GetX(un[1]) + GetX(un[2]))/2, (GetY(un[1]) + GetY(un[2]))/2];
          temp_list = [];

          if temp_target_list = 0 then
             temp_target_list = AllTargets;

          dist = 999;

          //Wybieranie najbliższego celu dla każdej pary laserów
          for i in temp_target_list do
          begin
               dist1 = GetDistUnits(i, un[1]);
               dist2 = GetDistUnits(i, un[2]);

               if dist1 > dist2 then
                  temp = dist1
               else temp = dist2;

               //Dodatkowy próg (+ 3) zapobiega zbyt częstej zmianie celu. Inaczej mogą zmieniać sobie cel gdy tylko minimalnie się ruszą
               if temp + 3 < dist then
               begin
                    dist = temp;
                    Target = i;
               end;
          end;

          temp_target_list = temp_target_list diff Target;

          TargetX = GetX(Target);
          TargetY = GetY(Target);

          hex_list1 = [];
          hex_list2 = [];

          //Wybieranie pierwszego dostępnego hexu z każdego kierunku, aby otrzymać pojedyńczy okrąg z hexów
          //Sprawdzane są w parach - jeśli jakiś kierunek nie ma żadnego dostępnego hexu, kierunek po przeciwnej stronie też się nie liczy
          for i = 1 to 6 do
          begin
               hex1 = [];
               hex2 = [];

               hex_list1 = hex_list1 ^ [hex1];
               hex_list2 = hex_list2 ^ [hex2];

               //Priorytet: najbliższy, środkowy lub najdalszy dystans, zależnie od wybranej wartości
               case val of
                    0: temp_list = [1,2,3,4,5,6,7];
                    1: temp_list = [4,5,3,6,2,7,1];
                    else
                        temp_list = [7,6,5,4,3,2,1];
               end;

               //Dostępny hex to: wolny i znajdujący się na mapie, nie będący w wybranym Area, nie będący stromym zboczem, ani terenem typu: don't enter, don't enter water, don't enter rock
               for j in temp_list do
               begin
                    temp_hex = [TargetX + temp_list_x[i][j], TargetY + temp_list_y[i][j]];

                    if not ValidHex(temp_hex[1], temp_hex[2]) or ( HexInfo(temp_hex[1], temp_hex[2]) > 0 and not HexInfo(temp_hex[1], temp_hex[2]) in un ) then
                       continue;

                    if Area > 0 then
                       if InArea(temp_hex[1], temp_hex[2], Area) then
                          continue;

                    if GetHexInfo(temp_hex[1], temp_hex[2])[3] in [40,41,42,43,44,45,48,49,50,51,52,53] or GetHexInfo(temp_hex[1], temp_hex[2])[6] in [3,4,6] then
                       continue;

                    hex1 = temp_hex; //Hex wybrany
                    break;
               end;

               if hex1 = [] then   
                  continue;

               //Powtórzenie tego samego dla kierunków po drugiej stronie celu
               for j in temp_list do
               begin
                    temp_hex = [TargetX + temp_list_x[i+6][j], TargetY + temp_list_y[i+6][j]];

                    if not ValidHex(temp_hex[1], temp_hex[2]) or ( HexInfo(temp_hex[1], temp_hex[2]) > 0 and not HexInfo(temp_hex[1], temp_hex[2]) in un ) then
                       continue;

                    if Area > 0 then
                       if InArea(temp_hex[1], temp_hex[2], Area) then
                          continue;

                    if GetHexInfo(temp_hex[1], temp_hex[2])[3] in [40,41,42,43,44,45,48,49,50,51,52,53] or GetHexInfo(temp_hex[1], temp_hex[2])[6] in [3,4,6] then
                       continue;

                    hex2 = temp_hex;
                    break;
               end;

               if hex2 = [] then
                  continue;

               //Te dwa zestawy razem tworzą pojenyńczy okrąg z hexów wokół celu
               hex_list1 = Replace(hex_list1, i, hex1);
               hex_list2 = Replace(hex_list2, i, hex2);
          end;

          //Jeśli nie wybrano żadnych hexów, lasery po prostu podjadą do celu
          if (hex_list1 diff 0) = 0 then
          begin
               ComMoveUnit(un, Target);
               exit;
          end;

          //Dwa zestawy tych samych hexów w przeciwnej kolejności. Po jednym dla każdego laseru.
          hex_list1 = hex_list1 ^ hex_list2;
          hex_list2 = hex_list2 ^ hex_list1;

          temp_list = [];
          j = [1,2,3,4,5,6,7,8,9,10,11,12];

          //W obrębie ustalonego okręgu: wybieranie najbliższej pary hexów zależnie od pozycji obu laserów
          //Aby potem porównać odległości od pozostałych hexów w odpowieniej kolejności
          for i in j do
              temp_list = temp_list ^ GetDistXY(common_hex[1],common_hex[2], TargetX + temp_list_x[i][5],TargetY + temp_list_y[i][5]);

          i = WorstFromListByList(j,temp_list);


          case i of
               1,7: temp_list = [4,5,6,1,2,3];
               2,8: temp_list = [5,6,1,2,3,4];
               3,9: temp_list = [6,1,2,3,4,5];
               4,10: temp_list = [1,2,3,4,5,6];
               5,11: temp_list = [2,3,4,5,6,1];
               6,12: temp_list = [3,4,5,6,1,2];
          end;                                 

          dist = 999;


          //2 tryby ataku: 1- Jeśli lasery są oddalone od celu to zbliżają się do swojej najbliższej pary hexów
          //               2- Jeśli już są na pozycji to powinny zacząć równocześnie przemieszczać się po okręgu. Dzięki temu mogą uniknąć trochę pocisków wroga
          for i in temp_list do
          begin
               if hex_list1[i] = [] then
                  continue;

               hex1 = hex_list1[i];
               hex2 = hex_list2[i];

               //Przy wybieraniu najbliższej pary hexów, dobrze jest najpierw ustalić który laser jest bliżej którego hexu
               if GetDistUnitXY(un[1], hex1[1], hex1[2]) < GetDistUnitXY(un[2], hex1[1], hex1[2]) + 3 then
               begin
                    L1 = un[1];
                    L2 = un[2];
               end
               else
               begin
                    L1 = un[2];
                    L2 = un[1];
               end;

               dist1 = GetDistUnitXY(L1, hex1[1], hex1[2]);
               dist2 = GetDistUnitXY(L2, hex2[1], hex2[2]); 


               //Atak 2: wybierane są trzy kolejne hexy w okręgu aby lasery były w ciągłym ruchu
               if dist1 < [3,4,6][val+1] and dist2 < [3,4,6][val+1] then
               begin
                    choosen_hexes = [];

                    for j = 1 to 3 do
                        if i + j > hex_list1 then
                           choosen_hexes = choosen_hexes ^ [hex_list1[i+j - hex_list1], hex_list2[i+j - hex_list1]]
                        else
                            choosen_hexes = choosen_hexes ^ [hex_list1[i+j], hex_list2[i+j]];
                    break;
               end;


               if dist1 > dist2 then
                  temp = dist1
               else
                   temp = dist2;

               //Atak1 : najbliższa para hexów
               if (temp + [6,8,10][val+1]) < dist then
               begin
                    dist = temp;
                    choosen_hexes = [hex1, hex2];
               end;
          end;

          //Jeśli zostanie jeden ekstra to będzie robił to samo co drugi laser w ostatniej parze
          if un > 2 then
             L2 = L2 ^ un[3];

          //Jeśli nie wybrano żadnych hexów, lasery po prostu podjadą do celu
          if choosen_hexes[1] = [] then
          begin
               ComMoveUnit([L1,L2], Target);
               exit;
          end;


          //I w końcu, polecenie samego ruchu do wybranych hexów
          ComMoveXY(L1, choosen_hexes[1][1],choosen_hexes[1][2]);
          ComMoveXY(L2, choosen_hexes[2][1],choosen_hexes[2][2]);

          if choosen_hexes > 2 then
             for i = 3 to choosen_hexes do
                 if choosen_hexes[i] > [] then
                    if i in [3,5] then
                       AddComMoveXY(L1, choosen_hexes[i][1],choosen_hexes[i][2])
                    else
                        AddComMoveXY(L2, choosen_hexes[i][1],choosen_hexes[i][2]);

     end;
end; 

Mała prezentacja (starszej wersji) poniżej. Kod ataku to dosłownie coś takiego:

Code: Select all

every 0$1 do
begin
DoubleLaserAttack(BlueTeam, RedTeam, area);
enable;
end;
Last edited by 0dd1 on Sun Feb 11, 2018 2:31 pm, edited 4 times in total.

User avatar

zoNE
The Great Uniter & Site Administrator
The Great Uniter & Site Administrator
Posts: 1159
Joined: Fri Feb 17, 2006 3:44 pm
Location: Poland
Contact:

Re: Sail: Podwójny Laser

#2

Post by zoNE » Sat Aug 12, 2017 11:38 pm

Fajne, fajne :P. Nie zaglebialem sie w kod, wiec nie sprawdzalem jak dokladnie dziala, ale tak patrzac na filmik, bym zrobil jeszcze 2ga, do ktorej bym dodal priorytety celow oraz skupianie sie na celach, bo tak, jak ComAttackUnit troszke sie gubia i dzialaja chaotycznie jedynie atakujac w drodze do celu :P. By mozna zrobic tak, by otaczaly konkretne wybrane cele priorytetowe w kodzie (wg waznosci celu) i na nich sie skupialy, by w drodze do okreslonego miejsca najpierw zniszczyc cele priorytetowe lub cele blokujace do nich dostep, a dopiero pozniej szly dalej. Moglaby z tego fajna funkcja wyjsc pod AI :).
Last edited by zoNE on Sat Aug 12, 2017 11:47 pm, edited 3 times in total.
PC MB: MSI Z97-G43 | CPU: Intel Xeon E3-1231v3 3.4GHz + Raijintek EreBoss | RAM: HyperX 2x8GB 1866MHz DDR3 CL9 | GPU: MSI GeForce GTX 970 100ME 4GB GDDR5 (256bit) | SSD: Crucial BX100 250GB | HDD: 4TB | LCD: EIZO FlexScan 22" S2243W Black | AUDIO: Asus Xonar D2 + KODA DRA-660 + KODA AV-701 + SW-550 v2 + Sennheiser HD 595 | OS: Windows 10 Pro
Laptop DELL Precision M6500 CPU: i5-520M RAM: 8GB DDR3 SSD: 128GB HDD: 500GB GPU: ATI FirePro M7740 1GB DDR5 OS: Windows 7 Ultimate 64-bit

User avatar

MarkedOne
Soldier level 5
Soldier level 5
Posts: 281
Joined: Wed Aug 17, 2011 12:36 pm
Location: Киев/Ольштын/Вроцлав

Re: Sail: Podwójny Laser

#3

Post by MarkedOne » Sun Aug 13, 2017 10:15 pm

Świetnie to wygląda, a wyglądałoby jeszcze lepiej z poprawkami, które napisał zoNE. :D
Gratulacje odd1
Завтра забудешь, что тебя короновал, что душу цветущую любовью выжег
И суетных дней взметенный карнавал растреплет страницы моих книжек
Слов моих сухие листья ли заставят остановиться, жадно дыша
Дай хоть последней нежностью выстелить твой уходящий шаг)

User avatar

Topic author
0dd1
ArCamp Developer
Posts: 225
Joined: Tue Jul 01, 2014 3:01 pm

Re: Sail: Podwójny Laser

#4

Post by 0dd1 » Mon Aug 14, 2017 5:45 pm

Lasery się gubią przy ataku bo wszystko jest w ciągłym ruchu, a nie ma prostego sposobu aby sprawdzić jak "dostępny" jest cel, poza porównywaniem odległości w prostej linii. Teraz to trochę usprawniłem i jest odrobinę stabilniej ale wciąż potrafią zachowywać się dziwnie.

Priorytety celów to raczej indywidualna kwestia, to trzeba dopasować do konkretnej sytuacji. Po to funkcja jest tak napisana żeby mogła poradzić sobie z każdą ilością jednostek, żeby można było samemu wybrać lasery i ich cele. Na przykład na filmiku widać jak atakują bazę z Am14. Tam specjalnie ustawiłem żeby najpierw atakowali wieżyczki, a dopiero potem inne jednostki. Dodatkowo funkcja celowo była użyta tylko na jednym celu naraz, aby lasery skupiły swój atak. Normalnie lepiej jest jak każda para ma osobny cel, ale tutaj miały utrudnione zadanie i w tym trybie o wiele szybciej by zostały zniszczone.

A co do samego AI, to już stworzyłem coś takiego w misji 13 Arabskiej Kampanii. Właściwie cała misja polega na tym że jednostki wroga spawnują się, jadą po wytyczonej ścieżce w górę mapy, i atakują jednostki gracza które zobaczą, a jak te zostaną zniszczone albo im uciekną, to jadą dalej. Teraz zastosowałem to samo w ostatniej misji, gdzie bazy wroga wysyłają co jakiś czas oddział na patrol po mapie, a funkcja ataku laserów powstała właśnie po to żeby AI mogło użyć podwójnych laserów przeciw graczowi.

User avatar

zoNE
The Great Uniter & Site Administrator
The Great Uniter & Site Administrator
Posts: 1159
Joined: Fri Feb 17, 2006 3:44 pm
Location: Poland
Contact:

Re: Sail: Podwójny Laser

#5

Post by zoNE » Mon Aug 14, 2017 6:29 pm

Ogolnie fajna funkcja, w grze czegos takiego wlasnie brakowalo - praktycznego wykorzystania DL przez komputer.
PC MB: MSI Z97-G43 | CPU: Intel Xeon E3-1231v3 3.4GHz + Raijintek EreBoss | RAM: HyperX 2x8GB 1866MHz DDR3 CL9 | GPU: MSI GeForce GTX 970 100ME 4GB GDDR5 (256bit) | SSD: Crucial BX100 250GB | HDD: 4TB | LCD: EIZO FlexScan 22" S2243W Black | AUDIO: Asus Xonar D2 + KODA DRA-660 + KODA AV-701 + SW-550 v2 + Sennheiser HD 595 | OS: Windows 10 Pro
Laptop DELL Precision M6500 CPU: i5-520M RAM: 8GB DDR3 SSD: 128GB HDD: 500GB GPU: ATI FirePro M7740 1GB DDR5 OS: Windows 7 Ultimate 64-bit

User avatar

Serpent
Soldier level 10
Soldier level 10
Posts: 3886
Joined: Tue Jul 07, 2009 9:13 pm
Location: Polska - EuroStan ZSRE
Contact:

Re: Sail: Podwójny Laser

#6

Post by Serpent » Wed Sep 20, 2017 8:24 am

Mała uwaga:
Podanie Area przy użyciu funkcji jest opcjonalne - oznacza obszar do którego lasery mają NIE wchodzić, czyli niedostępne hexy jak strome zbocza albo głęboka woda. Nie da się tego określić z poziomu Saila, jedyny sposób to ręczne zaznaczenie wszystkich takich hexów na mapie.
Ostatnio poprosiłem Stukacza który dodał funkcję sprawdzającą hex'a pod kątem jego właściwości. Myślę że można jej użyć w tym kodzie zamiast wyznaczać aree z góry :)
Epickie teksty:
Marek1906: jak zrobic aby sail był zielony?
Kvantovy: Wszystko normalne, wszystko w koło było dziwne
Kvantovy:: To jest fajne, że to nie jest takie głupie
Kvantovy:: remove sos from kanapeczka
Kvantovy:: zdarzają się rzezy które sie filozofom nie śniły
Cenwen: problemem jest gejostwo

User avatar

Topic author
0dd1
ArCamp Developer
Posts: 225
Joined: Tue Jul 01, 2014 3:01 pm

Re: Sail: Podwójny Laser

#7

Post by 0dd1 » Sun Feb 11, 2018 2:36 pm

W końcu się za to wziąłem. Teraz funkcja sama może zignorować niedostępne hexy ale i tak zostawiłem to Area. W niektórych sytuacjach może się przydać bo nie ma się innej kontroli nad tym gdzie lasery dokładnie pojadą.

Wypadałoby też uaktualnić to co jest w archiwum.

User avatar

zoNE
The Great Uniter & Site Administrator
The Great Uniter & Site Administrator
Posts: 1159
Joined: Fri Feb 17, 2006 3:44 pm
Location: Poland
Contact:

Re: Sail: Podwójny Laser

#8

Post by zoNE » Sun Feb 11, 2018 5:18 pm

Zaktualizowane
PC MB: MSI Z97-G43 | CPU: Intel Xeon E3-1231v3 3.4GHz + Raijintek EreBoss | RAM: HyperX 2x8GB 1866MHz DDR3 CL9 | GPU: MSI GeForce GTX 970 100ME 4GB GDDR5 (256bit) | SSD: Crucial BX100 250GB | HDD: 4TB | LCD: EIZO FlexScan 22" S2243W Black | AUDIO: Asus Xonar D2 + KODA DRA-660 + KODA AV-701 + SW-550 v2 + Sennheiser HD 595 | OS: Windows 10 Pro
Laptop DELL Precision M6500 CPU: i5-520M RAM: 8GB DDR3 SSD: 128GB HDD: 500GB GPU: ATI FirePro M7740 1GB DDR5 OS: Windows 7 Ultimate 64-bit

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest