/* virtual */ void COrder_Resource::Save(CFile &file, const CUnit &unit) const { file.printf("{\"action-resource\","); if (this->Finished) { file.printf(" \"finished\","); } if (this->HasGoal()) { file.printf(" \"goal\", \"%s\",", UnitReference(this->GetGoal()).c_str()); } file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); Assert(this->worker != NULL && worker->IsAlive()); file.printf(" \"worker\", \"%s\",", UnitReference(worker).c_str()); file.printf(" \"current-res\", %d,", this->CurrentResource); file.printf(" \"res-pos\", {%d, %d},", this->Resource.Pos.x, this->Resource.Pos.y); if (this->Resource.Mine != NULL) { file.printf(" \"res-mine\", \"%s\",", UnitReference(this->Resource.Mine).c_str()); } if (this->Depot != NULL) { file.printf(" \"res-depot\", \"%s\",", UnitReference(this->Depot).c_str()); } if (this->DoneHarvesting) { file.printf(" \"done-harvesting\","); } file.printf(" \"timetoharvest\", %d,", this->TimeToHarvest); file.printf(" \"state\", %d", this->State); file.printf("}"); }
/** ** Save the state of a missile to file. ** ** @param file Output file. */ void Missile::SaveMissile(CFile &file) const { file.printf("Missile(\"type\", \"%s\",", this->Type->Ident.c_str()); file.printf(" \"%s\",", this->Local ? "local" : "global"); file.printf(" \"pos\", "); SavePixelPos(file, this->position); file.printf(", \"origin-pos\", "); SavePixelPos(file, this->source); file.printf(", \"goal\", "); SavePixelPos(file, this->destination); file.printf(",\n \"frame\", %d, \"state\", %d, \"anim-wait\", %d, \"wait\", %d, \"delay\", %d,\n ", this->SpriteFrame, this->State, this->AnimWait, this->Wait, this->Delay); if (this->SourceUnit != NULL) { file.printf(" \"source\", \"%s\",", UnitReference(this->SourceUnit).c_str()); } if (this->TargetUnit != NULL) { file.printf(" \"target\", \"%s\",", UnitReference(this->TargetUnit).c_str()); } file.printf(" \"damage\", %d,", this->Damage); file.printf(" \"ttl\", %d,", this->TTL); if (this->Hidden) { file.printf(" \"hidden\", "); } file.printf(" \"step\", {%d, %d}", this->CurrentStep, this->TotalStep); // Slot filled in during init file.printf(")\n"); }
UnitReference UnitContainer::get_unit(id_t id) { if (this->valid_id(id)) { return UnitReference(this, id, this->live_units[id].get()); } else { return UnitReference(this, id, nullptr); } }
/** ** Save current selection state. ** ** @param file Output file. */ void SaveSelections(CFile &file) { file.printf("\n--- -----------------------------------------\n"); file.printf("--- MODULE: selection\n\n"); file.printf("SetGroupId(%d)\n", GroupId); file.printf("Selection(%d, {", NumSelected); for (int i = 0; i < NumSelected; ++i) { file.printf("\"%s\", ", UnitReference(*Selected[i]).c_str()); } file.printf("})\n"); }
/** ** Save current selection state. ** ** @param file Output file. */ void SaveSelections(CFile &file) { file.printf("\n--- -----------------------------------------\n"); file.printf("--- MODULE: selection\n\n"); file.printf("SetGroupId(%d)\n", GroupId); file.printf("Selection(%d, {", Selected.size()); // TODO: remove for (size_t i = 0; i != Selected.size(); ++i) { file.printf("\"%s\", ", UnitReference(*Selected[i]).c_str()); } file.printf("})\n"); }
/* virtual */ void COrder_Repair::Save(CFile &file, const CUnit &unit) const { file.printf("{\"action-repair\","); if (this->Finished) { file.printf(" \"finished\", "); } if (this->HasGoal()) { file.printf(" \"goal\", \"%s\",", UnitReference(this->GetGoal()).c_str()); } file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); if (this->ReparableTarget != NULL) { file.printf(" \"repair-target\", \"%s\",", UnitReference(this->GetReparableTarget()).c_str()); } file.printf(" \"repaircycle\", %d,", this->RepairCycle); file.printf(" \"state\", %d", this->State); file.printf("}"); }
/** ** Save groups. ** ** @param file Output file. */ void SaveGroups(CFile *file) { file->printf("\n--- -----------------------------------------\n"); file->printf("--- MODULE: groups\n\n"); for (int g = 0; g < NUM_GROUPS; ++g) { file->printf("Group(%d, %d, {", g, Groups[g].NumUnits); for (int i = 0; i < Groups[g].NumUnits; ++i) { file->printf("\"%s\", ", UnitReference(*Groups[g].Units[i]).c_str()); } file->printf("})\n"); } }
/** ** Save groups. ** ** @param file Output file. */ void SaveGroups(CFile &file) { file.printf("\n--- -----------------------------------------\n"); file.printf("--- MODULE: groups\n\n"); for (int g = 0; g < NUM_GROUPS; ++g) { file.printf("Group(%d, %lu, {", g, (long unsigned int)Groups[g].getUnits().size()); for (size_t i = 0; i < Groups[g].getUnits().size(); ++i) { file.printf("\"%s\", ", UnitReference(*Groups[g].getUnits()[i]).c_str()); } file.printf("})\n"); } }
/* virtual */ void COrder_Unload::Save(CFile &file, const CUnit &unit) const { file.printf("{\"action-unload\","); if (this->Finished) { file.printf(" \"finished\", "); } file.printf(" \"range\", %d,", this->Range); if (this->HasGoal()) { file.printf(" \"goal\", \"%s\",", UnitReference(this->GetGoal()).c_str()); } file.printf(" \"tile\", {%d, %d}, ", this->goalPos.x, this->goalPos.y); file.printf("\"state\", %d", this->State); file.printf("}"); }
UnitReference UnitContainer::new_unit(UnitType &type, Player &owner, TerrainObject *other) { auto newobj = std::make_unique<Unit>(*this, next_new_id++); // try placing unit TerrainObject *placed = type.place_beside(newobj.get(), other); if (placed) { type.initialise(newobj.get(), owner); auto id = newobj->id; this->live_units.emplace(id, std::move(newobj)); return this->live_units[id]->get_ref(); } return UnitReference(); // is not valid }
UnitReference UnitContainer::new_unit(UnitType &type, Player &owner, coord::phys3 position) { auto newobj = std::make_unique<Unit>(*this, next_new_id++); // try placing unit at this location auto terrain_shared = this->get_terrain(); auto placed = type.place(newobj.get(), terrain_shared, position); if (placed) { type.initialise(newobj.get(), owner); auto id = newobj->id; this->live_units.emplace(id, std::move(newobj)); return this->live_units[id]->get_ref(); } return UnitReference(); // is not valid }
/* virtual */ void COrder_Build::Save(CFile &file, const CUnit &unit) const { file.printf("{\"action-build\","); if (this->Finished) { file.printf(" \"finished\", "); } file.printf(" \"range\", %d,", this->Range); file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); if (this->BuildingUnit != NULL) { file.printf(" \"building\", \"%s\",", UnitReference(this->BuildingUnit).c_str()); } file.printf(" \"type\", \"%s\",", this->Type->Ident.c_str()); file.printf(" \"state\", %d", this->State); file.printf("}"); }
/* virtual */ void COrder_Follow::Save(CFile &file, const CUnit &unit) const { file.printf("{\"action-follow\","); if (this->Finished) { file.printf(" \"finished\", "); } file.printf(" \"range\", %d,", this->Range); if (this->HasGoal()) { file.printf(" \"goal\", \"%s\",", UnitReference(this->GetGoal()).c_str()); } file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); //Wyrmgus start file.printf(" \"map-layer\", %d,", this->MapLayer); //Wyrmgus end file.printf(" \"state\", %d", this->State); file.printf("}"); }
UnitReference GatherAction::nearest_dropsite() { // find nearest dropsite from the targeted resource auto ds = find_near(*this->target.get()->location, [=](const TerrainObject &obj) { return &obj.unit != this->entity && &obj.unit != this->target.get() && obj.unit.has_attribute(attr_type::building) && obj.unit.has_attribute(attr_type::owner) && obj.unit.get_attribute<attr_type::owner>().player.owns(*this->entity); }); if (ds) { return ds->unit.get_ref(); } else { this->entity->log(MSG(dbg) << "no dropsite found"); return UnitReference(); } }
/* virtual */ void COrder_Built::Save(CFile &file, const CUnit &unit) const { file.printf("{\"action-built\", "); if (this->Finished) { file.printf(" \"finished\", "); } CConstructionFrame *cframe = unit.Type->Construction->Frames; int frame = 0; while (cframe != this->Frame) { cframe = cframe->Next; ++frame; } if (this->Worker != NULL) { file.printf("\"worker\", \"%s\", ", UnitReference(this->Worker).c_str()); } file.printf("\"progress\", %d, \"frame\", %d", this->ProgressCounter, frame); if (this->IsCancelled) { file.printf(", \"cancel\""); } file.printf("}"); }
/** ** Save cursor state. */ global void SaveCursors(FILE* file) { int i; fprintf(file,"\n;;; -----------------------------------------\n"); fprintf(file,";;; MODULE: cursors $Id: cursor.c,v 1.54 2003/01/11 05:51:19 jsalmon3 Exp $\n\n"); for( i=0; Cursors[i].OType; ++i ) { fprintf(file,"(define-cursor '%s '%s\n", Cursors[i].Ident, Cursors[i].Race ? Cursors[i].Race : "any"); fprintf(file," 'image \"%s\"\n",Cursors[i].File); fprintf(file," 'hot-spot '(%d %d) ",Cursors[i].HotX,Cursors[i].HotY); fprintf(file,"'size '(%d %d) ",Cursors[i].Width,Cursors[i].Height); fprintf(file,")\n\n"); } // Not ready: fprintf(file,";;(set-game-cursor! '%s)\n",GameCursor->Ident); // FIXME: what about the other variables??? switch( CursorState ) { case CursorStatePoint: fprintf(file,";;(cursor-state 'point)\n"); break; case CursorStateSelect: fprintf(file,";;(cursor-state 'select)\n"); break; case CursorStateRectangle: fprintf(file,";;(cursor-state 'rectangle)\n"); break; } fprintf(file,";;(cursor-action %d)\n",CursorAction); fprintf(file,";;(cursor-value %d)\n",CursorValue); fprintf(file,";;(cursor-building '%s)\n", CursorBuilding ? CursorBuilding->Ident : "()"); fprintf(file,";;(cursor-position '(%d %d)\n",CursorX,CursorY); fprintf(file,";;(cursor-start '(%d %d)\n",CursorStartX,CursorStartY); fprintf(file,";;(unit-under-cursor %s\n", UnitUnderCursor ? UnitReference(UnitUnderCursor) : "()"); }
/* virtual */ void COrder_Attack::Save(CFile &file, const CUnit &unit) const { Assert(Action == UnitActionAttack || Action == UnitActionAttackGround); if (Action == UnitActionAttack) { file.printf("{\"action-attack\","); } else { file.printf("{\"action-attack-ground\","); } file.printf(" \"range\", %d,", this->Range); file.printf(" \"min-range\", %d,", this->MinRange); if (this->Finished) { file.printf(" \"finished\", "); } if (this->HasGoal()) { file.printf(" \"goal\", \"%s\",", UnitReference(this->GetGoal()).c_str()); } file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); file.printf(" \"state\", %d", this->State); file.printf("}"); }
/** ** Save state of players to file. ** ** @param file Output file. ** ** @note FIXME: Not completely saved. */ void SavePlayers(CFile *file) { int j; Uint8 r, g, b; file->printf("\n--------------------------------------------\n"); file->printf("--- MODULE: players\n\n"); // // Dump all players // for (int i = 0; i < NumPlayers; ++i) { CPlayer *p = &Players[i]; file->printf("Player(%d,\n", i); file->printf(" \"name\", \"%s\",\n", p->Name.c_str()); file->printf(" \"type\", "); switch (p->Type) { case PlayerNeutral: file->printf("\"neutral\","); break; case PlayerNobody: file->printf("\"nobody\","); break; case PlayerComputer: file->printf("\"computer\","); break; case PlayerPerson: file->printf("\"person\","); break; case PlayerRescuePassive: file->printf("\"rescue-passive\",");break; case PlayerRescueActive: file->printf("\"rescue-active\","); break; default: file->printf("%d,",p->Type);break; } file->printf(" \"race\", \"%s\",", PlayerRaces.Name[p->Race].c_str()); file->printf(" \"ai-name\", \"%s\",\n", p->AiName.c_str()); file->printf(" \"team\", %d,", p->Team); file->printf(" \"enemy\", \""); for (j = 0; j < PlayerMax; ++j) { file->printf("%c",(p->Enemy & (1 << j)) ? 'X' : '_'); } file->printf("\", \"allied\", \""); for (j = 0; j < PlayerMax; ++j) { file->printf("%c", (p->Allied & (1 << j)) ? 'X' : '_'); } file->printf("\", \"shared-vision\", \""); for (j = 0; j < PlayerMax; ++j) { file->printf("%c", (p->SharedVision & (1 << j)) ? 'X' : '_'); } file->printf("\",\n \"start\", {%d, %d},\n", p->StartX, p->StartY); // Resources file->printf(" \"resources\", {"); for (j = 0; j < MaxCosts; ++j) { if (j) { if (j == MaxCosts / 2) { file->printf("\n "); } else { file->printf(" "); } } file->printf("\"%s\", %d,", DefaultResourceNames[j].c_str(), p->Resources[j]); } // Last Resources file->printf("},\n \"last-resources\", {"); for (j = 0; j < MaxCosts; ++j) { if (j) { if (j == MaxCosts / 2) { file->printf("\n "); } else { file->printf(" "); } } file->printf("\"%s\", %d,", DefaultResourceNames[j].c_str(), p->LastResources[j]); } // Incomes file->printf("},\n \"incomes\", {"); for (j = 0; j < MaxCosts; ++j) { if (j) { if (j == MaxCosts / 2) { file->printf("\n "); } else { file->printf(" "); } } file->printf("\"%s\", %d,", DefaultResourceNames[j].c_str(), p->Incomes[j]); } // Revenue file->printf("},\n \"revenue\", {"); for (j = 0; j < MaxCosts; ++j) { if (j) { if (j == MaxCosts / 2) { file->printf("\n "); } else { file->printf(" "); } } file->printf("\"%s\", %d,", DefaultResourceNames[j].c_str(), p->Revenue[j]); } // UnitTypesCount done by load units. file->printf("},\n \"%s\",\n", p->AiEnabled ? "ai-enabled" : "ai-disabled"); // Ai done by load ais. // Units done by load units. // TotalNumUnits done by load units. // NumBuildings done by load units. file->printf(" \"supply\", %d,",p->Supply); file->printf(" \"unit-limit\", %d,", p->UnitLimit); file->printf(" \"building-limit\", %d,", p->BuildingLimit); file->printf(" \"total-unit-limit\", %d,", p->TotalUnitLimit); file->printf("\n \"score\", %d,", p->Score); file->printf("\n \"total-units\", %d,", p->TotalUnits); file->printf("\n \"total-buildings\", %d,", p->TotalBuildings); file->printf("\n \"total-resources\", {"); for (j = 0; j < MaxCosts; ++j) { if (j) { file->printf(" "); } file->printf("%d,", p->TotalResources[j]); } file->printf("},"); file->printf("\n \"total-razings\", %d,", p->TotalRazings); file->printf("\n \"total-kills\", %d,", p->TotalKills); SDL_GetRGB(p->Color, TheScreen->format, &r, &g, &b); file->printf("\n \"color\", { %d, %d, %d },", r, g, b); // UnitColors done by init code. // Allow saved by allow. file->printf("\n \"timers\", {"); for (j = 0; j < UpgradeMax; ++j) { if (j) { file->printf(" ,"); } file->printf("%d", p->UpgradeTimers.Upgrades[j]); } file->printf("}"); if(p->AutoAttackTargets.size() > 0) { file->printf("\n \"enemy-targets\", {"); CUnitCache &autoatacktargets = p->AutoAttackTargets; for(unsigned int k = 0; k < autoatacktargets.size();) { CUnit &aatarget = *autoatacktargets[k]; //Additional security if (!aatarget.IsAliveOnMap() || Map.Field(aatarget.tilePos)->Guard[i] == 0) { autoatacktargets.Units.erase(autoatacktargets.Units.begin() + k); aatarget.RefsDecrease(); continue; } if (k) { file->printf(" ,"); } file->printf("\"%s\"", UnitReference(aatarget).c_str()); ++k; } file->printf("}"); } file->printf(")\n\n"); } DebugPrint("FIXME: must save unit-stats?\n"); // // Dump local variables // file->printf("SetThisPlayer(%d)\n\n", ThisPlayer->Index); }
/** ** Save the state of a unit to file. ** ** @param unit Unit pointer to be saved. ** @param file Output file. */ void SaveUnit(const CUnit &unit, CFile *file) { CUnit *uins; int i; file->printf("\nUnit(%d, ", UnitNumber(unit)); // 'type and 'player must be first, needed to create the unit slot file->printf("\"type\", \"%s\", ", unit.Type->Ident.c_str()); if (unit.Seen.Type) { file->printf("\"seen-type\", \"%s\", ", unit.Seen.Type->Ident.c_str()); } file->printf("\"player\", %d,\n ", unit.Player->Index); if (unit.Next) { file->printf("\"next\", %d, ", UnitNumber(*unit.Next)); } file->printf("\"tile\", {%d, %d}, ", unit.tilePos.x, unit.tilePos.y); file->printf("\"refs\", %d, ", unit.Refs); #if 0 // latimerius: why is this so complex? // JOHNS: An unit can be owned by a new player and have still the old stats for (i = 0; i < PlayerMax; ++i) { if (&unit.Type->Stats[i] == unit.Stats) { file->printf("\"stats\", %d,\n ", i); break; } } // latimerius: what's the point of storing a pointer value anyway? if (i == PlayerMax) { file->printf("\"stats\", \"S%08X\",\n ", (int)unit.Stats); } #else file->printf("\"stats\", %d,\n ", unit.Player->Index); #endif file->printf("\"pixel\", {%d, %d}, ", unit.IX, unit.IY); file->printf("\"seen-pixel\", {%d, %d}, ", unit.Seen.IX, unit.Seen.IY); file->printf("\"frame\", %d, ", unit.Frame); if (unit.Seen.Frame != UnitNotSeen) { file->printf("\"seen\", %d, ", unit.Seen.Frame); } else { file->printf("\"not-seen\", "); } file->printf("\"direction\", %d,\n ", unit.Direction); file->printf("\"attacked\", %lu,\n ", unit.Attacked); file->printf(" \"current-sight-range\", %d,", unit.CurrentSightRange); if (unit.Burning) { file->printf(" \"burning\","); } if (unit.Destroyed) { file->printf(" \"destroyed\","); } if (unit.Removed) { file->printf(" \"removed\","); } if (unit.Selected) { file->printf(" \"selected\","); } if (unit.RescuedFrom) { file->printf(" \"rescued-from\", %d,", unit.RescuedFrom->Index); } // n0b0dy: How is this useful? // mr-russ: You can't always load units in order, it saved the information // so you can load a unit whose Container hasn't been loaded yet. // SEE unit loading code. if (unit.Container && unit.Removed) { file->printf(" \"host-info\", {%d, %d, %d, %d}, ", unit.Container->tilePos.x, unit.Container->tilePos.y, unit.Container->Type->TileWidth, unit.Container->Type->TileHeight); } file->printf(" \"seen-by-player\", \""); for (i = 0; i < PlayerMax; ++i) { file->printf("%c", (unit.Seen.ByPlayer & (1 << i)) ? 'X' : '_'); } file->printf("\",\n "); file->printf(" \"seen-destroyed\", \""); for (i = 0; i < PlayerMax; ++i) { file->printf("%c", (unit.Seen.Destroyed & (1 << i)) ? 'X' : '_'); } file->printf("\",\n "); if (unit.Constructed) { file->printf(" \"constructed\","); } if (unit.Seen.Constructed) { file->printf(" \"seen-constructed\","); } file->printf(" \"seen-state\", %d, ", unit.Seen.State); if (unit.Active) { file->printf(" \"active\","); } file->printf("\"ttl\", %lu, ", unit.TTL); for (i = 0; i < (int)UnitTypeVar.GetNumberVariable(); ++i) { file->printf("\"%s\", {Value = %d, Max = %d, Increase = %d, Enable = %s},\n ", UnitTypeVar.VariableNameLookup[i], unit.Variable[i].Value, unit.Variable[i].Max, unit.Variable[i].Increase, unit.Variable[i].Enable ? "true" : "false"); } file->printf("\"group-id\", %d,\n ", unit.GroupId); file->printf("\"last-group\", %d,\n ", unit.LastGroup); file->printf("\"resources-held\", %d,\n ", unit.ResourcesHeld); if (unit.CurrentResource) { file->printf("\"current-resource\", \"%s\",\n ", DefaultResourceNames[unit.CurrentResource].c_str()); } if (unit.SubAction && unit.IsAgressive() && (unit.CurrentAction() == UnitActionStill || unit.CurrentAction() == UnitActionStandGround)) { //Force recalculate Guard points //if unit atack from StandGround then attac target is recalculate //When unit first time handle action code. file->printf("\"sub-action\", 0, "); } else { file->printf("\"sub-action\", %d, ", unit.SubAction); } file->printf("\"wait\", %d, ", unit.Wait); file->printf("\"state\", %d,", unit.State); file->printf("\"anim-wait\", %d,", unit.Anim.Wait); for (i = 0; i < NumAnimations; ++i) { if (AnimationsArray[i] == unit.Anim.CurrAnim) { file->printf("\"curr-anim\", %d,", i); file->printf("\"anim\", %d,", unit.Anim.Anim - unit.Anim.CurrAnim); break; } } if (unit.Anim.Unbreakable) { file->printf(" \"unbreakable\","); } file->printf("\n \"blink\", %d,", unit.Blink); if (unit.Moving) { file->printf(" \"moving\","); } if (unit.ReCast) { file->printf(" \"re-cast\","); } if (unit.Boarded) { file->printf(" \"boarded\","); } if (unit.AutoRepair) { file->printf(" \"auto-repair\","); } if (unit.NextWorker) { if (unit.NextWorker->Destroyed) { /* this unit is destroyed so it's not in the global unit * array - this means it won't be saved!!! */ printf ("FIXME: storing destroyed Worker - loading will fail.\n"); } file->printf(" \"next-worker\", \"%s\",", UnitReference(*unit.NextWorker).c_str()); } file->printf(" \"units-boarded-count\", %d,", unit.BoardCount); if (unit.UnitInside) { file->printf("\n \"units-contained\", {"); uins = unit.UnitInside->PrevContained; for (i = unit.InsideCount; i; --i, uins = uins->PrevContained) { file->printf("\"%s\"", UnitReference(*uins).c_str()); if (i > 1) { file->printf(", "); } } file->printf("},\n "); } Assert((unsigned int)unit.OrderCount == unit.Orders.size()); file->printf("\"order-count\", %d,\n ", unit.OrderCount); file->printf("\"order-flush\", %d,\n ", unit.OrderFlush); file->printf("\"orders\", {"); for (i = 0; i < unit.OrderCount; ++i) { file->printf("\n "); SaveOrder(unit.Orders[i], file); if (i < unit.OrderCount - 1) { file->printf(","); } } file->printf("},\n \"saved-order\", "); SaveOrder((COrderPtr)(&unit.SavedOrder), file); file->printf(",\n \"critical-order\", "); SaveOrder((COrderPtr)(&unit.CriticalOrder), file); file->printf(",\n \"new-order\", "); SaveOrder((COrderPtr)(&unit.NewOrder), file); // // Order data part // switch (unit.CurrentAction()) { case UnitActionStill: // FIXME: support other resource types if (unit.Type->GivesResource) { file->printf(", \"resource-active\", %d", unit.Data.Resource.Active); if (unit.Type->CanHarvest) { file->printf(", \"data-resource\", {\"assigned\", %d", unit.Data.Resource.Assigned); if (unit.Data.Resource.Workers) { if (unit.Data.Resource.Workers->Destroyed) { /* this unit is destroyed so it's not in the global unit * array - this means it won't be saved!!! */ printf ("FIXME: storing destroyed Worker - loading will fail.\n"); } file->printf(", \"first-worker\", \"%s\"", UnitReference(*unit.Data.Resource.Workers).c_str()); } file->printf("}"); } } break; case UnitActionResource: file->printf(", \"data-res-worker\", {\"time-to-harvest\", %d", unit.Data.ResWorker.TimeToHarvest); if (unit.Data.ResWorker.DoneHarvesting) { file->printf(", \"done-harvesting\""); } file->printf("}"); break; case UnitActionBuilt: { CConstructionFrame *cframe; int frame; cframe = unit.Type->Construction->Frames; frame = 0; while (cframe != unit.Data.Built.Frame) { cframe = cframe->Next; ++frame; } file->printf(",\n \"data-built\", {"); if (unit.Data.Built.Worker) { file->printf("\"worker\", \"%s\", ", UnitReference(*unit.Data.Built.Worker).c_str()); } file->printf("\"progress\", %d, \"frame\", %d", unit.Data.Built.Progress, frame); if (unit.Data.Built.Cancel) { file->printf(", \"cancel\""); } file->printf("}"); break; } case UnitActionResearch: file->printf(",\n \"data-research\", {"); file->printf("\"ident\", \"%s\"", unit.Data.Research.Upgrade->Ident.c_str()); file->printf("}"); break; case UnitActionUpgradeTo: file->printf(",\n \"data-upgrade-to\", {"); file->printf("\"ticks\", %d", unit.Data.UpgradeTo.Ticks); file->printf("}"); break; case UnitActionTrain: file->printf(",\n \"data-train\", {"); file->printf("\"ticks\", %d ", unit.Data.Train.Ticks); file->printf("}"); break; default: file->printf(",\n \"data-move\", {"); if (unit.Data.Move.Cycles) { file->printf("\"cycles\", %d,", unit.Data.Move.Cycles); } if (unit.Data.Move.Fast) { file->printf("\"fast\", "); } if (unit.Data.Move.Length > 0) { file->printf("\"path\", {"); for (i = 0; i < unit.Data.Move.Length; ++i) { file->printf("%d, ", unit.Data.Move.Path[i]); } file->printf("}"); } file->printf("}"); break; } if (unit.Goal) { file->printf(",\n \"goal\", %d", UnitNumber(*unit.Goal)); } if (unit.AutoCastSpell) { for (i = 0; (unsigned int) i < SpellTypeTable.size(); ++i) { if (unit.AutoCastSpell[i]) { file->printf(",\n \"auto-cast\", \"%s\"", SpellTypeTable[i]->Ident.c_str()); } } } file->printf(")\n"); }
/** ** Save an order. ** ** @param order Order who should be saved. ** @param file Output file. */ void SaveOrder(const COrderPtr order, CFile *file) { file->printf("{"); switch (order->Action) { case UnitActionNone: file->printf("\"action-none\","); break; case UnitActionStill: file->printf("\"action-still\","); break; case UnitActionStandGround: file->printf("\"action-stand-ground\","); break; case UnitActionFollow: file->printf("\"action-follow\","); break; case UnitActionMove: file->printf("\"action-move\","); break; case UnitActionAttack: file->printf("\"action-attack\","); break; case UnitActionAttackGround: file->printf("\"action-attack-ground\","); break; case UnitActionDie: file->printf("\"action-die\","); break; case UnitActionSpellCast: file->printf("\"action-spell-cast\","); break; case UnitActionTrain: file->printf("\"action-train\","); break; case UnitActionUpgradeTo: file->printf("\"action-upgrade-to\","); break; case UnitActionResearch: file->printf("\"action-research\","); break; case UnitActionBuilt: file->printf("\"action-built\","); break; case UnitActionBoard: file->printf("\"action-board\","); break; case UnitActionUnload: file->printf("\"action-unload\","); break; case UnitActionPatrol: file->printf("\"action-patrol\","); break; case UnitActionBuild: file->printf("\"action-build\","); break; case UnitActionRepair: file->printf("\"action-repair\","); break; case UnitActionResource: file->printf("\"action-resource\","); break; case UnitActionReturnGoods: file->printf("\"action-return-goods\","); break; case UnitActionTransformInto: file->printf("\"action-transform-into\","); break; default: DebugPrint("Unknown action in order\n"); } file->printf(" \"range\", %d,", order->Range); file->printf(" \"width\", %d,", order->Width); file->printf(" \"height\", %d,", order->Height); file->printf(" \"min-range\", %d,", order->MinRange); if (order->HasGoal()) { CUnit &goal = *order->GetGoal(); if (goal.Destroyed) { /* this unit is destroyed so it's not in the global unit * array - this means it won't be saved!!! */ printf ("FIXME: storing destroyed Goal - loading will fail.\n"); } file->printf(" \"goal\", \"%s\",", UnitReference(goal).c_str()); } file->printf(" \"tile\", {%d, %d}", order->goalPos.x, order->goalPos.y); // Extra arg. switch (order->Action) { case UnitActionTrain: case UnitActionUpgradeTo: case UnitActionBuild: case UnitActionTransformInto: file->printf(", \"type\", \"%s\"", order->Arg1.Type->Ident.c_str()); break; case UnitActionPatrol: file->printf(", \"patrol\", {%d, %d}", order->Arg1.Patrol.x, order->Arg1.Patrol.y); break; case UnitActionSpellCast: if (order->Arg1.Spell) { file->printf(", \"spell\", \"%s\"", order->Arg1.Spell->Ident.c_str()); } break; case UnitActionResearch: if (order->Arg1.Upgrade) { file->printf(", \"upgrade\", \"%s\"", order->Arg1.Upgrade->Ident.c_str()); } break; case UnitActionResource : case UnitActionReturnGoods : if (order->CurrentResource) { file->printf(", \"current-resource\", \"%s\",", DefaultResourceNames[order->CurrentResource].c_str()); if(order->CurrentResource == WoodCost) { file->printf(" \"resource-pos\", {%d, %d}", order->Arg1.Resource.Pos.x, order->Arg1.Resource.Pos.y); } else { if (order->Arg1.Resource.Mine->Destroyed) { /* this unit is destroyed so it's not in the global unit * array - this means it won't be saved!!! */ printf ("FIXME: storing destroyed Mine - loading will fail.\n"); } file->printf(" \"resource-mine\", \"%s\"", UnitReference(*order->Arg1.Resource.Mine).c_str()); } } break; default: break; } file->printf("}"); }
UnitReference Unit::get_ref() { return UnitReference(container, id, this); }
/** ** Save the state of a unit to file. ** ** @param unit Unit pointer to be saved. ** @param file Output file. */ void SaveUnit(const CUnit &unit, CFile &file) { file.printf("\nUnit(%d, {", UnitNumber(unit)); // 'type and 'player must be first, needed to create the unit slot file.printf("\"type\", \"%s\", ", unit.Type->Ident.c_str()); if (unit.Seen.Type) { file.printf("\"seen-type\", \"%s\", ", unit.Seen.Type->Ident.c_str()); } file.printf("\"player\", %d,\n ", unit.Player->Index); file.printf("\"tile\", {%d, %d}, ", unit.tilePos.x, unit.tilePos.y); file.printf("\"seen-tile\", {%d, %d}, ", unit.Seen.tilePos.x, unit.Seen.tilePos.y); file.printf("\"refs\", %d, ", unit.Refs); #if 0 // latimerius: why is this so complex? // JOHNS: An unit can be owned by a new player and have still the old stats for (i = 0; i < PlayerMax; ++i) { if (&unit.Type->Stats[i] == unit.Stats) { file.printf("\"stats\", %d,\n ", i); break; } } // latimerius: what's the point of storing a pointer value anyway? if (i == PlayerMax) { file.printf("\"stats\", \"S%08X\",\n ", (int)unit.Stats); } #else file.printf("\"stats\", %d,\n ", unit.Player->Index); #endif file.printf("\"pixel\", {%d, %d}, ", unit.IX, unit.IY); file.printf("\"seen-pixel\", {%d, %d}, ", unit.Seen.IX, unit.Seen.IY); file.printf("\"frame\", %d, ", unit.Frame); if (unit.Seen.Frame != UnitNotSeen) { file.printf("\"seen\", %d, ", unit.Seen.Frame); } else { file.printf("\"not-seen\", "); } file.printf("\"direction\", %d,\n ", unit.Direction); file.printf("\"damage-type\", %d,", unit.DamagedType); file.printf("\"attacked\", %lu,\n ", unit.Attacked); file.printf(" \"current-sight-range\", %d,", unit.CurrentSightRange); if (unit.Burning) { file.printf(" \"burning\","); } if (unit.Destroyed) { file.printf(" \"destroyed\","); } if (unit.Removed) { file.printf(" \"removed\","); } if (unit.Selected) { file.printf(" \"selected\","); } if (unit.Summoned) { file.printf(" \"summoned\","); } if (unit.RescuedFrom) { file.printf(" \"rescued-from\", %d,", unit.RescuedFrom->Index); } // n0b0dy: How is this useful? // mr-russ: You can't always load units in order, it saved the information // so you can load a unit whose Container hasn't been loaded yet. // SEE unit loading code. if (unit.Container && unit.Removed) { file.printf(" \"host-info\", {%d, %d, %d, %d}, ", unit.Container->tilePos.x, unit.Container->tilePos.y, unit.Container->Type->TileWidth, unit.Container->Type->TileHeight); } file.printf(" \"seen-by-player\", \""); for (int i = 0; i < PlayerMax; ++i) { file.printf("%c", (unit.Seen.ByPlayer & (1 << i)) ? 'X' : '_'); } file.printf("\",\n "); file.printf(" \"seen-destroyed\", \""); for (int i = 0; i < PlayerMax; ++i) { file.printf("%c", (unit.Seen.Destroyed & (1 << i)) ? 'X' : '_'); } file.printf("\",\n "); if (unit.Constructed) { file.printf(" \"constructed\","); } if (unit.Seen.Constructed) { file.printf(" \"seen-constructed\","); } file.printf(" \"seen-state\", %d, ", unit.Seen.State); if (unit.Active) { file.printf(" \"active\","); } file.printf("\"ttl\", %lu,\n ", unit.TTL); file.printf("\"threshold\", %d,\n ", unit.Threshold); for (size_t i = 0; i < UnitTypeVar.GetNumberVariable(); ++i) { if (unit.Variable[i] != unit.Type->DefaultStat.Variables[i]) { file.printf("\"%s\", {Value = %d, Max = %d, Increase = %d, Enable = %s},\n ", UnitTypeVar.VariableNameLookup[i], unit.Variable[i].Value, unit.Variable[i].Max, unit.Variable[i].Increase, unit.Variable[i].Enable ? "true" : "false"); } } file.printf("\"group-id\", %d,\n ", unit.GroupId); file.printf("\"last-group\", %d,\n ", unit.LastGroup); file.printf("\"resources-held\", %d,\n ", unit.ResourcesHeld); if (unit.CurrentResource) { file.printf("\"current-resource\", \"%s\",\n ", DefaultResourceNames[unit.CurrentResource].c_str()); } unit.pathFinderData->input.Save(file); unit.pathFinderData->output.Save(file); file.printf("\"wait\", %d, ", unit.Wait); CAnimations::SaveUnitAnim(file, unit); file.printf(",\n \"blink\", %d,", unit.Blink); if (unit.Moving) { file.printf(" \"moving\","); } if (unit.ReCast) { file.printf(" \"re-cast\","); } if (unit.Boarded) { file.printf(" \"boarded\","); } if (unit.AutoRepair) { file.printf(" \"auto-repair\","); } if (unit.NextWorker) { if (unit.NextWorker->Destroyed) { /* this unit is destroyed so it's not in the global unit * array - this means it won't be saved!!! */ printf("FIXME: storing destroyed Worker - loading will fail.\n"); } file.printf(" \"next-worker\", \"%s\",", UnitReference(*unit.NextWorker).c_str()); } if (unit.Resource.Workers != NULL) { file.printf(" \"resource-active\", %d,", unit.Resource.Active); file.printf(" \"resource-assigned\", %d,", unit.Resource.Assigned); file.printf(" \"resource-workers\", \"%s\",", UnitReference(*unit.Resource.Workers).c_str()); } else { Assert(unit.Resource.Active == 0); Assert(unit.Resource.Assigned == 0); } file.printf(" \"units-boarded-count\", %d,", unit.BoardCount); if (unit.UnitInside) { file.printf("\n \"units-contained\", {"); CUnit *uins = unit.UnitInside->PrevContained; for (int i = unit.InsideCount; i; --i, uins = uins->PrevContained) { file.printf("\"%s\"", UnitReference(*uins).c_str()); if (i > 1) { file.printf(", "); } } file.printf("},\n "); } file.printf("\"orders\", {\n"); Assert(unit.Orders.empty() == false); unit.Orders[0]->Save(file, unit); for (size_t i = 1; i != unit.Orders.size(); ++i) { file.printf(",\n "); unit.Orders[i]->Save(file, unit); } file.printf("}"); if (unit.SavedOrder) { file.printf(",\n \"saved-order\", "); unit.SavedOrder->Save(file, unit); } if (unit.CriticalOrder) { file.printf(",\n \"critical-order\", "); unit.CriticalOrder->Save(file, unit); } if (unit.NewOrder) { file.printf(",\n \"new-order\", "); unit.NewOrder->Save(file, unit); } if (unit.Goal) { file.printf(",\n \"goal\", %d", UnitNumber(*unit.Goal)); } if (unit.AutoCastSpell) { for (size_t i = 0; i < SpellTypeTable.size(); ++i) { if (unit.AutoCastSpell[i]) { file.printf(",\n \"auto-cast\", \"%s\"", SpellTypeTable[i]->Ident.c_str()); } } } if (unit.SpellCoolDownTimers) { file.printf(",\n \"spell-cooldown\", {"); for (size_t i = 0; i < SpellTypeTable.size(); ++i) { if (i) { file.printf(" ,"); } file.printf("%d", unit.SpellCoolDownTimers[i]); } file.printf("}"); } file.printf("})\n"); }