Here's a function that is meant to work like ComAttackunit, but for a double laser to use their special attack.
LaserList - List of double laser units. AllTargets - List of enemies. Area - optional, double lasers will not go in that area. Could be of use because there's no other control of the lasers movements. val - Defines preferred distance. At 0 they will surround the target as tightly as possible, 1 is middle distance (most reasonable), at 2 they will spread out as much as possible (may have trouble hitting human units).
The function automatically pairs up the lasers and assigns them to separate targets.
Note that it should be used continuously, unlike normal command function.
Code:
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;
if Lasers < 2 then begin ComAttackUnit(Lasers, AllTargets[1]); //Same for a single laser exit; end else begin LaserGroups = [];
//Pair up the lasers. If there's one left it will just do the same as laser2 in the last pair 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;
//For any given target (T), assume a set of relative hexes forming circles around it. There are 7 hexes going away from the target (2 hexes appart from each other) in 12 different directions //Dir0 here is the same as direction 0 in editor, Dir1 is between directions 0 and 1 in editor, Dir2 corresponds to direction 1 in editor and so on // * * * * * // * * * * * // ***** // * * * T * * * // ***** // * * * * * // * * * * *
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;
//Pick the closest target for a given pair. 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;
//A small threshhold (+3 here) is necessary to prevent them from switching to another target as soon as they move slightly toward one 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 = [];
//Pick the first available hex from each direction, to form a single circle around the target //Check them in pairs - if a given direction doesn't have a single hex available, then the opposite of it is also disregerded for i = 1 to 6 do begin hex1 = []; hex2 = [];
//Prioritize the closest, middle distance or the farthest hexes, as chosen on the top 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;
//Available hex is: A valid empty hex, not in the forbidden area, not a red slope or a terrain of: 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 picked break; end;
if hex1 = [] then continue;
//Repeat the same process for the opposite direction 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;
//These two sets compose a single circle of hexes around the target hex_list1 = Replace(hex_list1, i, hex1); hex_list2 = Replace(hex_list2, i, hex2); end;
//If no available hexes found at all (unlikely), simply move toward the target and hope for the best if (hex_list1 diff 0) = 0 then begin ComMoveUnit(un, Target); exit; end;
//Two sets of the same hexes (just opposite order) for convenience. One for each laser. 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];
//Select the closest pair of hexes to the lasers, from the determined circle //So later on the distances from all other hexes can be measured in correct order 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 attack modes: 1- If any laser is away from it's hex, then move just toward that pair of hexes // 2- If both are already in place, move simultaneously to the next hexes in the circle. Staying on the move may help them dodge enemy missiles for i in temp_list do begin if hex_list1[i] = [] then continue;
hex1 = hex_list1[i]; hex2 = hex_list2[i];
//Try to assign a laser to its closer hex of the two 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;
//Attack 2: select the next 3 hexes in the circle for the lasers, to keep them moving 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;
//Attack 1: picking the closest pair of hexes if (temp + [6,8,10][val+1]) < dist then begin dist = temp; choosen_hexes = [hex1, hex2]; end; end;
//If there's an 0dd 1 out it will just do the same as laser2 in the pair if un > 2 then L2 = L2 ^ un[3];
//If no available hexes found at all (unlikely), simply move toward the target and hope for the best if choosen_hexes[1] = [] then begin ComMoveUnit([L1,L2], Target); exit; end;
//And finally, the command to move through all selected hexes 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;
Below is a small presentation, of a bit older version (it's just been tweaked a bit since then). In case of the simplest situations, the attack code was literally something like this:
Code:
every 0$1 do begin DoubleLaserAttack(BlueTeam, RedTeam, 0, 1); enable; end;
Users browsing this forum: No registered users and 1 guest
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum