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.
Kod: Zaznacz cały
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:
Kod: Zaznacz cały
every 0$1 do
begin
DoubleLaserAttack(BlueTeam, RedTeam, area);
enable;
end;