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
00030
00031
00032
00033
00034
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038
00039 #include "stratagus.h"
00040 #include "unit.h"
00041 #include "unit_manager.h"
00042 #include "unit_cache.h"
00043 #include "unittype.h"
00044 #include "animation.h"
00045 #include "upgrade.h"
00046 #include "player.h"
00047 #include "script.h"
00048 #include "spells.h"
00049 #include "pathfinder.h"
00050 #include "map.h"
00051 #include "trigger.h"
00052 #include "actions.h"
00053 #include "construct.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00064 extern unsigned CclGetResourceByName(lua_State *l);
00065
00073 static int CclSetBuildingCapture(lua_State *l)
00074 {
00075 LuaCheckArgs(l, 1);
00076 EnableBuildingCapture = LuaToBoolean(l, 1);
00077 return 0;
00078 }
00079
00087 static CUnit *CclGetUnit(lua_State *l)
00088 {
00089 return UnitSlots[(int)LuaToNumber(l, -1)];
00090 }
00091
00098 void CclParseOrder(lua_State *l, COrder *order)
00099 {
00100 const char *value;
00101 int args;
00102 int j;
00103
00104
00105
00106
00107 args = lua_objlen(l, -1);
00108 for (j = 0; j < args; ++j) {
00109 lua_rawgeti(l, -1, j + 1);
00110 value = LuaToString(l, -1);
00111 lua_pop(l, 1);
00112 if (!strcmp(value, "action-none")) {
00113 order->Action = UnitActionNone;
00114 } else if (!strcmp(value, "action-still")) {
00115 order->Action = UnitActionStill;
00116 } else if (!strcmp(value, "action-stand-ground")) {
00117 order->Action = UnitActionStandGround;
00118 } else if (!strcmp(value, "action-follow")) {
00119 order->Action = UnitActionFollow;
00120 } else if (!strcmp(value, "action-move")) {
00121 order->Action = UnitActionMove;
00122 } else if (!strcmp(value, "action-attack")) {
00123 order->Action = UnitActionAttack;
00124 } else if (!strcmp(value, "action-attack-ground")) {
00125 order->Action = UnitActionAttackGround;
00126 } else if (!strcmp(value, "action-die")) {
00127 order->Action = UnitActionDie;
00128 } else if (!strcmp(value, "action-spell-cast")) {
00129 order->Action = UnitActionSpellCast;
00130 } else if (!strcmp(value, "action-train")) {
00131 order->Action = UnitActionTrain;
00132 } else if (!strcmp(value, "action-built")) {
00133 order->Action = UnitActionBuilt;
00134 } else if (!strcmp(value, "action-board")) {
00135 order->Action = UnitActionBoard;
00136 } else if (!strcmp(value, "action-unload")) {
00137 order->Action = UnitActionUnload;
00138 } else if (!strcmp(value, "action-patrol")) {
00139 order->Action = UnitActionPatrol;
00140 } else if (!strcmp(value, "action-build")) {
00141 order->Action = UnitActionBuild;
00142 } else if (!strcmp(value, "action-repair")) {
00143 order->Action = UnitActionRepair;
00144 } else if (!strcmp(value, "action-resource")) {
00145 order->Action = UnitActionResource;
00146 } else if (!strcmp(value, "range")) {
00147 ++j;
00148 lua_rawgeti(l, -1, j + 1);
00149 order->Range = LuaToNumber(l, -1);
00150 lua_pop(l, 1);
00151 } else if (!strcmp(value, "min-range")) {
00152 ++j;
00153 lua_rawgeti(l, -1, j + 1);
00154 order->MinRange = LuaToNumber(l, -1);
00155 lua_pop(l, 1);
00156 } else if (!strcmp(value, "width")) {
00157 ++j;
00158 lua_rawgeti(l, -1, j + 1);
00159 order->Width = LuaToNumber(l, -1);
00160 lua_pop(l, 1);
00161 } else if (!strcmp(value, "height")) {
00162 ++j;
00163 lua_rawgeti(l, -1, j + 1);
00164 order->Height = LuaToNumber(l, -1);
00165 lua_pop(l, 1);
00166 } else if (!strcmp(value, "goal")) {
00167 int slot;
00168
00169 ++j;
00170 lua_rawgeti(l, -1, j + 1);
00171 value = LuaToString(l, -1);
00172 lua_pop(l, 1);
00173
00174 slot = strtol(value + 1, NULL, 16);
00175 order->Goal = UnitSlots[slot];
00176 if (!UnitSlots[slot]) {
00177 DebugPrint("FIXME: Forward reference not supported\n");
00178 }
00179
00180
00181 } else if (!strcmp(value, "tile")) {
00182 ++j;
00183 lua_rawgeti(l, -1, j + 1);
00184 if (!lua_istable(l, -1) || lua_objlen(l, -1) != 2) {
00185 LuaError(l, "incorrect argument");
00186 }
00187 lua_rawgeti(l, -1, 1);
00188 order->X = LuaToNumber(l, -1);
00189 lua_pop(l, 1);
00190 lua_rawgeti(l, -1, 2);
00191 order->Y = LuaToNumber(l, -1);
00192 lua_pop(l, 1);
00193 lua_pop(l, 1);
00194
00195 } else if (!strcmp(value, "type")) {
00196 ++j;
00197 lua_rawgeti(l, -1, j + 1);
00198 order->Type = UnitTypeByIdent(LuaToString(l, -1));
00199 lua_pop(l, 1);
00200
00201 } else if (!strcmp(value, "patrol")) {
00202 ++j;
00203 lua_rawgeti(l, -1, j + 1);
00204 if (!lua_istable(l, -1) || lua_objlen(l, -1) != 2) {
00205 LuaError(l, "incorrect argument");
00206 }
00207 lua_rawgeti(l, -1, 1);
00208 order->Arg1.Patrol.X = LuaToNumber(l, -1);
00209 lua_pop(l, 1);
00210 lua_rawgeti(l, -1, 2);
00211 order->Arg1.Patrol.Y = LuaToNumber(l, -1);
00212 lua_pop(l, 1);
00213 lua_pop(l, 1);
00214
00215 } else if (!strcmp(value, "spell")) {
00216 ++j;
00217 lua_rawgeti(l, -1, j + 1);
00218 order->Arg1.Spell = SpellTypeByIdent(LuaToString(l, -1));
00219 lua_pop(l, 1);
00220
00221 } else {
00222
00223 LuaError(l, "Unsupported tag: %s" _C_ value);
00224 }
00225 }
00226 }
00227
00234 static void CclParseOrders(lua_State *l, CUnit *unit)
00235 {
00236 for (std::vector<COrder *>::iterator order = unit->Orders.begin();
00237 order != unit->Orders.end();
00238 ++order) {
00239 delete *order;
00240 }
00241 unit->Orders.clear();
00242 for (int j = 0; j < unit->OrderCount; ++j) {
00243 lua_rawgeti(l, -1, j + 1);
00244 unit->Orders.push_back(new COrder);
00245 CclParseOrder(l, unit->Orders[j]);
00246 lua_pop(l, 1);
00247 }
00248 }
00249
00256 static void CclParseBuilt(lua_State *l, CUnit *unit)
00257 {
00258 const char *value;
00259 int args;
00260 int j;
00261
00262 if (!lua_istable(l, -1)) {
00263 LuaError(l, "incorrect argument");
00264 }
00265 args = lua_objlen(l, -1);
00266 for (j = 0; j < args; ++j) {
00267 lua_rawgeti(l, -1, j + 1);
00268 value = LuaToString(l, -1);
00269 lua_pop(l, 1);
00270 ++j;
00271 if (!strcmp(value, "worker")) {
00272 int slot;
00273
00274 lua_rawgeti(l, -1, j + 1);
00275 value = LuaToString(l, -1);
00276 lua_pop(l, 1);
00277 slot = strtol(value + 1, NULL, 16);
00278 Assert(UnitSlots[slot]);
00279 unit->Data.Built.Worker = UnitSlots[slot];
00280
00281 } else if (!strcmp(value, "progress")) {
00282 lua_rawgeti(l, -1, j + 1);
00283 unit->Data.Built.Progress = LuaToNumber(l, -1);
00284 lua_pop(l, 1);
00285 } else if (!strcmp(value, "cancel")) {
00286 unit->Data.Built.Cancel = 1;
00287 --j;
00288 } else if (!strcmp(value, "frame")) {
00289 int frame;
00290 CConstructionFrame *cframe;
00291
00292 lua_rawgeti(l, -1, j + 1);
00293 frame = LuaToNumber(l, -1);
00294 lua_pop(l, 1);
00295 cframe = unit->Type->Construction->Frames;
00296 while (frame--) {
00297 cframe = cframe->Next;
00298 }
00299 unit->Data.Built.Frame = cframe;
00300 } else {
00301 LuaError(l, "Unsupported tag: %s" _C_ value);
00302 }
00303 }
00304 }
00305
00312 static void CclParseTrain(lua_State *l, CUnit *unit)
00313 {
00314 const char *value;
00315 int args;
00316 int j;
00317
00318 if (!lua_istable(l, -1)) {
00319 LuaError(l, "incorrect argument");
00320 }
00321 args = lua_objlen(l, -1);
00322 for (j = 0; j < args; ++j) {
00323 lua_rawgeti(l, -1, j + 1);
00324 value = LuaToString(l, -1);
00325 lua_pop(l, 1);
00326 ++j;
00327 if (!strcmp(value, "ticks")) {
00328 lua_rawgeti(l, -1, j + 1);
00329 unit->Data.Train.Ticks = LuaToNumber(l, -1);
00330 lua_pop(l, 1);
00331 } else {
00332 LuaError(l, "Unsupported tag: %s" _C_ value);
00333 }
00334 }
00335 }
00336
00343 static void CclParseHarvest(lua_State *l, CUnit *unit)
00344 {
00345 const char *value;
00346 int args;
00347 int j;
00348
00349 if (!lua_istable(l, -1)) {
00350 LuaError(l, "incorrect argument");
00351 }
00352 args = lua_objlen(l, -1);
00353 for (j = 0; j < args; ++j) {
00354 lua_rawgeti(l, -1, j + 1);
00355 value = LuaToString(l, -1);
00356 lua_pop(l, 1);
00357 ++j;
00358 if (!strcmp(value, "current-production")) {
00359 lua_rawgeti(l, -1, j + 1);
00360 if (!lua_istable(l, -1) || lua_objlen(l, -1) != MaxCosts) {
00361 LuaError(l, "incorrect argument");
00362 }
00363 for (int i = 0; i < MaxCosts; ++i) {
00364 lua_rawgeti(l, -1, i + 1);
00365 unit->Data.Harvest.CurrentProduction[i] = LuaToNumber(l, -1);
00366 lua_pop(l, 1);
00367 }
00368 lua_pop(l, 1);
00369 } else {
00370 LuaError(l, "Unsupported tag: %s" _C_ value);
00371 }
00372 }
00373 }
00374
00381 static void CclParseMove(lua_State *l, CUnit *unit)
00382 {
00383 const char *value;
00384 int args;
00385 int j;
00386
00387 if (!lua_istable(l, -1)) {
00388 LuaError(l, "incorrect argument");
00389 }
00390 args = lua_objlen(l, -1);
00391 for (j = 0; j < args; ++j) {
00392 lua_rawgeti(l, -1, j + 1);
00393 value = LuaToString(l, -1);
00394 lua_pop(l, 1);
00395 ++j;
00396 if (!strcmp(value, "fast")) {
00397 unit->Data.Move.Fast = 1;
00398 --j;
00399 } else if (!strcmp(value, "path")) {
00400 int subargs;
00401 int k;
00402
00403 lua_rawgeti(l, -1, j + 1);
00404 if (!lua_istable(l, -1)) {
00405 LuaError(l, "incorrect argument");
00406 }
00407 subargs = lua_objlen(l, -1);
00408 for (k = 0; k < subargs; ++k) {
00409 lua_rawgeti(l, -1, k + 1);
00410 unit->Data.Move.Path[k] = LuaToNumber(l, -1);
00411 lua_pop(l, 1);
00412 }
00413 unit->Data.Move.Length = subargs;
00414 lua_pop(l, 1);
00415 } else {
00416 LuaError(l, "Unsupported tag: %s" _C_ value);
00417 }
00418 }
00419 }
00420
00429 static int CclUnit(lua_State *l)
00430 {
00431 const char *value;
00432 CUnit *unit;
00433 CUnitType *type;
00434 CUnitType *seentype;
00435 CPlayer *player;
00436 int slot;
00437 int i;
00438 const char *s;
00439 int args;
00440 int j;
00441
00442 args = lua_gettop(l);
00443 j = 0;
00444
00445 slot = LuaToNumber(l, j + 1);
00446 ++j;
00447
00448 unit = NULL;
00449 type = NULL;
00450 seentype = NULL;
00451 player = NULL;
00452 i = 0;
00453
00454
00455
00456
00457 for (; j < args; ++j) {
00458 value = LuaToString(l, j + 1);
00459 ++j;
00460
00461 if (!strcmp(value, "type")) {
00462 type = UnitTypeByIdent(LuaToString(l, j + 1));
00463 } else if (!strcmp(value, "seen-type")) {
00464 seentype = UnitTypeByIdent(LuaToString(l, j + 1));
00465 } else if (!strcmp(value, "player")) {
00466 player = &Players[(int)LuaToNumber(l, j + 1)];
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 Assert(type);
00479 unit = UnitSlots[slot];
00480 unit->Init(type);
00481 unit->Seen.Type = seentype;
00482 unit->Removed = 0;
00483 Assert(unit->Slot == slot);
00484 } else if (!strcmp(value, "next")) {
00485 unit->Next = UnitSlots[(int)LuaToNumber(l, j + 1)];
00486 } else if (!strcmp(value, "current-sight-range")) {
00487 unit->CurrentSightRange = LuaToNumber(l, j + 1);
00488 } else if (!strcmp(value, "refs")) {
00489 unit->Refs = LuaToNumber(l, j + 1);
00490 } else if (!strcmp(value, "host-info")) {
00491 int x;
00492 int y;
00493 int w;
00494 int h;
00495
00496 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 4) {
00497 LuaError(l, "incorrect argument");
00498 }
00499 lua_rawgeti(l, j + 1, 1);
00500 x = LuaToNumber(l, -1);
00501 lua_pop(l, 1);
00502 lua_rawgeti(l, j + 1, 2);
00503 y = LuaToNumber(l, -1);
00504 lua_pop(l, 1);
00505 lua_rawgeti(l, j + 1, 3);
00506 w = LuaToNumber(l, -1);
00507 lua_pop(l, 1);
00508 lua_rawgeti(l, j + 1, 4);
00509 h = LuaToNumber(l, -1);
00510 lua_pop(l, 1);
00511 MapSight(player, x, y, w, h, unit->CurrentSightRange, MapMarkTileSight);
00512
00513 } else if (!strcmp(value, "tile")) {
00514 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00515 LuaError(l, "incorrect argument");
00516 }
00517 lua_rawgeti(l, j + 1, 1);
00518 unit->X = LuaToNumber(l, -1);
00519 lua_pop(l, 1);
00520 lua_rawgeti(l, j + 1, 2);
00521 unit->Y = LuaToNumber(l, -1);
00522 lua_pop(l, 1);
00523 } else if (!strcmp(value, "seen-tile")) {
00524 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00525 LuaError(l, "incorrect argument");
00526 }
00527 lua_rawgeti(l, j + 1, 1);
00528 unit->Seen.X = LuaToNumber(l, -1);
00529 lua_pop(l, 1);
00530 lua_rawgeti(l, j + 1, 2);
00531 unit->Seen.Y = LuaToNumber(l, -1);
00532 lua_pop(l, 1);
00533 } else if (!strcmp(value, "stats")) {
00534 unit->Stats = &type->Stats[(int)LuaToNumber(l, j + 1)];
00535 } else if (!strcmp(value, "pixel")) {
00536 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00537 LuaError(l, "incorrect argument");
00538 }
00539 lua_rawgeti(l, j + 1, 1);
00540 unit->IX = LuaToNumber(l, -1);
00541 lua_pop(l, 1);
00542 lua_rawgeti(l, j + 1, 2);
00543 unit->IY = LuaToNumber(l, -1);
00544 lua_pop(l, 1);
00545 } else if (!strcmp(value, "seen-pixel")) {
00546 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != 2) {
00547 LuaError(l, "incorrect argument");
00548 }
00549 lua_rawgeti(l, j + 1, 1);
00550 unit->Seen.IX = LuaToNumber(l, -1);
00551 lua_pop(l, 1);
00552 lua_rawgeti(l, j + 1, 2);
00553 unit->Seen.IY = LuaToNumber(l, -1);
00554 lua_pop(l, 1);
00555 } else if (!strcmp(value, "frame")) {
00556 unit->Frame = LuaToNumber(l, j + 1);
00557 } else if (!strcmp(value, "seen")) {
00558 unit->Seen.Frame = LuaToNumber(l, j + 1);
00559 } else if (!strcmp(value, "not-seen")) {
00560 unit->Seen.Frame = UnitNotSeen;
00561 --j;
00562 } else if (!strcmp(value, "direction")) {
00563 unit->Direction = LuaToNumber(l, j + 1);
00564 } else if (!strcmp(value, "attacked")) {
00565
00566 unit->Attacked = LuaToNumber(l, j + 1);
00567 } else if (!strcmp(value, "auto-repair")) {
00568 unit->AutoRepair = 1;
00569 --j;
00570 } else if (!strcmp(value, "burning")) {
00571 unit->Burning = 1;
00572 --j;
00573 } else if (!strcmp(value, "destroyed")) {
00574 unit->Destroyed = 1;
00575 --j;
00576 } else if (!strcmp(value, "removed")) {
00577 unit->Removed = 1;
00578 --j;
00579 } else if (!strcmp(value, "selected")) {
00580 unit->Selected = 1;
00581 --j;
00582 } else if (!strcmp(value, "rescued-from")) {
00583 unit->RescuedFrom = &Players[(int)LuaToNumber(l, j + 1)];
00584 } else if (!strcmp(value, "seen-by-player")) {
00585 s = LuaToString(l, j + 1);
00586 unit->Seen.ByPlayer = 0;
00587 for (i = 0; i < PlayerMax && *s; ++i, ++s) {
00588 if (*s == '-' || *s == '_' || *s == ' ') {
00589 unit->Seen.ByPlayer &= ~(1 << i);
00590 } else {
00591 unit->Seen.ByPlayer |= (1 << i);
00592 }
00593 }
00594 } else if (!strcmp(value, "seen-destroyed")) {
00595 s = LuaToString(l, j + 1);
00596 unit->Seen.Destroyed = 0;
00597 for (i = 0; i < PlayerMax && *s; ++i, ++s) {
00598 if (*s == '-' || *s == '_' || *s == ' ') {
00599 unit->Seen.Destroyed &= ~(1 << i);
00600 } else {
00601 unit->Seen.Destroyed |= (1 << i);
00602 }
00603 }
00604 } else if (!strcmp(value, "constructed")) {
00605 unit->Constructed = 1;
00606 --j;
00607 } else if (!strcmp(value, "seen-constructed")) {
00608 unit->Seen.Constructed = 1;
00609 --j;
00610 } else if (!strcmp(value, "seen-cframe")) {
00611 int frame;
00612 CConstructionFrame *cframe;
00613
00614 frame = LuaToNumber(l, j + 1);
00615 cframe = unit->Seen.Type->Construction->Frames;
00616 while (frame--) {
00617 cframe = cframe->Next;
00618 }
00619 unit->Seen.CFrame = cframe;
00620 } else if (!strcmp(value, "seen-state")) {
00621 unit->Seen.State = LuaToNumber(l, j + 1);
00622 } else if (!strcmp(value, "ttl")) {
00623
00624 unit->TTL = LuaToNumber(l, j + 1);
00625 } else if (!strcmp(value, "group-id")) {
00626 unit->GroupId = LuaToNumber(l, j + 1);
00627 } else if (!strcmp(value, "last-group")) {
00628 unit->LastGroup = LuaToNumber(l, j + 1);
00629 } else if (!strcmp(value, "resources-held")) {
00630 if (!lua_istable(l, j + 1) || lua_objlen(l, j + 1) != MaxCosts) {
00631 LuaError(l, "incorrect argument");
00632 }
00633 for (i = 0; i < MaxCosts; ++i) {
00634 lua_rawgeti(l, j + 1, i + 1);
00635 unit->ResourcesHeld[i] = LuaToNumber(l, -1);
00636 lua_pop(l, 1);
00637 }
00638 } else if (!strcmp(value, "production-efficiency")) {
00639 unit->ProductionEfficiency = LuaToNumber(l, j + 1);
00640 } else if (!strcmp(value, "sub-action")) {
00641 unit->SubAction = LuaToNumber(l, j + 1);
00642 } else if (!strcmp(value, "wait")) {
00643 unit->Wait = LuaToNumber(l, j + 1);
00644 } else if (!strcmp(value, "state")) {
00645 unit->State = LuaToNumber(l, j + 1);
00646 } else if (!strcmp(value, "anim-wait")) {
00647 unit->Anim.Wait = LuaToNumber(l, j + 1);
00648 } else if (!strcmp(value, "curr-anim")) {
00649 unit->Anim.CurrAnim = AnimationsArray[(int)LuaToNumber(l, j + 1)];
00650 } else if (!strcmp(value, "anim")) {
00651 unit->Anim.Anim = unit->Anim.CurrAnim + (int)LuaToNumber(l, j + 1);
00652 } else if (!strcmp(value, "unbreakable")) {
00653 unit->Anim.Unbreakable = 1;
00654 --j;
00655 } else if (!strcmp(value, "blink")) {
00656 unit->Blink = LuaToNumber(l, j + 1);
00657 } else if (!strcmp(value, "moving")) {
00658 unit->Moving = 1;
00659 --j;
00660 } else if (!strcmp(value, "re-cast")) {
00661 unit->ReCast = 1;
00662 --j;
00663 } else if (!strcmp(value, "boarded")) {
00664 unit->Boarded = 1;
00665 --j;
00666 } else if (!strcmp(value, "units-boarded-count")) {
00667 unit->BoardCount = LuaToNumber(l, j + 1);
00668 } else if (!strcmp(value, "units-contained")) {
00669 int subargs;
00670 int k;
00671
00672 if (!lua_istable(l, j + 1)) {
00673 LuaError(l, "incorrect argument");
00674 }
00675 subargs = lua_objlen(l, j + 1);
00676 for (k = 0; k < subargs; ++k) {
00677 lua_rawgeti(l, j + 1, k + 1);
00678 value = LuaToString(l, -1);
00679 lua_pop(l, 1);
00680 slot = strtol(value + 1, NULL, 16);
00681 UnitSlots[slot]->AddInContainer(unit);
00682 Assert(UnitSlots[slot]);
00683
00684 }
00685 } else if (!strcmp(value, "order-count")) {
00686 unit->OrderCount = LuaToNumber(l, j + 1);
00687 } else if (!strcmp(value, "order-flush")) {
00688 unit->OrderFlush = LuaToNumber(l, j + 1);
00689 } else if (!strcmp(value, "orders")) {
00690 lua_pushvalue(l, j + 1);
00691 CclParseOrders(l, unit);
00692 lua_pop(l, 1);
00693
00694 unit->AssignToPlayer (player);
00695 if (unit->Orders[0]->Action == UnitActionBuilt) {
00696 DebugPrint("HACK: the building is not ready yet\n");
00697
00698 unit->Player->UnitTypesCount[type->Slot]--;
00699 }
00700 } else if (!strcmp(value, "saved-order")) {
00701 lua_pushvalue(l, j + 1);
00702 CclParseOrder(l, &unit->SavedOrder);
00703 lua_pop(l, 1);
00704 } else if (!strcmp(value, "new-order")) {
00705 lua_pushvalue(l, j + 1);
00706 CclParseOrder(l, &unit->NewOrder);
00707 lua_pop(l, 1);
00708 } else if (!strcmp(value, "data-built")) {
00709 lua_pushvalue(l, j + 1);
00710 CclParseBuilt(l, unit);
00711 lua_pop(l, 1);
00712 } else if (!strcmp(value, "data-train")) {
00713 lua_pushvalue(l, j + 1);
00714 CclParseTrain(l, unit);
00715 lua_pop(l, 1);
00716 } else if (!strcmp(value, "data-harvest")) {
00717 lua_pushvalue(l, j + 1);
00718 CclParseHarvest(l, unit);
00719 lua_pop(l, 1);
00720 } else if (!strcmp(value, "data-move")) {
00721 lua_pushvalue(l, j + 1);
00722 CclParseMove(l, unit);
00723 lua_pop(l, 1);
00724 } else if (!strcmp(value, "goal")) {
00725 unit->Goal = UnitSlots[(int)LuaToNumber(l, j + 1)];
00726 } else if (!strcmp(value, "auto-cast")) {
00727 s = LuaToString(l, j + 1);
00728 Assert(SpellTypeByIdent(s));
00729 if (!unit->AutoCastSpell) {
00730 unit->AutoCastSpell = new char[SpellTypeTable.size()];
00731 memset(unit->AutoCastSpell, 0, SpellTypeTable.size());
00732 }
00733 unit->AutoCastSpell[SpellTypeByIdent(s)->Slot] = 1;
00734 } else {
00735 i = GetVariableIndex(value);
00736 if (i != -1) {
00737 DefineVariableField(l, unit->Variable + i, j + 1);
00738 continue;
00739 }
00740 LuaError(l, "Unsupported tag: %s" _C_ value);
00741 }
00742 }
00743
00744
00745
00746
00747
00748
00749 if (!unit->Player) {
00750 unit->AssignToPlayer(player);
00751 UpdateForNewUnit(unit, 0);
00752 }
00753
00754
00755 if (unit->Removed && unit->Type->Revealer) {
00756 MapMarkUnitSight(unit);
00757 }
00758
00759
00760 if (unit->RescuedFrom) {
00761 unit->Colors = &unit->RescuedFrom->UnitColors;
00762 }
00763
00764 return 0;
00765 }
00766
00774 static int CclMoveUnit(lua_State *l)
00775 {
00776 CUnit *unit;
00777 int heading;
00778 int ix;
00779 int iy;
00780
00781 LuaCheckArgs(l, 2);
00782
00783 lua_pushvalue(l, 1);
00784 unit = CclGetUnit(l);
00785 lua_pop(l, 1);
00786
00787 lua_rawgeti(l, 2, 1);
00788 ix = LuaToNumber(l, -1);
00789 lua_pop(l, 1);
00790 lua_rawgeti(l, 2, 2);
00791 iy = LuaToNumber(l, -1);
00792 lua_pop(l, 1);
00793
00794 heading = SyncRand() % 256;
00795 if (UnitCanBeAt(unit, ix, iy)) {
00796 unit->Place(ix, iy);
00797 } else {
00798 unit->X = ix;
00799 unit->Y = iy;
00800 DropOutOnSide(unit, heading, 1, 1);
00801 }
00802
00803
00804 lua_pushvalue(l, 1);
00805 return 1;
00806 }
00807
00815 static int CclCreateUnit(lua_State *l)
00816 {
00817 CUnitType *unittype;
00818 CUnit *unit;
00819 int heading;
00820 int playerno;
00821 int ix;
00822 int iy;
00823
00824 LuaCheckArgs(l, 3);
00825
00826 lua_pushvalue(l, 1);
00827 unittype = CclGetUnitType(l);
00828 lua_pop(l, 1);
00829 if (!lua_istable(l, 3) || lua_objlen(l, 3) != 2) {
00830 LuaError(l, "incorrect argument !!");
00831 }
00832 lua_rawgeti(l, 3, 1);
00833 ix = LuaToNumber(l, -1);
00834 lua_pop(l, 1);
00835 lua_rawgeti(l, 3, 2);
00836 iy = LuaToNumber(l, -1);
00837 lua_pop(l, 1);
00838
00839 heading = SyncRand() % 256;
00840 lua_pushvalue(l, 2);
00841 playerno = TriggerGetPlayer(l);
00842 lua_pop(l, 1);
00843 if (playerno == -1) {
00844 printf("CreateUnit: You cannot use \"any\" in create-unit, specify a player\n");
00845 LuaError(l, "bad player");
00846 return 0;
00847 }
00848 if (Players[playerno].Type == PlayerNobody) {
00849 printf("CreateUnit: player %d does not exist\n", playerno);
00850 LuaError(l, "bad player");
00851 return 0;
00852 }
00853
00854 unit = MakeUnit(unittype, &Players[playerno]);
00855 if (unit == NoUnitP) {
00856 DebugPrint("Unable to allocate unit");
00857 return 0;
00858 } else {
00859 if (UnitCanBeAt(unit, ix, iy) ||
00860 (unit->Type->Building && CanBuildUnitType(NULL, unit->Type, ix, iy, 0))) {
00861 unit->Place(ix, iy);
00862 } else {
00863 unit->X = ix;
00864 unit->Y = iy;
00865 DropOutOnSide(unit, heading, 1, 1);
00866 }
00867 UpdateForNewUnit(unit, 0);
00868
00869 lua_pushnumber(l, unit->Slot);
00870 return 1;
00871 }
00872 }
00873
00879 static int CclSetResourcesHeld(lua_State *l)
00880 {
00881 CUnit *unit;
00882
00883 LuaCheckArgs(l, 2);
00884
00885 if (lua_isnil(l, 1)) {
00886 return 0;
00887 }
00888 if (!lua_istable(l, 2) || lua_objlen(l, 2) != MaxCosts) {
00889 LuaError(l, "incorrect argument");
00890 }
00891
00892 lua_pushvalue(l, 1);
00893 unit = CclGetUnit(l);
00894 lua_pop(l, 1);
00895
00896 for (int i = 0; i < MaxCosts; ++i) {
00897 lua_rawgeti(l, 2, i + 1);
00898 unit->ResourcesHeld[i] = LuaToNumber(l, -1) * CYCLES_PER_SECOND;
00899 lua_pop(l, 1);
00900 }
00901
00902 return 0;
00903 }
00904
00912 static int CclOrderUnit(lua_State *l)
00913 {
00914 int plynr;
00915 int x1;
00916 int y1;
00917 int x2;
00918 int y2;
00919 int dx1;
00920 int dy1;
00921 int dx2;
00922 int dy2;
00923 const CUnitType *unittype;
00924 CUnit *table[UnitMax];
00925 CUnit *unit;
00926 int an;
00927 int j;
00928 const char *order;
00929
00930 LuaCheckArgs(l, 5);
00931
00932 lua_pushvalue(l, 1);
00933 plynr = TriggerGetPlayer(l);
00934 lua_pop(l, 1);
00935 lua_pushvalue(l, 2);
00936 unittype = TriggerGetUnitType(l);
00937 lua_pop(l, 1);
00938 if (!lua_istable(l, 3)) {
00939 LuaError(l, "incorrect argument");
00940 }
00941 lua_rawgeti(l, 3, 1);
00942 x1 = LuaToNumber(l, -1);
00943 lua_pop(l, 1);
00944 lua_rawgeti(l, 3, 2);
00945 y1 = LuaToNumber(l, -1);
00946 lua_pop(l, 1);
00947 if (lua_objlen(l, 3) == 4) {
00948 lua_rawgeti(l, 3, 3);
00949 x2 = LuaToNumber(l, -1);
00950 lua_pop(l, 1);
00951 lua_rawgeti(l, 3, 4);
00952 y2 = LuaToNumber(l, -1);
00953 lua_pop(l, 1);
00954 } else {
00955 x2 = x1;
00956 y2 = y1;
00957 }
00958 if (!lua_istable(l, 4)) {
00959 LuaError(l, "incorrect argument");
00960 }
00961 lua_rawgeti(l, 4, 1);
00962 dx1 = LuaToNumber(l, -1);
00963 lua_pop(l, 1);
00964 lua_rawgeti(l, 4, 2);
00965 dy1 = LuaToNumber(l, -1);
00966 lua_pop(l, 1);
00967 if (lua_objlen(l, 4) == 4) {
00968 lua_rawgeti(l, 4, 3);
00969 dx2 = LuaToNumber(l, -1);
00970 lua_pop(l, 1);
00971 lua_rawgeti(l, 4, 4);
00972 dy2 = LuaToNumber(l, -1);
00973 lua_pop(l, 1);
00974 } else {
00975 dx2 = dx1;
00976 dy2 = dy1;
00977 }
00978 order = LuaToString(l, 5);
00979
00980 an = UnitCache.Select(x1, y1, x2 + 1, y2 + 1, table, UnitMax);
00981 for (j = 0; j < an; ++j) {
00982 unit = table[j];
00983 if (unittype == ANY_UNIT ||
00984 (unittype == ALL_FOODUNITS && !unit->Type->Building) ||
00985 (unittype == ALL_BUILDINGS && unit->Type->Building) ||
00986 unittype == unit->Type) {
00987 if (plynr == -1 || plynr == unit->Player->Index) {
00988 if (!strcmp(order,"move")) {
00989 CommandMove(unit, (dx1 + dx2) / 2, (dy1 + dy2) / 2, 1);
00990 } else if (!strcmp(order, "attack")) {
00991 CUnit *attack;
00992
00993 attack = TargetOnMap(unit, dx1, dy1, dx2 + 1, dy2 + 1);
00994 CommandAttack(unit, (dx1 + dx2) / 2, (dy1 + dy2) / 2, attack, 1);
00995 } else if (!strcmp(order, "patrol")) {
00996 CommandPatrolUnit(unit, (dx1 + dx2) / 2, (dy1 + dy2) / 2, 1);
00997 } else {
00998 LuaError(l, "Unsupported order: %s" _C_ order);
00999 }
01000 }
01001 }
01002 }
01003
01004 return 0;
01005 }
01006
01014 static int CclKillUnit(lua_State *l)
01015 {
01016 int j;
01017 int plynr;
01018 const CUnitType *unittype;
01019 CUnit *unit;
01020 CUnit **table;
01021
01022 LuaCheckArgs(l, 2);
01023
01024 lua_pushvalue(l, 1);
01025 unittype = TriggerGetUnitType(l);
01026 lua_pop(l, 1);
01027 plynr = TriggerGetPlayer(l);
01028 if (plynr == -1) {
01029 table = Units;
01030 j = NumUnits - 1;
01031 } else {
01032 table = Players[plynr].Units;
01033 j = Players[plynr].TotalNumUnits - 1;
01034 }
01035
01036 for (; j >= 0; --j) {
01037 unit = table[j];
01038 if (unittype == ANY_UNIT ||
01039 (unittype == ALL_FOODUNITS && !unit->Type->Building) ||
01040 (unittype == ALL_BUILDINGS && unit->Type->Building) ||
01041 unittype == unit->Type) {
01042 LetUnitDie(unit);
01043 lua_pushboolean(l, 1);
01044 return 1;
01045 }
01046 }
01047
01048 lua_pushboolean(l, 0);
01049 return 1;
01050 }
01051
01059 static int CclKillUnitAt(lua_State *l)
01060 {
01061 int plynr;
01062 int q;
01063 int x1;
01064 int y1;
01065 int x2;
01066 int y2;
01067 const CUnitType *unittype;
01068 CUnit *table[UnitMax];
01069 CUnit *unit;
01070 int an;
01071 int j;
01072 int s;
01073
01074 LuaCheckArgs(l, 2);
01075
01076 lua_pushvalue(l, 2);
01077 plynr = TriggerGetPlayer(l);
01078 lua_pop(l, 1);
01079 q = LuaToNumber(l, 3);
01080 lua_pushvalue(l, 1);
01081 unittype = TriggerGetUnitType(l);
01082 lua_pop(l, 1);
01083 if (!lua_istable(l, 4)) {
01084 LuaError(l, "incorrect argument");
01085 }
01086 lua_rawgeti(l, 4, 1);
01087 x1 = LuaToNumber(l, -1);
01088 lua_pop(l, 1);
01089 lua_rawgeti(l, 4, 2);
01090 y1 = LuaToNumber(l, -1);
01091 lua_pop(l, 1);
01092 lua_rawgeti(l, 4, 3);
01093 x2 = LuaToNumber(l, -1);
01094 lua_pop(l, 1);
01095 lua_rawgeti(l, 4, 4);
01096 y2 = LuaToNumber(l, -1);
01097 lua_pop(l, 1);
01098
01099 an = UnitCache.Select(x1, y1, x2 + 1, y2 + 1, table, UnitMax);
01100 for (j = s = 0; j < an && s < q; ++j) {
01101 unit = table[j];
01102 if (unittype == ANY_UNIT ||
01103 (unittype == ALL_FOODUNITS && !unit->Type->Building) ||
01104 (unittype == ALL_BUILDINGS && unit->Type->Building) ||
01105 unittype==unit->Type) {
01106 if (plynr == -1 || plynr == unit->Player->Index) {
01107 LetUnitDie(unit);
01108 ++s;
01109 }
01110 }
01111 }
01112
01113 lua_pushnumber(l, s);
01114 return 1;
01115 }
01116
01124 static int CclGetUnits(lua_State *l)
01125 {
01126 int plynr;
01127 int i;
01128
01129 LuaCheckArgs(l, 1);
01130
01131 plynr = TriggerGetPlayer(l);
01132
01133 lua_newtable(l);
01134 if (plynr == -1) {
01135 for (i = 0; i < NumUnits; ++i) {
01136 lua_pushnumber(l, Units[i]->Slot);
01137 lua_rawseti(l, -2, i + 1);
01138 }
01139 } else {
01140 for (i = 0; i < Players[plynr].TotalNumUnits; ++i) {
01141 lua_pushnumber(l, Players[plynr].Units[i]->Slot);
01142 lua_rawseti(l, -2, i + 1);
01143 }
01144 }
01145 return 1;
01146 }
01147
01155 static int CclGetUnitVariable(lua_State *l)
01156 {
01157 const CUnit *unit;
01158 int index;
01159
01160 LuaCheckArgs(l, 2);
01161
01162 lua_pushvalue(l, 1);
01163 unit = CclGetUnit(l);
01164 lua_pop(l, 1);
01165
01166 index = GetVariableIndex(LuaToString(l, 2));
01167 if (index == -1) {
01168 LuaError(l, "Bad variable name '%s'\n" _C_ LuaToString(l, 2));
01169 }
01170 lua_pushnumber(l, unit->Variable[index].Value);
01171 return 1;
01172 }
01173
01181 static int CclSetUnitVariable(lua_State *l)
01182 {
01183 CUnit *unit;
01184 int index;
01185 int value;
01186
01187 LuaCheckArgs(l, 3);
01188
01189 lua_pushvalue(l, 1);
01190 unit = CclGetUnit(l);
01191 lua_pop(l, 1);
01192 index = GetVariableIndex(LuaToString(l, 2));
01193 if (index == -1) {
01194 LuaError(l, "Bad variable name '%s'\n" _C_ LuaToString(l, 2));
01195 }
01196 value = LuaToNumber(l, 3);
01197 if (value > unit->Variable[index].Max) {
01198 unit->Variable[index].Value = unit->Variable[index].Max;
01199 } else {
01200 unit->Variable[index].Value = value;
01201 }
01202 lua_pushnumber(l, value);
01203 return 1;
01204 }
01205
01211 static int CclSlotUsage(lua_State *l)
01212 {
01213 unsigned int args;
01214 unsigned int i;
01215 const char *key;
01216 int unit_index;
01217 unsigned long cycle;
01218
01219 args = lua_gettop(l);
01220 if (args == 0) {
01221 UnitSlotFree = 0;
01222 return 0;
01223 }
01224 UnitSlotFree = LuaToNumber(l, 1);
01225 for (i = 0; i < UnitSlotFree; i++) {
01226 UnitSlots[i] = new CUnit;
01227 UnitSlots[i]->Slot = i;
01228 }
01229 for (i = 2; i <= args; i++) {
01230 unit_index = -1;
01231 cycle = (unsigned long)-1;
01232 for (lua_pushnil(l); lua_next(l, i); lua_pop(l, 1)) {
01233 key = LuaToString(l, -2);
01234 if (!strcmp(key, "Slot")) {
01235 unit_index = LuaToNumber(l, -1);
01236 } else if (!strcmp(key, "FreeCycle")) {
01237 cycle = LuaToNumber(l, -1);
01238 } else {
01239 LuaError(l, "Wrong key %s" _C_ key);
01240 }
01241 }
01242 Assert(unit_index != -1 && cycle != (unsigned long)-1);
01243 UnitManager.ReleaseUnit(UnitSlots[unit_index]);
01244 UnitSlots[unit_index]->Refs = cycle;
01245 }
01246 return 0;
01247 }
01248
01252 void UnitCclRegister(void)
01253 {
01254 lua_register(Lua, "SetBuildingCapture", CclSetBuildingCapture);
01255
01256 lua_register(Lua, "Unit", CclUnit);
01257
01258 lua_register(Lua, "MoveUnit", CclMoveUnit);
01259 lua_register(Lua, "CreateUnit", CclCreateUnit);
01260 lua_register(Lua, "SetResourcesHeld", CclSetResourcesHeld);
01261 lua_register(Lua, "OrderUnit", CclOrderUnit);
01262 lua_register(Lua, "KillUnit", CclKillUnit);
01263 lua_register(Lua, "KillUnitAt", CclKillUnitAt);
01264
01265 lua_register(Lua, "GetUnits", CclGetUnits);
01266
01267
01268 lua_register(Lua, "GetUnitVariable", CclGetUnitVariable);
01269 lua_register(Lua, "SetUnitVariable", CclSetUnitVariable);
01270
01271 lua_register(Lua, "SlotUsage", CclSlotUsage);
01272 }
01273