Author: 0dd10dd1 hat geschrieben: ↑Sa 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: Alles auswählen
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: Alles auswählen
every 0$1 do begin DoubleLaserAttack(BlueTeam, RedTeam, area); enable; end;
Topic: https://forum.original-war.net/viewtopi ... 51&p=53183