/* virtual */ bool COrder_Built::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) { if (!strcmp(value, "worker")) { ++j; lua_rawgeti(l, -1, j + 1); this->Worker = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "progress")) { ++j; this->ProgressCounter = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "cancel")) { this->IsCancelled = true; } else if (!strcmp(value, "frame")) { ++j; int frame = LuaToNumber(l, -1, j + 1); CConstructionFrame *cframe = unit.Type->Construction->Frames; while (frame-- && cframe->Next != NULL) { cframe = cframe->Next; } this->Frame = cframe; } else { return false; } return true; }
/* virtual */ bool COrder_Build::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) { if (!strcmp(value, "building")) { ++j; lua_rawgeti(l, -1, j + 1); this->BuildingUnit = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "range")) { ++j; this->Range = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "state")) { ++j; this->State = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "tile")) { ++j; lua_rawgeti(l, -1, j + 1); CclGetPos(l, &this->goalPos.x , &this->goalPos.y); lua_pop(l, 1); } else if (!strcmp(value, "type")) { ++j; this->Type = UnitTypeByIdent(LuaToString(l, -1, j + 1)); } else { return false; } return true; }
/* virtual */ bool COrder_Resource::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) { if (!strcmp(value, "current-res")) { ++j; this->CurrentResource = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "done-harvesting")) { this->DoneHarvesting = true; } else if (!strcmp(value, "res-depot")) { ++j; lua_rawgeti(l, -1, j + 1); this->Depot = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "res-mine")) { ++j; lua_rawgeti(l, -1, j + 1); this->Resource.Mine = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "res-pos")) { ++j; lua_rawgeti(l, -1, j + 1); CclGetPos(l, &this->Resource.Pos.x , &this->Resource.Pos.y); lua_pop(l, 1); } else if (!strcmp(value, "state")) { ++j; this->State = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "timetoharvest")) { ++j; this->TimeToHarvest = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "worker")) { ++j; lua_rawgeti(l, -1, j + 1); this->worker = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "tile")) { ++j; lua_rawgeti(l, -1, j + 1); CclGetPos(l, &this->goalPos.x , &this->goalPos.y); lua_pop(l, 1); } else { return false; } return true; }
bool COrder::ParseGenericData(lua_State *l, int &j, const char *value) { if (!strcmp(value, "finished")) { this->Finished = true; } else if (!strcmp(value, "goal")) { ++j; lua_rawgeti(l, -1, j + 1); this->SetGoal(CclGetUnitFromRef(l)); lua_pop(l, 1); } else { return false; } return true; }
/* virtual */ bool COrder_Repair::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) { if (!strcmp("repaircycle", value)) { ++j; this->RepairCycle = LuaToNumber(l, -1, j + 1); } else if (!strcmp("repair-target", value)) { ++j; lua_rawgeti(l, -1, j + 1); this->ReparableTarget = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp("state", value)) { ++j; this->State = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "tile")) { ++j; lua_rawgeti(l, -1, j + 1); CclGetPos(l, &this->goalPos.x , &this->goalPos.y); lua_pop(l, 1); } else { return false; } return true; }
/** ** Create a missile. ** ** @param l Lua state. */ static int CclMissile(lua_State *l) { MissileType *type = nullptr; PixelPos position(-1, -1); PixelPos destination(-1, -1); PixelPos source(-1, -1); int z = 0; Missile *missile = nullptr; DebugPrint("FIXME: not finished\n"); const int args = lua_gettop(l); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; if (!strcmp(value, "type")) { type = MissileTypeByIdent(LuaToString(l, j + 1)); } else if (!strcmp(value, "pos")) { CclGetPos(l, &position.x, &position.y, j + 1); } else if (!strcmp(value, "origin-pos")) { CclGetPos(l, &source.x, &source.y, j + 1); } else if (!strcmp(value, "goal")) { CclGetPos(l, &destination.x, &destination.y, j + 1); //Wyrmgus start } else if (!strcmp(value, "map-layer")) { z = LuaToNumber(l, j + 1); //Wyrmgus end } else if (!strcmp(value, "local")) { Assert(type); //Wyrmgus start // missile = MakeLocalMissile(*type, position, destination); missile = MakeLocalMissile(*type, position, destination, z); //Wyrmgus end missile->Local = 1; --j; } else if (!strcmp(value, "global")) { Assert(type); //Wyrmgus start // missile = MakeMissile(*type, position, destination); missile = MakeMissile(*type, position, destination, z); //Wyrmgus end missile->position = position; missile->source = source; missile->destination = destination; //Wyrmgus start missile->MapLayer = z; //Wyrmgus end missile->Local = 0; --j; } else if (!strcmp(value, "frame")) { Assert(missile); missile->SpriteFrame = LuaToNumber(l, j + 1); } else if (!strcmp(value, "state")) { Assert(missile); missile->State = LuaToNumber(l, j + 1); } else if (!strcmp(value, "anim-wait")) { Assert(missile); missile->AnimWait = LuaToNumber(l, j + 1); } else if (!strcmp(value, "wait")) { Assert(missile); missile->Wait = LuaToNumber(l, j + 1); } else if (!strcmp(value, "delay")) { Assert(missile); missile->Delay = LuaToNumber(l, j + 1); } else if (!strcmp(value, "source")) { Assert(missile); lua_pushvalue(l, j + 1); missile->SourceUnit = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "target")) { Assert(missile); lua_pushvalue(l, j + 1); missile->TargetUnit = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "damage")) { Assert(missile); missile->Damage = LuaToNumber(l, j + 1); } else if (!strcmp(value, "lightning-damage")) { Assert(missile); missile->LightningDamage = LuaToNumber(l, j + 1); } else if (!strcmp(value, "ttl")) { Assert(missile); missile->TTL = LuaToNumber(l, j + 1); } else if (!strcmp(value, "hidden")) { Assert(missile); missile->Hidden = 1; --j; } else if (!strcmp(value, "step")) { Assert(missile); if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 2) { LuaError(l, "incorrect argument"); } missile->CurrentStep = LuaToNumber(l, j + 1, 1); missile->TotalStep = LuaToNumber(l, j + 1, 2); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } // we need to reinitialize position parameters - that's because of // the way InitMissile() (called from MakeLocalMissile()) computes // them - it works for creating a missile during a game but breaks // loading the missile from a file. missile->position = position; missile->source = source; missile->destination = destination; missile->MapLayer = z; return 0; }
/** ** Parse unit ** ** @param l Lua state. ** ** @todo Verify that vision table is always correct (transporter) ** @todo (PlaceUnit() and host-info). */ static int CclUnit(lua_State *l) { const int slot = LuaToNumber(l, 1); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument"); } CUnit *unit = NULL; CUnitType *type = NULL; CUnitType *seentype = NULL; CPlayer *player = NULL; // Parse the list: const int args = lua_rawlen(l, 2); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, 2, j + 1); ++j; if (!strcmp(value, "type")) { type = UnitTypeByIdent(LuaToString(l, 2, j + 1)); } else if (!strcmp(value, "seen-type")) { seentype = UnitTypeByIdent(LuaToString(l, 2, j + 1)); } else if (!strcmp(value, "player")) { player = &Players[LuaToNumber(l, 2, j + 1)]; // During a unit's death animation (when action is "die" but the // unit still has its original type, i.e. it's still not a corpse) // the unit is already removed from map and from player's // unit list (=the unit went through LetUnitDie() which // calls RemoveUnit() and UnitLost()). Such a unit should not // be put on player's unit list! However, this state is not // easily detected from this place. It seems that it is // characterized by // unit->CurrentAction()==UnitActionDie so we have to wait // until we parsed at least Unit::Orders[]. Assert(type); unit = &UnitManager.GetSlotUnit(slot); unit->Init(*type); unit->Seen.Type = seentype; unit->Active = 0; unit->Removed = 0; Assert(UnitNumber(*unit) == slot); } else if (!strcmp(value, "current-sight-range")) { unit->CurrentSightRange = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "refs")) { unit->Refs = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "host-info")) { lua_rawgeti(l, 2, j + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 4) { LuaError(l, "incorrect argument"); } Vec2i pos; int w; int h; pos.x = LuaToNumber(l, -1, 1); pos.y = LuaToNumber(l, -1, 2); w = LuaToNumber(l, -1, 3); h = LuaToNumber(l, -1, 4); MapSight(*player, pos, w, h, unit->CurrentSightRange, MapMarkTileSight); // Detectcloak works in container if (unit->Type->DetectCloak) { MapSight(*player, pos, w, h, unit->CurrentSightRange, MapMarkTileDetectCloak); } // Radar(Jammer) not. lua_pop(l, 1); } else if (!strcmp(value, "tile")) { lua_rawgeti(l, 2, j + 1); CclGetPos(l, &unit->tilePos.x , &unit->tilePos.y, -1); lua_pop(l, 1); unit->Offset = Map.getIndex(unit->tilePos); } else if (!strcmp(value, "seen-tile")) { lua_rawgeti(l, 2, j + 1); CclGetPos(l, &unit->Seen.tilePos.x , &unit->Seen.tilePos.y, -1); lua_pop(l, 1); } else if (!strcmp(value, "stats")) { unit->Stats = &type->Stats[LuaToNumber(l, 2, j + 1)]; } else if (!strcmp(value, "pixel")) { lua_rawgeti(l, 2, j + 1); CclGetPos(l, &unit->IX , &unit->IY, -1); lua_pop(l, 1); } else if (!strcmp(value, "seen-pixel")) { lua_rawgeti(l, 2, j + 1); CclGetPos(l, &unit->Seen.IX , &unit->Seen.IY, -1); lua_pop(l, 1); } else if (!strcmp(value, "frame")) { unit->Frame = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "seen")) { unit->Seen.Frame = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "not-seen")) { unit->Seen.Frame = UnitNotSeen; --j; } else if (!strcmp(value, "direction")) { unit->Direction = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "damage-type")) { unit->DamagedType = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "attacked")) { // FIXME : unsigned long should be better handled unit->Attacked = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "auto-repair")) { unit->AutoRepair = 1; --j; } else if (!strcmp(value, "burning")) { unit->Burning = 1; --j; } else if (!strcmp(value, "destroyed")) { unit->Destroyed = 1; --j; } else if (!strcmp(value, "removed")) { unit->Removed = 1; --j; } else if (!strcmp(value, "selected")) { unit->Selected = 1; --j; } else if (!strcmp(value, "summoned")) { unit->Summoned = 1; --j; } else if (!strcmp(value, "waiting")) { unit->Waiting = 1; --j; } else if (!strcmp(value, "mine-low")) { unit->MineLow = 1; --j; } else if (!strcmp(value, "rescued-from")) { unit->RescuedFrom = &Players[LuaToNumber(l, 2, j + 1)]; } else if (!strcmp(value, "seen-by-player")) { const char *s = LuaToString(l, 2, j + 1); unit->Seen.ByPlayer = 0; for (int i = 0; i < PlayerMax && *s; ++i, ++s) { if (*s == '-' || *s == '_' || *s == ' ') { unit->Seen.ByPlayer &= ~(1 << i); } else { unit->Seen.ByPlayer |= (1 << i); } } } else if (!strcmp(value, "seen-destroyed")) { const char *s = LuaToString(l, 2, j + 1); unit->Seen.Destroyed = 0; for (int i = 0; i < PlayerMax && *s; ++i, ++s) { if (*s == '-' || *s == '_' || *s == ' ') { unit->Seen.Destroyed &= ~(1 << i); } else { unit->Seen.Destroyed |= (1 << i); } } } else if (!strcmp(value, "constructed")) { unit->Constructed = 1; --j; } else if (!strcmp(value, "seen-constructed")) { unit->Seen.Constructed = 1; --j; } else if (!strcmp(value, "seen-state")) { unit->Seen.State = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "active")) { unit->Active = 1; --j; } else if (!strcmp(value, "ttl")) { // FIXME : unsigned long should be better handled unit->TTL = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "threshold")) { // FIXME : unsigned long should be better handled unit->Threshold = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "group-id")) { unit->GroupId = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "last-group")) { unit->LastGroup = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "resources-held")) { unit->ResourcesHeld = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "current-resource")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->CurrentResource = CclGetResourceByName(l); lua_pop(l, 1); } else if (!strcmp(value, "pathfinder-input")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->pathFinderData->input.Load(l); lua_pop(l, 1); } else if (!strcmp(value, "pathfinder-output")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->pathFinderData->output.Load(l); lua_pop(l, 1); } else if (!strcmp(value, "wait")) { unit->Wait = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "anim-data")) { lua_rawgeti(l, 2, j + 1); CAnimations::LoadUnitAnim(l, *unit, -1); lua_pop(l, 1); } else if (!strcmp(value, "wait-anim-data")) { lua_rawgeti(l, 2, j + 1); CAnimations::LoadWaitUnitAnim(l, *unit, -1); lua_pop(l, 1); } else if (!strcmp(value, "blink")) { unit->Blink = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "moving")) { unit->Moving = 1; --j; } else if (!strcmp(value, "re-cast")) { unit->ReCast = 1; --j; } else if (!strcmp(value, "boarded")) { unit->Boarded = 1; --j; } else if (!strcmp(value, "next-worker")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->NextWorker = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "resource-workers")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->Resource.Workers = CclGetUnitFromRef(l); lua_pop(l, 1); } else if (!strcmp(value, "resource-assigned")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->Resource.Assigned = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "resource-active")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); unit->Resource.Active = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "units-boarded-count")) { unit->BoardCount = LuaToNumber(l, 2, j + 1); } else if (!strcmp(value, "units-contained")) { int subargs; int k; lua_rawgeti(l, 2, j + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } subargs = lua_rawlen(l, -1); for (k = 0; k < subargs; ++k) { lua_rawgeti(l, -1, k + 1); CUnit *u = CclGetUnitFromRef(l); lua_pop(l, 1); u->AddInContainer(*unit); } lua_pop(l, 1); } else if (!strcmp(value, "orders")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); CclParseOrders(l, *unit); lua_pop(l, 1); // now we know unit's action so we can assign it to a player Assert(player != NULL); unit->AssignToPlayer(*player); if (unit->CurrentAction() == UnitActionBuilt) { DebugPrint("HACK: the building is not ready yet\n"); // HACK: the building is not ready yet unit->Player->UnitTypesCount[type->Slot]--; if (unit->Active) { unit->Player->UnitTypesAiActiveCount[type->Slot]--; } } } else if (!strcmp(value, "critical-order")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); CclParseOrder(l, *unit , &unit->CriticalOrder); lua_pop(l, 1); } else if (!strcmp(value, "saved-order")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); CclParseOrder(l, *unit, &unit->SavedOrder); lua_pop(l, 1); } else if (!strcmp(value, "new-order")) { lua_rawgeti(l, 2, j + 1); lua_pushvalue(l, -1); CclParseOrder(l, *unit, &unit->NewOrder); lua_pop(l, 1); } else if (!strcmp(value, "goal")) { unit->Goal = &UnitManager.GetSlotUnit(LuaToNumber(l, 2, j + 1)); } else if (!strcmp(value, "auto-cast")) { const char *s = LuaToString(l, 2, j + 1); Assert(SpellTypeByIdent(s)); if (!unit->AutoCastSpell) { unit->AutoCastSpell = new char[SpellTypeTable.size()]; memset(unit->AutoCastSpell, 0, SpellTypeTable.size()); } unit->AutoCastSpell[SpellTypeByIdent(s)->Slot] = 1; } else if (!strcmp(value, "spell-cooldown")) { lua_rawgeti(l, 2, j + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != SpellTypeTable.size()) { LuaError(l, "incorrect argument"); } if (!unit->SpellCoolDownTimers) { unit->SpellCoolDownTimers = new int[SpellTypeTable.size()]; memset(unit->SpellCoolDownTimers, 0, SpellTypeTable.size() * sizeof(int)); } for (size_t k = 0; k < SpellTypeTable.size(); ++k) { unit->SpellCoolDownTimers[k] = LuaToNumber(l, -1, k + 1); } lua_pop(l, 1); } else { const int index = UnitTypeVar.VariableNameLookup[value];// User variables if (index != -1) { // Valid index lua_rawgeti(l, 2, j + 1); DefineVariableField(l, unit->Variable + index, -1); lua_pop(l, 1); continue; } LuaError(l, "Unit: Unsupported tag: %s" _C_ value); } } // Unit may not have been assigned to a player before now. If not, // do so now. It is only assigned earlier if we have orders. // for loading of units from a MAP, and not a savegame, we won't // have orders for those units. They should appear here as if // they were just created. if (!unit->Player) { Assert(player); unit->AssignToPlayer(*player); UpdateForNewUnit(*unit, 0); } // Revealers are units that can see while removed if (unit->Removed && unit->Type->Revealer) { MapMarkUnitSight(*unit); } // Fix Colors for rescued units. if (unit->RescuedFrom) { unit->Colors = &unit->RescuedFrom->UnitColors; } return 0; }