00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039
00040 #include "stratagus.h"
00041 #include "unittype.h"
00042 #include "player.h"
00043 #include "unit.h"
00044 #include "unit_manager.h"
00045 #include "unit_cache.h"
00046 #include "interface.h"
00047 #include "map.h"
00048 #include "ui.h"
00049 #include "commands.h"
00050 #include "network.h"
00051 #include "iolib.h"
00052
00053 #include "script.h"
00054
00055
00056
00057
00058
00059 int NumSelected;
00060 int TeamNumSelected[PlayerMax];
00061 int MaxSelectable;
00062 CUnit **Selected;
00063 CUnit **TeamSelected[PlayerMax];
00064
00065 static int _NumSelected;
00066 static int _TeamNumSelected[PlayerMax];
00067 static CUnit **_Selected;
00068 static CUnit **_TeamSelected[PlayerMax];
00069
00070 static unsigned GroupId;
00071
00072
00073
00074
00075
00079 void SaveSelection(void)
00080 {
00081 int i;
00082 int j;
00083
00084 for (i = 0; i < PlayerMax; ++i) {
00085 _TeamNumSelected[i] = TeamNumSelected[i];
00086 for (j = 0; j < TeamNumSelected[i]; ++j) {
00087 _TeamSelected[i][j] = TeamSelected[i][j];
00088 }
00089 }
00090 _NumSelected = NumSelected;
00091 for (j = 0; j < NumSelected; ++j) {
00092 _Selected[j] = Selected[j];
00093 }
00094 }
00095
00099 void RestoreSelection(void)
00100 {
00101 int i;
00102 int j;
00103
00104 UnSelectAll();
00105 for (i = 0; i < PlayerMax; ++i) {
00106 TeamNumSelected[i] = _TeamNumSelected[i];
00107 for (j = 0; j < _TeamNumSelected[i]; ++j) {
00108 TeamSelected[i][j] = _TeamSelected[i][j];
00109 TeamSelected[i][j]->TeamSelected |= (1 << i);
00110 }
00111 }
00112 NumSelected = _NumSelected;
00113 for (j = 0; j < _NumSelected; ++j) {
00114 Selected[j] = _Selected[j];
00115 Selected[j]->Selected = 1;
00116 }
00117 }
00118
00122 void UnSelectAll(void)
00123 {
00124 CUnit *unit;
00125
00126 while (!++GroupId) {
00127 }
00128
00129 while (NumSelected) {
00130 unit = Selected[--NumSelected];
00131 Selected[NumSelected] = NoUnitP;
00132 unit->Selected = 0;
00133 }
00134
00135 }
00136
00143 void ChangeSelectedUnits(CUnit **units,int count)
00144 {
00145 CUnit *unit;
00146 int i;
00147 int n;
00148
00149 Assert(count <= MaxSelectable);
00150
00151 UnSelectAll();
00152 NetworkSendSelection(units, count);
00153 for (n = i = 0; i < count; ++i) {
00154 if (!units[i]->Removed && !units[i]->TeamSelected && !units[i]->Type->IsNotSelectable) {
00155 Selected[n++] = unit = units[i];
00156 unit->Selected = 1;
00157 if (count > 1) {
00158 unit->LastGroup = GroupId;
00159 }
00160 }
00161 }
00162 NumSelected = n;
00163 }
00164
00173 void ChangeTeamSelectedUnits(CPlayer *player, CUnit **units, int adjust, int count)
00174 {
00175 int i;
00176 int n;
00177 CUnit *unit;
00178
00179 switch (adjust) {
00180 case 0:
00181
00182 while (TeamNumSelected[player->Index]) {
00183 unit = TeamSelected[player->Index][--TeamNumSelected[player->Index]];
00184 unit->TeamSelected &= ~(1 << player->Index);
00185 TeamSelected[player->Index][TeamNumSelected[player->Index]] = NoUnitP;
00186 }
00187
00188 case 2:
00189 for (i = 0; i < count; ++i) {
00190 Assert(!units[i]->Removed);
00191 if (!units[i]->Type->IsNotSelectable) {
00192 TeamSelected[player->Index][TeamNumSelected[player->Index]++] = units[i];
00193 units[i]->TeamSelected |= 1 << player->Index;
00194 }
00195 }
00196 Assert(TeamNumSelected[player->Index] <= MaxSelectable);
00197 break;
00198 case 1:
00199 for (n = 0; n < TeamNumSelected[player->Index]; ++n) {
00200 for (i = 0; i < count; ++i) {
00201 if (units[i] == TeamSelected[player->Index][n]) {
00202 TeamSelected[player->Index][n] =
00203 TeamSelected[player->Index][TeamNumSelected[player->Index]--];
00204 }
00205 }
00206 }
00207 Assert(TeamNumSelected[player->Index] >= 0);
00208 break;
00209 default:
00210 Assert(0);
00211 }
00212 }
00213
00223 int SelectUnit(CUnit *unit)
00224 {
00225 if (unit->Type->Revealer) {
00226 DebugPrint("Selecting revealer?\n");
00227 return 0;
00228 }
00229
00230 if (unit->Removed) {
00231 DebugPrint("Selecting removed?\n");
00232 return 0;
00233 }
00234
00235 if (NumSelected == MaxSelectable) {
00236 return 0;
00237 }
00238
00239 if (unit->Selected) {
00240 return 0;
00241 }
00242
00243 if (unit->Type->IsNotSelectable && GameRunning) {
00244 return 0;
00245 }
00246
00247 Selected[NumSelected++] = unit;
00248 unit->Selected = 1;
00249 if (NumSelected > 1) {
00250 Selected[0]->LastGroup = unit->LastGroup = GroupId;
00251 }
00252 return 1;
00253 }
00254
00260 void SelectSingleUnit(CUnit *unit)
00261 {
00262 ChangeSelectedUnits(&unit, 1);
00263 }
00264
00270 void UnSelectUnit(CUnit *unit)
00271 {
00272 int i;
00273 int j;
00274
00275 if (unit->TeamSelected) {
00276 for (i = 0; i < PlayerMax; ++i) {
00277 if (unit->TeamSelected & (1 << i)) {
00278 for (j = 0; TeamSelected[i][j] != unit; ++i) {
00279 ;
00280 }
00281 Assert(j < TeamNumSelected[i]);
00282
00283 if (j < --TeamNumSelected[i]) {
00284
00285 TeamSelected[i][j] = TeamSelected[i][TeamNumSelected[i]];
00286 }
00287 unit->TeamSelected &= ~(1 << i);
00288 }
00289 }
00290 }
00291 if (!unit->Selected) {
00292 return;
00293 }
00294
00295 for (i = 0; Selected[i] != unit; ++i) {
00296 ;
00297 }
00298 Assert(i < NumSelected);
00299
00300 if (i < --NumSelected) {
00301 Selected[i] = Selected[NumSelected];
00302 }
00303
00304 if (NumSelected > 1) {
00305 while (!++GroupId) {
00306 }
00307 for (i = 0; i < NumSelected; ++i) {
00308 Selected[i]->LastGroup = GroupId;
00309 }
00310 }
00311
00312 Selected[NumSelected] = NoUnitP;
00313 unit->Selected = 0;
00314 }
00315
00322 int ToggleSelectUnit(CUnit *unit)
00323 {
00324 if (unit->Selected) {
00325 UnSelectUnit(unit);
00326 return 0;
00327 }
00328 SelectUnit(unit);
00329 return 1;
00330 }
00331
00346 int SelectUnitsByType(CUnit *base)
00347 {
00348 CUnit *unit;
00349 CUnit *table[UnitMax];
00350 const CUnitType *type;
00351 int r;
00352 int i;
00353 const CViewport *vp;
00354
00355 Assert(UI.MouseViewport);
00356
00357 type = base->Type;
00358
00359
00360
00361
00362
00363 vp = UI.MouseViewport;
00364 r = UnitCache.Select(vp->MapX - 1, vp->MapY - 1, vp->MapX + vp->MapWidth + 1,
00365 vp->MapY + vp->MapHeight + 1, table, UnitMax);
00366
00367
00368
00369 if (base->Removed || base->Orders[0]->Action == UnitActionDie) {
00370 return 0;
00371 }
00372
00373 if (base->Type->IsNotSelectable && GameRunning) {
00374 return 0;
00375 }
00376 if (base->TeamSelected) {
00377 return 0;
00378 }
00379
00380 UnSelectAll();
00381 Selected[0] = base;
00382 base->Selected = 1;
00383 NumSelected = 1;
00384
00385
00386
00387 if (!CanSelectMultipleUnits(base->Player) || !type->SelectableByRectangle) {
00388 return NumSelected;
00389 }
00390
00391
00392
00393
00394
00395
00396 for (i = 0; i < r; ++i) {
00397 unit = table[i];
00398 if (!CanSelectMultipleUnits(unit->Player) || unit->Type != type) {
00399 continue;
00400 }
00401 if (unit->IsUnusable()) {
00402 continue;
00403 }
00404 if (unit == base) {
00405 continue;
00406 }
00407 if (unit->TeamSelected) {
00408 continue;
00409 }
00410 Selected[NumSelected++] = unit;
00411 unit->Selected = 1;
00412 if (NumSelected == MaxSelectable) {
00413 break;
00414 }
00415 }
00416
00417 if (NumSelected > 1) {
00418 for (i = 0; i < NumSelected; ++i) {
00419 Selected[i]->LastGroup = GroupId;
00420 }
00421 }
00422
00423 NetworkSendSelection(Selected, NumSelected);
00424 return NumSelected;
00425 }
00426
00440 int ToggleUnitsByType(CUnit *base)
00441 {
00442 CUnit *unit;
00443 CUnit *table[UnitMax];
00444 const CUnitType *type;
00445 int r;
00446 int i;
00447
00448 type = base->Type;
00449
00450
00451
00452
00453
00454 r = UnitCache.Select(UI.MouseViewport->MapX - 1,
00455 UI.MouseViewport->MapY - 1,
00456 UI.MouseViewport->MapX + UI.MouseViewport->MapWidth + 1,
00457 UI.MouseViewport->MapY + UI.MouseViewport->MapHeight + 1, table, UnitMax);
00458
00459
00460
00461 if (base->Removed || base->Orders[0]->Action == UnitActionDie) {
00462 return 0;
00463 }
00464
00465
00466 if (!CanSelectMultipleUnits(base->Player) || !type->SelectableByRectangle) {
00467 return 0;
00468 }
00469
00470 if (!SelectUnit(base)) {
00471 return 0;
00472 }
00473
00474
00475
00476
00477
00478 for (i = 0; i < r; ++i) {
00479 unit = table[i];
00480 if (!CanSelectMultipleUnits(unit->Player) || unit->Type != type) {
00481 continue;
00482 }
00483 if (unit->IsUnusable()) {
00484 continue;
00485 }
00486 if (unit == base) {
00487 continue;
00488 }
00489 if (unit->TeamSelected) {
00490 continue;
00491 }
00492 if (!SelectUnit(unit)) {
00493 return NumSelected;
00494 }
00495 }
00496
00497 NetworkSendSelection(Selected, NumSelected);
00498 return NumSelected;
00499 }
00500
00509 int SelectGroup(int group_number)
00510 {
00511 int nunits;
00512
00513 Assert(group_number <= NUM_GROUPS);
00514
00515 if (!(nunits = GetNumberUnitsOfGroup(group_number))) {
00516 return 0;
00517 }
00518
00519 ChangeSelectedUnits(GetUnitsOfGroup(group_number), nunits);
00520 return NumSelected;
00521 }
00522
00531 int AddGroupFromUnitToSelection(CUnit *unit)
00532 {
00533 int i;
00534 int group;
00535
00536 if (!(group = unit->LastGroup)) {
00537 return 0;
00538 }
00539
00540 for (i = 0; i < NumUnits; ++i) {
00541 if (Units[i]->LastGroup == group && !Units[i]->Removed) {
00542 SelectUnit(Units[i]);
00543 if (NumSelected == MaxSelectable) {
00544 return NumSelected;
00545 }
00546 }
00547 }
00548 return NumSelected;
00549 }
00550
00561 int SelectGroupFromUnit(CUnit *unit)
00562 {
00563 if (!unit->LastGroup) {
00564 return 0;
00565 }
00566
00567 UnSelectAll();
00568 return AddGroupFromUnitToSelection(unit);
00569 }
00570
00581 static int SelectOrganicUnitsInTable(CUnit **table, int num_units)
00582 {
00583 CUnit *unit;
00584 int n;
00585 int i;
00586
00587 for (n = i = 0; i < num_units; ++i) {
00588 unit = table[i];
00589 if (!CanSelectMultipleUnits(unit->Player) || !unit->Type->SelectableByRectangle) {
00590 continue;
00591 }
00592 if (unit->IsUnusable()) {
00593 continue;
00594 }
00595 if (unit->TeamSelected) {
00596 continue;
00597 }
00598 table[n++] = unit;
00599 if (n == MaxSelectable) {
00600 break;
00601 }
00602 }
00603 return n;
00604 }
00605
00621 static int SelectSpritesInsideRectangle (int sx0, int sy0, int sx1, int sy1,
00622 CUnit **table, int num_units)
00623 {
00624 int n;
00625 int i;
00626
00627 for (i = n = 0; i < num_units; ++i) {
00628 int sprite_x;
00629 int sprite_y;
00630 CUnit *unit;
00631 const CUnitType *type;
00632
00633 unit = table[i];
00634 type = unit->Type;
00635 sprite_x = unit->X * TileSizeX + unit->IX;
00636 sprite_x -= (type->BoxWidth - TileSizeX * type->TileWidth) / 2;
00637 sprite_x += type->OffsetX;
00638 sprite_y = unit->Y * TileSizeY + unit->IY;
00639 sprite_y -= (type->BoxHeight - TileSizeY * type->TileHeight) / 2;
00640 sprite_y += type->OffsetY;
00641 if (sprite_x + type->BoxWidth < sx0) {
00642 continue;
00643 }
00644 if (sprite_x > sx1) {
00645 continue;
00646 }
00647 if (sprite_y + type->BoxHeight < sy0) {
00648 continue;
00649 }
00650 if (sprite_y > sy1) {
00651 continue;
00652 }
00653 table[n++] = unit;
00654 }
00655 return n;
00656 }
00657
00668 int AddSelectedUnitsInRectangle(int x0, int y0, int x1, int y1)
00669 {
00670 CUnit *table[UnitMax];
00671 int toggle_num;
00672 int n;
00673 int i;
00674
00675
00676 if (!NumSelected) {
00677 return SelectUnitsInRectangle(x0, y0, x1, y1);
00678 }
00679
00680
00681
00682
00683 if (NumSelected == 1 &&
00684 (!CanSelectMultipleUnits(Selected[0]->Player) ||
00685 !Selected[0]->Type->SelectableByRectangle)) {
00686 return NumSelected;
00687 }
00688
00689
00690 toggle_num = UnitCache.Select((x0 / TileSizeX) - 2, (y0 / TileSizeY) - 2,
00691 (x1 / TileSizeX) + 2 + 1, (y1 / TileSizeX) + 2 + 1, table, UnitMax);
00692 if (!toggle_num) {
00693 return NumSelected;
00694 }
00695 toggle_num = SelectSpritesInsideRectangle(x0, y0, x1, y1, table, toggle_num);
00696 if (!toggle_num) {
00697 return NumSelected;
00698 }
00699
00700
00701
00702 if (!(n = SelectOrganicUnitsInTable(table, toggle_num))) {
00703 return NumSelected;
00704 }
00705
00706 for (i = 0; i < n && NumSelected < MaxSelectable; ++i) {
00707 SelectUnit(table[i]);
00708 }
00709 return NumSelected;
00710 }
00711
00727 int SelectUnitsInRectangle (int sx0, int sy0, int sx1, int sy1)
00728 {
00729 CUnit *unit;
00730 CUnit *table[UnitMax];
00731 CUnitType *type;
00732 int r;
00733 int n;
00734 int i;
00735 int tx0;
00736 int ty0;
00737 int tx1;
00738 int ty1;
00739
00740 tx0 = sx0 / TileSizeX;
00741 ty0 = sy0 / TileSizeY;
00742 tx1 = sx1 / TileSizeX;
00743 ty1 = sy1 / TileSizeY;
00744
00745 r = UnitCache.Select(tx0 - 2, ty0 - 2, tx1 + 2 + 1, ty1 + 2 + 1, table, UnitMax);
00746 r = SelectSpritesInsideRectangle(sx0, sy0, sx1, sy1, table, r);
00747
00748
00749
00750
00751 if ((n = SelectOrganicUnitsInTable(table, r))) {
00752 ChangeSelectedUnits(table, n);
00753 return n;
00754 }
00755
00756
00757
00758
00759 for (i = 0; i < r; ++i) {
00760 unit = table[i];
00761 if (!CanSelectMultipleUnits(unit->Player)) {
00762 continue;
00763 }
00764
00765 if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
00766 SelectSingleUnit(unit);
00767 return 1;
00768 }
00769 }
00770
00771
00772
00773
00774 for (i = 0; i < r; ++i) {
00775 unit = table[i];
00776
00777 if (!unit->IsVisibleInViewport(UI.SelectedViewport)) {
00778 continue;
00779 }
00780 type = unit->Type;
00781
00782 if (type->Building && !unit->IsVisibleOnMap(ThisPlayer)) {
00783 continue;
00784 }
00785 if ((type->CanHarvestFrom && !unit->Removed)) {
00786 SelectSingleUnit(unit);
00787 return 1;
00788 }
00789 }
00790
00791
00792
00793
00794 for (i = 0; i < r; ++i) {
00795 unit = table[i];
00796
00797 if (!unit->IsVisibleInViewport(UI.SelectedViewport)) {
00798 continue;
00799 }
00800
00801 if (unit->Type->Building && !unit->IsVisibleOnMap(ThisPlayer)) {
00802 continue;
00803 }
00804 if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
00805 SelectSingleUnit(unit);
00806 return 1;
00807 }
00808 }
00809
00810 return 0;
00811 }
00812
00823 int SelectGroundUnitsInRectangle(int sx0, int sy0, int sx1, int sy1)
00824 {
00825 CUnit *unit;
00826 CUnit *table[UnitMax];
00827 int r;
00828 int n;
00829 int i;
00830 int tx0;
00831 int ty0;
00832 int tx1;
00833 int ty1;
00834
00835 tx0 = sx0 / TileSizeX;
00836 ty0 = sy0 / TileSizeY;
00837 tx1 = sx1 / TileSizeX;
00838 ty1 = sy1 / TileSizeY;
00839
00840 r = UnitCache.Select(tx0 - 2, ty0 - 2, tx1 + 2 + 1, ty1 + 2 + 1, table, UnitMax);
00841 r = SelectSpritesInsideRectangle(sx0, sy0, sx1, sy1, table, r);
00842
00843 for (n = i = 0; i < r; ++i) {
00844 unit = table[i];
00845 if (!CanSelectMultipleUnits(unit->Player) || !unit->Type->SelectableByRectangle) {
00846 continue;
00847 }
00848 if (unit->IsUnusable()) {
00849 continue;
00850 }
00851 if (unit->Type->UnitType == UnitTypeFly) {
00852 continue;
00853 }
00854 if (unit->TeamSelected) {
00855 continue;
00856 }
00857 table[n++] = unit;
00858 if (n == MaxSelectable) {
00859 break;
00860 }
00861 }
00862 if (n) {
00863 ChangeSelectedUnits(table, n);
00864 }
00865 return n;
00866 }
00867
00878 int SelectAirUnitsInRectangle(int sx0, int sy0, int sx1, int sy1)
00879 {
00880 CUnit *unit;
00881 CUnit *table[UnitMax];
00882 int r;
00883 int n;
00884 int i;
00885 int tx0;
00886 int ty0;
00887 int tx1;
00888 int ty1;
00889
00890 tx0 = sx0 / TileSizeX;
00891 ty0 = sy0 / TileSizeY;
00892 tx1 = sx1 / TileSizeX;
00893 ty1 = sy1 / TileSizeY;
00894
00895 r = UnitCache.Select(tx0 - 2, ty0 - 2, tx1 + 2 + 1, ty1 + 2 + 1, table, UnitMax);
00896 r = SelectSpritesInsideRectangle(sx0, sy0, sx1, sy1, table, r);
00897
00898 for (n = i = 0; i < r; ++i) {
00899 unit = table[i];
00900 if (!CanSelectMultipleUnits(unit->Player) || !unit->Type->SelectableByRectangle) {
00901 continue;
00902 }
00903 if (unit->IsUnusable()) {
00904 continue;
00905 }
00906 if (unit->Type->UnitType != UnitTypeFly) {
00907 continue;
00908 }
00909 if (unit->TeamSelected) {
00910 continue;
00911 }
00912 table[n++] = unit;
00913 if (n == MaxSelectable) {
00914 break;
00915 }
00916 }
00917 if (n) {
00918 ChangeSelectedUnits(table, n);
00919 }
00920 return n;
00921 }
00922
00933 int AddSelectedGroundUnitsInRectangle(int sx0, int sy0, int sx1, int sy1)
00934 {
00935 CUnit *unit;
00936 CUnit *table[UnitMax];
00937 int r;
00938 int n;
00939 int i;
00940 int tx0;
00941 int ty0;
00942 int tx1;
00943 int ty1;
00944
00945
00946 if (!NumSelected) {
00947 return SelectGroundUnitsInRectangle(sx0, sy0, sx1, sy1);
00948 }
00949
00950
00951
00952
00953 if (NumSelected == 1 &&
00954 (!CanSelectMultipleUnits(Selected[0]->Player) ||
00955 !Selected[0]->Type->SelectableByRectangle)) {
00956 return NumSelected;
00957 }
00958
00959 tx0 = sx0 / TileSizeX;
00960 ty0 = sy0 / TileSizeY;
00961 tx1 = sx1 / TileSizeX;
00962 ty1 = sy1 / TileSizeY;
00963
00964 r = UnitCache.Select(tx0 - 2, ty0 - 2, tx1 + 2 + 1, ty1 + 2 + 1, table, UnitMax);
00965 r = SelectSpritesInsideRectangle(sx0, sy0, sx1, sy1, table, r);
00966
00967 for (n = i = 0; i < r; ++i) {
00968 unit = table[i];
00969 if (!CanSelectMultipleUnits(unit->Player) ||
00970 !unit->Type->SelectableByRectangle) {
00971 continue;
00972 }
00973 if (unit->IsUnusable()) {
00974 continue;
00975 }
00976 if (unit->Type->UnitType == UnitTypeFly) {
00977 continue;
00978 }
00979 if (unit->TeamSelected) {
00980 continue;
00981 }
00982 table[n++] = unit;
00983 if (n == MaxSelectable) {
00984 break;
00985 }
00986 }
00987
00988
00989
00990
00991 for (i = 0; i < n && NumSelected < MaxSelectable; ++i) {
00992 SelectUnit(table[i]);
00993 }
00994 return NumSelected;
00995 }
00996
01007 int AddSelectedAirUnitsInRectangle(int sx0, int sy0, int sx1, int sy1)
01008 {
01009 CUnit *unit;
01010 CUnit *table[UnitMax];
01011 int r;
01012 int n;
01013 int i;
01014 int tx0;
01015 int ty0;
01016 int tx1;
01017 int ty1;
01018
01019
01020 if (!NumSelected) {
01021 return SelectAirUnitsInRectangle(sx0, sy0, sx1, sy1);
01022 }
01023
01024
01025
01026
01027 if (NumSelected == 1 &&
01028 (!CanSelectMultipleUnits(Selected[0]->Player) ||
01029 !Selected[0]->Type->SelectableByRectangle)) {
01030 return NumSelected;
01031 }
01032
01033 tx0 = sx0 / TileSizeX;
01034 ty0 = sy0 / TileSizeY;
01035 tx1 = sx1 / TileSizeX;
01036 ty1 = sy1 / TileSizeY;
01037
01038 r = UnitCache.Select(tx0 - 2, ty0 - 2, tx1 + 2 + 1, ty1 + 2 + 1, table, UnitMax);
01039 r = SelectSpritesInsideRectangle(sx0, sy0, sx1, sy1, table, r);
01040
01041 for (n = i = 0; i < r; ++i) {
01042 unit = table[i];
01043 if (!CanSelectMultipleUnits(unit->Player) ||
01044 !unit->Type->SelectableByRectangle) {
01045 continue;
01046 }
01047 if (unit->IsUnusable()) {
01048 continue;
01049 }
01050 if (unit->Type->UnitType != UnitTypeFly) {
01051 continue;
01052 }
01053 if (unit->TeamSelected) {
01054 continue;
01055 }
01056 table[n++] = unit;
01057 if (n == MaxSelectable) {
01058 break;
01059 }
01060 }
01061
01062
01063
01064
01065 for (i = 0; i < n && NumSelected < MaxSelectable; ++i) {
01066 SelectUnit(table[i]);
01067 }
01068 return NumSelected;
01069 }
01070
01074 void InitSelections(void)
01075 {
01076
01077 if (!Selected) {
01078 Selected = new CUnit *[MaxSelectable];
01079 _Selected = new CUnit *[MaxSelectable];
01080 }
01081 for (int i = 0; i < PlayerMax; ++i) {
01082 if (!TeamSelected[i]) {
01083 TeamSelected[i] = new CUnit *[MaxSelectable];
01084 _TeamSelected[i] = new CUnit *[MaxSelectable];
01085 }
01086 }
01087 }
01088
01094 void SaveSelections(CFile *file)
01095 {
01096 file->printf("\n--- -----------------------------------------\n");
01097 file->printf("--- MODULE: selection\n\n");
01098
01099 file->printf("SetGroupId(%d)\n", GroupId);
01100 file->printf("Selection(%d, {", NumSelected);
01101 for (int i = 0; i < NumSelected; ++i) {
01102 file->printf("\"%s\", ", UnitReference(Selected[i]).c_str());
01103 }
01104 file->printf("})\n");
01105 }
01106
01110 void CleanSelections(void)
01111 {
01112 GroupId = 0;
01113 NumSelected = 0;
01114 delete[] Selected;
01115 Selected = NULL;
01116 delete[] _Selected;
01117 _Selected = NULL;
01118
01119 for (int i = 0; i < PlayerMax; ++i) {
01120 delete[] TeamSelected[i];
01121 TeamSelected[i] = NULL;
01122 delete[] _TeamSelected[i];
01123 _TeamSelected[i] = NULL;
01124 TeamNumSelected[i] = 0;
01125 _TeamNumSelected[i] = 0;
01126 }
01127 }
01128
01129
01130
01136 static int CclSetGroupId(lua_State *l)
01137 {
01138 int old;
01139
01140 LuaCheckArgs(l, 1);
01141 old = GroupId;
01142 GroupId = LuaToNumber(l, 1);
01143
01144 lua_pushnumber(l, old);
01145 return 1;
01146 }
01147
01153 static int CclSelection(lua_State *l)
01154 {
01155 int i;
01156 int args;
01157 int j;
01158
01159 LuaCheckArgs(l, 2);
01160 if (!lua_istable(l, 2)) {
01161 LuaError(l, "incorrect argument");
01162 }
01163 InitSelections();
01164 NumSelected = LuaToNumber(l, 1);
01165 i = 0;
01166 args = lua_objlen(l, 2);
01167 for (j = 0; j < args; ++j) {
01168 const char *str;
01169
01170 lua_rawgeti(l, 2, j + 1);
01171 str = LuaToString(l, -1);
01172 lua_pop(l, 1);
01173 Selected[i++] = UnitSlots[strtol(str + 1, NULL, 16)];
01174 }
01175
01176 return 0;
01177 }
01178
01182 void SelectionCclRegister(void)
01183 {
01184 lua_register(Lua, "SetGroupId", CclSetGroupId);
01185 lua_register(Lua, "Selection", CclSelection);
01186 }
01187