diff --git a/src/action/action_resource.cpp b/src/action/action_resource.cpp index 9d4752f2e..1530a7a12 100644 --- a/src/action/action_resource.cpp +++ b/src/action/action_resource.cpp @@ -47,6 +47,8 @@ #include "interface.h" #include "sound.h" #include "map.h" +#include "script.h" +#include "iolib.h" /*---------------------------------------------------------------------------- -- Declarations @@ -66,24 +68,160 @@ -- Functions ----------------------------------------------------------------------------*/ +Vec2i COrder_Resource::GetHarvestLocation() const +{ + return this->Resource.Pos; +} + +bool COrder_Resource::IsGatheringStarted() const +{ + return this->State > SUB_START_GATHERING; +} + +bool COrder_Resource::IsGatheringFinished() const +{ + return this->State >= SUB_STOP_GATHERING; +} + +bool COrder_Resource::IsGatheringWaiting() const +{ + return this->State == SUB_START_GATHERING && this->worker->Wait != 0; +} + +COrder_Resource::~COrder_Resource() +{ + +} + +void COrder_Resource::ReleaseRefs(CUnit &owner) +{ + CUnit *mine = this->Resource.Mine; + + if (mine && mine->IsAlive()) { + owner.DeAssignWorkerFromMine(*mine); + this->Resource.Mine = NULL; + } + if (this->HasGoal()) { + // If mining decrease the active count on the resource. + if (this->State == SUB_GATHER_RESOURCE ) { + CUnit *goal = this->GetGoal(); + + goal->Resource.Active--; + Assert(goal->Resource.Active >= 0); + } + this->ClearGoal(); + } +} + +/* virtual */ void COrder_Resource::Save(CFile &file, const CUnit &unit) const +{ + file.printf("{\"action-resource\","); + if (this->Finished) { + file.printf(" \"finished\","); + } + file.printf(" \"range\", %d,", this->Range); +// file.printf(" \"width\", %d,", order.Width); +// file.printf(" \"height\", %d,", order.Height); +// file.printf(" \"min-range\", %d,", order.MinRange); + if (this->HasGoal()) { + CUnit &goal = *this->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},", 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,\n ", this->State); + SaveDataMove(file); + file.printf("}"); +} + +/* virtual */ bool COrder_Resource::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) +{ + if (this->ParseMoveData(l, j, value)) { + return true; + } else if (!strcmp(value, "current-res")) { + ++j; + lua_rawgeti(l, -1, j + 1); + this->CurrentResource = LuaToNumber(l, -1); + lua_pop(l, 1); + } else if (!strcmp(value, "done-harvesting")) { + lua_rawgeti(l, -1, j + 1); + this->DoneHarvesting = true; + lua_pop(l, 1); + } 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; + lua_rawgeti(l, -1, j + 1); + this->State = LuaToNumber(l, -1); + lua_pop(l, 1); + } else if (!strcmp(value, "timetoharvest")) { + ++j; + lua_rawgeti(l, -1, j + 1); + this->TimeToHarvest = LuaToNumber(l, -1); + lua_pop(l, 1); + } else if (!strcmp(value, "worker")) { + ++j; + lua_rawgeti(l, -1, j + 1); + this->worker = CclGetUnitFromRef(l); + lua_pop(l, 1); + } else { + return false; + } + return true; +} + + /** ** Move unit to terrain. ** ** @return 1 if reached, -1 if unreacheable, 0 if on the way. */ -static int MoveToResource_Terrain(CUnit &unit) +int COrder_Resource::MoveToResource_Terrain(CUnit &unit) { Vec2i pos = unit.CurrentOrder()->goalPos; // Wood gone, look somewhere else. - if ((!Map.ForestOnMap(pos)) && (!unit.IX) && (!unit.IY)) { + if ((Map.Info.IsPointOnMap(pos) == false || Map.ForestOnMap(pos) == false) && (!unit.IX) && (!unit.IY)) { if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 16, unit.Player, unit.CurrentOrder()->goalPos, &pos)) { // no wood in range return -1; } else { - unit.CurrentOrder()->goalPos = pos; - unit.CurrentOrder()->NewResetPath(); + this->goalPos = pos; + this->NewResetPath(); } } switch (DoActionMove(unit)) { @@ -91,8 +229,8 @@ static int MoveToResource_Terrain(CUnit &unit) unit.Wait = 10; if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 9999, unit.Player, unit.tilePos, &pos)) { - unit.CurrentOrder()->goalPos = pos; - unit.CurrentOrder()->NewResetPath(); + this->goalPos = pos; + this->NewResetPath(); DebugPrint("Found a better place to harvest %d,%d\n" _C_ pos.x _C_ pos.y); // FIXME: can't this overflow? It really shouldn't, since // x and y are really supossed to be reachable, checked thorugh a flood fill. @@ -112,9 +250,9 @@ static int MoveToResource_Terrain(CUnit &unit) ** ** @return 1 if reached, -1 if unreacheable, 0 if on the way. */ -static int MoveToResource_Unit(CUnit &unit) +int COrder_Resource::MoveToResource_Unit(CUnit &unit) { - const CUnit *goal = unit.CurrentOrder()->GetGoal(); + const CUnit *goal = this->GetGoal(); Assert(goal); switch (DoActionMove(unit)) { // reached end-point? @@ -139,7 +277,7 @@ static int MoveToResource_Unit(CUnit &unit) ** ** @return 1 if reached, -1 if unreacheable, 0 if on the way. */ -static int MoveToResource(CUnit &unit) +int COrder_Resource::MoveToResource(CUnit &unit) { const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; @@ -150,22 +288,20 @@ static int MoveToResource(CUnit &unit) } } -static void UnitGotoGoal(CUnit &unit, CUnit *const goal, int mode) +void COrder_Resource::UnitGotoGoal(CUnit &unit, CUnit *const goal, int state) { - COrderPtr order = unit.CurrentOrder(); - - if (order->GetGoal() != goal) { - order->SetGoal(goal); + if (this->GetGoal() != goal) { + this->SetGoal(goal); if (goal) { - order->goalPos.x = order->goalPos.y = -1; + this->goalPos.x = this->goalPos.y = -1; } } - order->Range = 1; - order->SubAction.Res = mode; + this->Range = 1; + this->State = state; unit.State = 0; - if (mode == SUB_MOVE_TO_DEPOT || mode == SUB_MOVE_TO_RESOURCE) { - unit.CurrentOrder()->Data.Move.Cycles = 0; //moving counter - unit.CurrentOrder()->NewResetPath(); + if (state == SUB_MOVE_TO_DEPOT || state == SUB_MOVE_TO_RESOURCE) { + this->Data.Move.Cycles = 0; //moving counter + this->NewResetPath(); } } @@ -176,7 +312,7 @@ static void UnitGotoGoal(CUnit &unit, CUnit *const goal, int mode) ** ** @return TRUE if ready, otherwise FALSE. */ -static int StartGathering(CUnit &unit) +int COrder_Resource::StartGathering(CUnit &unit) { CUnit *goal; const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; @@ -191,29 +327,29 @@ static int StartGathering(CUnit &unit) return 0; } #endif - UnitHeadingFromDeltaXY(unit, unit.CurrentOrder()->goalPos - unit.tilePos); + UnitHeadingFromDeltaXY(unit, this->goalPos - unit.tilePos); if (resinfo.WaitAtResource) { - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId]; + this->TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId]; } else { - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = 1; + this->TimeToHarvest = 1; } - unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 0; + this->DoneHarvesting = 0; return 1; } - goal = unit.CurrentOrder()->GetGoal(); - // + goal = this->GetGoal(); + // Target is dead, stop getting resources. - // if (!goal->IsVisibleAsGoal(*unit.Player)) { // Find an alternative, but don't look too far. - unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1; + this->goalPos.x = -1; + this->goalPos.y = -1; if ((goal = UnitFindResource(unit, unit.tilePos, 15, unit.CurrentResource, unit.Player->AiEnabled))) { - unit.CurrentOrder()->SubAction.Res = SUB_START_RESOURCE; - unit.CurrentOrder()->SetGoal(goal); + this->State = SUB_START_RESOURCE; + this->SetGoal(goal); } else { - unit.CurrentOrder()->ClearGoal(); - unit.ClearAction(); + this->ClearGoal(); + this->Finished = true; } return 0; } @@ -221,16 +357,12 @@ static int StartGathering(CUnit &unit) // FIXME: 0 can happen, if to near placed by map designer. Assert(unit.MapDistanceTo(*goal) <= 1); - // // Update the heading of a harvesting unit to looks straight at the resource. - // if (goal) { UnitHeadingFromDeltaXY(unit, goal->tilePos - unit.tilePos + goal->Type->GetHalfTileSize()); } - // // If resource is still under construction, wait! - // if ((goal->Type->MaxOnBoard && goal->Resource.Active >= goal->Type->MaxOnBoard) || goal->CurrentAction() == UnitActionBuilt) { @@ -243,12 +375,10 @@ static int StartGathering(CUnit &unit) return 0; } - // // Place unit inside the resource - // if (!resinfo.HarvestFromOutside) { if (goal->Variable[MAXHARVESTERS_INDEX].Value == 0 || goal->Variable[MAXHARVESTERS_INDEX].Value > goal->InsideCount) { - unit.CurrentOrder()->ClearGoal(); + this->ClearGoal(); unit.Remove(goal); } else if (goal->Variable[MAXHARVESTERS_INDEX].Value <= goal->InsideCount) { //Resource is full, wait @@ -261,13 +391,11 @@ static int StartGathering(CUnit &unit) goal->Resource.Active++; if (resinfo.WaitAtResource) { - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId]; + this->TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId]; } else { - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = 1; + this->TimeToHarvest = 1; } - - unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 0; - + this->DoneHarvesting = 0; return 1; } @@ -289,7 +417,7 @@ static void AnimateActionHarvest(CUnit &unit) ** @param unit pointer to harvester unit. ** @param source pointer to resource unit. */ -static void LoseResource(CUnit &unit, const CUnit &source) +void COrder_Resource::LoseResource(CUnit &unit, const CUnit &source) { CUnit *depot; const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; @@ -298,12 +426,10 @@ static void LoseResource(CUnit &unit, const CUnit &source) || (!unit.Container && resinfo.HarvestFromOutside)); if (resinfo.HarvestFromOutside) { - unit.CurrentOrder()->ClearGoal(); + this->ClearGoal(); } - // // Continue to harvest if we aren't fully loaded - // if (resinfo.HarvestFromOutside && unit.ResourcesHeld < resinfo.ResourceCapacity){ if (unit.Container) { DropOutOnSide(unit, LookingW, &source); @@ -312,32 +438,27 @@ static void LoseResource(CUnit &unit, const CUnit &source) CUnit *goal = UnitFindResource(unit, pos, 15, unit.CurrentResource, 1); if (goal) { - CUnit *mine = unit.CurrentOrder()->Arg1.Resource.Mine; + CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); } unit.AssignWorkerToMine(*goal); - unit.CurrentOrder()->SetGoal(goal); - goal->RefsIncrease(); - unit.CurrentOrder()->Arg1.Resource.Mine = goal; - unit.CurrentOrder()->Range = 1; - unit.CurrentOrder()->goalPos = goal->tilePos; - unit.CurrentOrder()->SubAction.Res = SUB_MOVE_TO_RESOURCE; + this->SetGoal(goal); + this->Resource.Mine = goal; + this->Range = 1; + this->goalPos = goal->tilePos; + this->State = SUB_MOVE_TO_RESOURCE; unit.State = 0; return; } } - // // If we are fully loaded first search for a depot. - // if (unit.ResourcesHeld && (depot = FindDeposit(unit, 1000, unit.CurrentResource))) { if (unit.Container) { DropOutNearest(unit, depot->tilePos + depot->Type->GetHalfTileSize(), &source); } - // // Remember where it mined, so it can look around for another resource. // //FIXME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -347,28 +468,26 @@ static void LoseResource(CUnit &unit, const CUnit &source) _C_ unit.Player->Index _C_ unit.Slot); return; } - // // No depot found, or harvester empty // Dump the unit outside and look for something to do. - // if (unit.Container) { Assert(!resinfo.HarvestFromOutside); DropOutOnSide(unit, LookingW, &source); } - unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1; + this->goalPos.x = -1; + this->goalPos.y = -1; //use depot as goal depot = UnitFindResource(unit, unit.tilePos, 15, unit.CurrentResource, unit.Player->AiEnabled); if (depot) { DebugPrint("%d: Worker %d report: Resource is exhausted, Found another resource.\n" _C_ unit.Player->Index _C_ unit.Slot); - unit.CurrentOrder()->SubAction.Res = SUB_START_RESOURCE; + this->State = SUB_START_RESOURCE; unit.State = 0; - unit.CurrentOrder()->SetGoal(depot); + this->SetGoal(depot); } else { DebugPrint("%d: Worker %d report: Resource is exhausted, Just sits around confused.\n" _C_ unit.Player->Index _C_ unit.Slot); - unit.ClearAction(); - unit.CurrentOrder()->ClearGoal(); //just in case + this->Finished = true; unit.State = 0; } } @@ -382,18 +501,13 @@ static void LoseResource(CUnit &unit, const CUnit &source) ** ** @return non-zero if ready, otherwise zero. */ -static int GatherResource(CUnit &unit) +int COrder_Resource::GatherResource(CUnit &unit) { CUnit *source = 0; - CUnit *uins; const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; - int i; int addload; if (!resinfo.HarvestFromOutside && unit.Container != NULL) { -#if 0 -// unit.Container->SubAction = SUB_GATHER_RESOURCE; -#endif UnitShowAnimation(*unit.Container, unit.Container->Type->Animations->Harvest[unit.CurrentResource]); } @@ -403,18 +517,18 @@ static int GatherResource(CUnit &unit) unit.Anim.CurrAnim = NULL; } - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest--; + this->TimeToHarvest--; - if (unit.CurrentOrder()->Data.ResWorker.DoneHarvesting) { + if (this->DoneHarvesting) { Assert(resinfo.HarvestFromOutside || resinfo.TerrainHarvester); return !unit.Anim.Unbreakable; } // Target gone? - if (resinfo.TerrainHarvester && !Map.ForestOnMap(unit.CurrentOrder()->goalPos)) { + if (resinfo.TerrainHarvester && !Map.ForestOnMap(this->goalPos)) { if (!unit.Anim.Unbreakable) { // Action now breakable, move to resource again. - unit.CurrentOrder()->SubAction.Res = SUB_MOVE_TO_RESOURCE; + this->State = SUB_MOVE_TO_RESOURCE; // Give it some reasonable look while searching. // FIXME: which frame? unit.Frame = 0; @@ -423,18 +537,15 @@ static int GatherResource(CUnit &unit) // No wood? Freeze!!! } - while (!unit.CurrentOrder()->Data.ResWorker.DoneHarvesting && - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest < 0) { + while (!this->DoneHarvesting && this->TimeToHarvest < 0) { //FIXME: rb - how should it look for WaitAtResource == 0 if (resinfo.WaitAtResource) { - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest += resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId]; + this->TimeToHarvest += resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId]; } else { - unit.CurrentOrder()->Data.ResWorker.TimeToHarvest += 1; + this->TimeToHarvest += 1; } - // // Calculate how much we can load. - // if (resinfo.ResourceStep) { addload = resinfo.ResourceStep; } else { @@ -449,11 +560,11 @@ static int GatherResource(CUnit &unit) unit.ResourcesHeld += addload; if (addload && unit.ResourcesHeld == resinfo.ResourceCapacity) { - Map.ClearTile(MapFieldForest, unit.CurrentOrder()->goalPos); + Map.ClearTile(MapFieldForest, this->goalPos); } } else { if (resinfo.HarvestFromOutside) { - source = unit.CurrentOrder()->GetGoal(); + source = this->GetGoal(); } else { source = unit.Container; } @@ -461,33 +572,29 @@ static int GatherResource(CUnit &unit) Assert(source); Assert(source->ResourcesHeld <= 655350); bool is_visible = source->IsVisibleAsGoal(*unit.Player); - // // Target is not dead, getting resources. - // if (is_visible) { // Don't load more that there is. if (addload > source->ResourcesHeld) { addload = source->ResourcesHeld; } - unit.ResourcesHeld += addload; source->ResourcesHeld -= addload; } - // // End of resource: destroy the resource. // FIXME: implement depleted resources. - // if ((!is_visible) || (source->ResourcesHeld == 0)) { if (unit.Anim.Unbreakable) { return 0; } DebugPrint("%d: Worker %d report: Resource is destroyed\n" _C_ unit.Player->Index _C_ unit.Slot); bool dead = source->CurrentAction() == UnitActionDie; - // + // Improved version of DropOutAll that makes workers go to the depot. - // LoseResource(unit, *source); + int i; + CUnit *uins; for (i = source->InsideCount, uins = source->UnitInside; i; --i, uins = uins->NextContained) { if (uins->CurrentOrder()->Action == UnitActionResource) { @@ -507,19 +614,20 @@ static int GatherResource(CUnit &unit) if (resinfo.TerrainHarvester) { if (unit.ResourcesHeld == resinfo.ResourceCapacity) { // Mark as complete. - unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 1; + this->DoneHarvesting = true; } return 0; - } else + } else { if (resinfo.HarvestFromOutside) { if ((unit.ResourcesHeld == resinfo.ResourceCapacity) || (source == NULL)) { // Mark as complete. - unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 1; + this->DoneHarvesting = true; } return 0; } else { return unit.ResourcesHeld == resinfo.ResourceCapacity && source; } + } } return 0; } @@ -531,7 +639,10 @@ int GetNumWaitingWorkers(const CUnit &mine) for (int i = 0; NULL != worker; worker = worker->NextWorker, ++i) { - if (worker->CurrentOrder()->SubAction.Res == SUB_START_GATHERING && worker->Wait) { + Assert(worker->CurrentAction() == UnitActionResource); + COrder_Resource &order = *static_cast<COrder_Resource*>(worker->CurrentOrder()); + + if (order.IsGatheringWaiting()) { ret++; } Assert(i <= mine.Resource.Assigned); @@ -546,31 +657,22 @@ int GetNumWaitingWorkers(const CUnit &mine) ** ** @return TRUE if ready, otherwise FALSE. */ -static int StopGathering(CUnit &unit) +int COrder_Resource::StopGathering(CUnit &unit) { CUnit *source = 0; const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; if (!resinfo.TerrainHarvester) { if (resinfo.HarvestFromOutside) { - source = unit.CurrentOrder()->GetGoal(); - unit.CurrentOrder()->ClearGoal(); + source = this->GetGoal(); + this->ClearGoal(); } else { source = unit.Container; } source->Resource.Active--; Assert(source->Resource.Active >= 0); -#if 0 - if (!resinfo.HarvestFromOutside && source->Resource.Active == 0) { - source->SubAction = 1; - } -#endif //Store resource position. - if (unit.Orders[0]->Arg1.Resource.Mine) { - unit.Orders[0]->Arg1.Resource.Mine->RefsDecrease(); - } - source->RefsIncrease(); - unit.Orders[0]->Arg1.Resource.Mine = source; + this->Resource.Mine = source; if (source->Type->MaxOnBoard) { int count = 0; @@ -578,11 +680,14 @@ static int StopGathering(CUnit &unit) CUnit *next = NULL; for(; NULL != worker; worker = worker->NextWorker) { - if (worker != &unit && worker->CurrentOrder()->SubAction.Res == SUB_START_GATHERING && worker->Wait) { + Assert(worker->CurrentAction() == UnitActionResource); + COrder_Resource& order = *static_cast<COrder_Resource*>(worker->CurrentOrder()); + if (worker != &unit && order.IsGatheringWaiting()) { count++; if (next) { - if (next->Wait > worker->Wait) + if (next->Wait > worker->Wait) { next = worker; + } } else { next = worker; } @@ -604,8 +709,8 @@ static int StopGathering(CUnit &unit) } } else { // Store resource position. - unit.CurrentOrder()->Arg1.Resource.Pos = unit.tilePos; - Assert(unit.CurrentOrder()->Arg1.Resource.Mine == NULL); + this->Resource.Pos = unit.tilePos; + Assert(this->Resource.Mine == NULL); } #ifdef DEBUG @@ -621,18 +726,16 @@ static int StopGathering(CUnit &unit) Assert(unit.Container); DropOutOnSide(unit, LookingW, source); } - CUnit *mine = unit.Orders[0]->Arg1.Resource.Mine; + CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); - unit.Orders[0]->Arg1.Resource.Mine = NULL; + this->Resource.Mine = NULL; } DebugPrint("%d: Worker %d report: Can't find a resource [%d] deposit.\n" _C_ unit.Player->Index _C_ unit.Slot _C_ unit.CurrentResource); - unit.CurrentOrder()->ClearGoal(); - unit.ClearAction(); + this->Finished = true; return 0; } else { if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) { @@ -644,7 +747,9 @@ static int StopGathering(CUnit &unit) if (IsOnlySelected(unit)) { SelectedUnitChanged(); } - return unit.CurrentAction() != UnitActionStill; +#if 1 + return 1; +#endif } extern void AiNewDepotRequest(CUnit &worker); @@ -656,12 +761,12 @@ extern void AiNewDepotRequest(CUnit &worker); ** ** @return TRUE if reached, otherwise FALSE. */ -static int MoveToDepot(CUnit &unit) +int COrder_Resource::MoveToDepot(CUnit &unit) { const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; - CUnit *goal = unit.CurrentOrder()->GetGoal(); - CPlayer& player = *unit.Player; - Assert(goal); + CUnit &goal = *this->GetGoal(); + CPlayer &player = *unit.Player; + Assert(&goal); switch (DoActionMove(unit)) { // reached end-point? case PF_UNREACHABLE: @@ -669,7 +774,7 @@ static int MoveToDepot(CUnit &unit) case PF_REACHED: break; default: - if (unit.Anim.Unbreakable || goal->IsVisibleAsGoal(player)) { + if (unit.Anim.Unbreakable || goal.IsVisibleAsGoal(player)) { return 0; } break; @@ -678,7 +783,7 @@ static int MoveToDepot(CUnit &unit) // // Target is dead, stop getting resources. // - if (!goal->IsVisibleAsGoal(player)) { + if (!goal.IsVisibleAsGoal(player)) { DebugPrint("%d: Worker %d report: Destroyed depot\n" _C_ player.Index _C_ unit.Slot); unit.CurrentOrder()->ClearGoal(); @@ -693,28 +798,28 @@ static int MoveToDepot(CUnit &unit) _C_ player.Index _C_ unit.Slot); // FIXME: perhaps we should choose an alternative - unit.ClearAction(); + this->Finished = true; } return 0; } // Not ready - if (player.AiEnabled && unit.CurrentOrder()->Data.Move.Cycles > 300) { + if (player.AiEnabled && this->Data.Move.Cycles > 300) { AiNewDepotRequest(unit); } // If resource depot is still under construction, wait! - if (goal->CurrentOrder()->Action == UnitActionBuilt) { + if (goal.CurrentAction() == UnitActionBuilt) { unit.Wait = 10; return 0; } - unit.CurrentOrder()->ClearGoal(); + this->ClearGoal(); unit.Wait = resinfo.WaitAtDepot; // Place unit inside the depot if (unit.Wait) { - unit.Remove(goal); + unit.Remove(&goal); unit.Anim.CurrAnim = NULL; } @@ -743,7 +848,7 @@ static int MoveToDepot(CUnit &unit) ** ** @return TRUE if ready, otherwise FALSE. */ -static int WaitInDepot(CUnit &unit) +bool COrder_Resource::WaitInDepot(CUnit &unit) { const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; const CUnit *depot = ResourceDepositOnMap(unit.tilePos, resinfo.ResourceId); @@ -752,21 +857,22 @@ static int WaitInDepot(CUnit &unit) // Range hardcoded. don't stray too far though if (resinfo.TerrainHarvester) { - Vec2i pos = unit.CurrentOrder()->Arg1.Resource.Pos; + Vec2i pos = this->Resource.Pos; if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 10, unit.Player, pos, &pos)) { if (depot) { DropOutNearest(unit, pos, depot); } - unit.CurrentOrder()->goalPos = pos; + this->goalPos = pos; } else { if (depot) { DropOutOnSide(unit, LookingW, depot); } - unit.ClearAction(); + this->Finished = true; + return false; } } else { - CUnit *mine = unit.CurrentOrder()->Arg1.Resource.Mine; + CUnit *mine = this->Resource.Mine; const int range = (mine ? 15 : 1000); const Vec2i pos = mine ? mine->tilePos : unit.tilePos; CUnit *goal = UnitFindResource(unit, pos, range, unit.CurrentResource, unit.Player->AiEnabled, depot); @@ -779,15 +885,13 @@ static int WaitInDepot(CUnit &unit) if (goal != mine) { if (mine) { unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); } unit.AssignWorkerToMine(*goal); - goal->RefsIncrease(); - unit.CurrentOrder()->Arg1.Resource.Mine = goal; + this->Resource.Mine = goal; } - unit.CurrentOrder()->SetGoal(goal); - unit.CurrentOrder()->Range = 1; - unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1; + this->SetGoal(goal); + this->Range = 1; + this->goalPos.x = this->goalPos.y = -1; } else { DebugPrint("%d: Worker %d report: [%d,%d] Resource gone near [%d,%d] in range %d. Sit and play dumb.\n" _C_ unit.Player->Index _C_ unit.Slot @@ -798,19 +902,18 @@ static int WaitInDepot(CUnit &unit) } if (mine) { unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); - unit.CurrentOrder()->Arg1.Resource.Mine = NULL; + this->Resource.Mine = NULL; } - unit.ClearAction(); + this->Finished = true; + return false; } } - return unit.CurrentAction() != UnitActionStill; + return true; } -void DropResource(CUnit &unit) +void COrder_Resource::DropResource(CUnit &unit) { if (unit.CurrentResource) { - COrderPtr order = unit.CurrentOrder(); const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; if (resinfo.LoseResources && unit.ResourcesHeld < resinfo.ResourceCapacity) { unit.ResourcesHeld = 0; @@ -819,16 +922,14 @@ void DropResource(CUnit &unit) unit.ResourcesHeld = 0; } if (!resinfo.TerrainHarvester) { - CUnit *mine = order->Arg1.Resource.Mine; + CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); } } //fast clean both resource data: pos and mine - order->Arg1.Resource.Mine = NULL; + this->Resource.Mine = NULL; unit.CurrentResource = 0; - order->CurrentResource = 0; } } @@ -837,12 +938,12 @@ void DropResource(CUnit &unit) ** ** @param unit Pointer to unit. */ -void ResourceGiveUp(CUnit &unit) +void COrder_Resource::ResourceGiveUp(CUnit &unit) { DebugPrint("%d: Worker %d report: Gave up on resource gathering.\n" _C_ unit.Player->Index _C_ unit.Slot); - unit.CurrentOrder()->ClearGoal(); + this->ClearGoal(); DropResource(unit); - unit.ClearAction(); + this->Finished = true; } /** @@ -850,11 +951,11 @@ void ResourceGiveUp(CUnit &unit) ** ** return false if action is canceled, true otherwise. */ -static bool ActionResourceInit(CUnit &unit) +bool COrder_Resource::ActionResourceInit(CUnit &unit) { - Assert(unit.CurrentOrder()->SubAction.Res == SUB_START_RESOURCE); + Assert(this->State == SUB_START_RESOURCE); - CUnit *const goal = unit.CurrentOrder()->GetGoal(); + CUnit *const goal = this->GetGoal(); int newres; if (goal) { @@ -872,20 +973,17 @@ static bool ActionResourceInit(CUnit &unit) ResourceGiveUp(unit); return false; } - COrderPtr order = unit.CurrentOrder(); - order->CurrentResource = newres; - if (goal && order->Arg1.Resource.Mine != goal) { - CUnit *mine = order->Arg1.Resource.Mine; + this->CurrentResource = newres; + if (goal && this->Resource.Mine != goal) { + CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); - order->Arg1.Resource.Mine = NULL; + this->Resource.Mine = NULL; } if (goal->CurrentAction() != UnitActionBuilt) { unit.AssignWorkerToMine(*goal); - goal->RefsIncrease(); - order->Arg1.Resource.Mine = goal; + this->Resource.Mine = goal; } } UnitGotoGoal(unit, goal, SUB_MOVE_TO_RESOURCE); @@ -899,7 +997,7 @@ static bool ActionResourceInit(CUnit &unit) ** ** @param unit Pointer to unit. */ -void HandleActionResource(COrder& order, CUnit &unit) +void COrder_Resource::Execute(CUnit &unit) { if (unit.Wait) { // FIXME: show idle animation while we wait? @@ -908,33 +1006,29 @@ void HandleActionResource(COrder& order, CUnit &unit) } // Let's start mining. - if (order.SubAction.Res == SUB_START_RESOURCE) { + if (this->State == SUB_START_RESOURCE) { if (ActionResourceInit(unit) == false) { return; } } // Move to the resource location. - if (SUB_MOVE_TO_RESOURCE <= order.SubAction.Res && order.SubAction.Res < SUB_UNREACHABLE_RESOURCE) { + if (SUB_MOVE_TO_RESOURCE <= this->State && this->State < SUB_UNREACHABLE_RESOURCE) { const int ret = MoveToResource(unit); - switch (ret) - { - case -1: // Can't Reach - { - order.SubAction.Res++; + switch (ret) { + case -1: { // Can't Reach + this->State++; unit.Wait = 5; return; } - case 1: // Reached - { - order.SubAction.Res = SUB_START_GATHERING; + case 1: { // Reached + this->State = SUB_START_GATHERING; break; } case 0: // Move along. return; - default: - { + default: { Assert(0); break; } @@ -942,59 +1036,55 @@ void HandleActionResource(COrder& order, CUnit &unit) } // Resource seems to be unreachable - if (order.SubAction.Res == SUB_UNREACHABLE_RESOURCE) { + if (this->State == SUB_UNREACHABLE_RESOURCE) { ResourceGiveUp(unit); return; } // Start gathering the resource - if (order.SubAction.Res == SUB_START_GATHERING) { + if (this->State == SUB_START_GATHERING) { if (StartGathering(unit)) { - order.SubAction.Res = SUB_GATHER_RESOURCE; + this->State = SUB_GATHER_RESOURCE; } else { return; } } // Gather the resource. - if (order.SubAction.Res == SUB_GATHER_RESOURCE) { + if (this->State == SUB_GATHER_RESOURCE) { if (GatherResource(unit)) { - order.SubAction.Res = SUB_STOP_GATHERING; + this->State = SUB_STOP_GATHERING; } else { return; } } // Stop gathering the resource. - if (order.SubAction.Res == SUB_STOP_GATHERING) { + if (this->State == SUB_STOP_GATHERING) { if (StopGathering(unit)) { - order.SubAction.Res = SUB_MOVE_TO_DEPOT; - order.Data.Move.Cycles = 0; //moving counter + this->State = SUB_MOVE_TO_DEPOT; + this->Data.Move.Cycles = 0; //moving counter } else return; } // Move back home. - if (SUB_MOVE_TO_DEPOT <= order.SubAction.Res && order.SubAction.Res < SUB_UNREACHABLE_DEPOT) { + if (SUB_MOVE_TO_DEPOT <= this->State && this->State < SUB_UNREACHABLE_DEPOT) { const int ret = MoveToDepot(unit); - switch (ret) - { - case -1: // Can't Reach - { - order.SubAction.Res++; + switch (ret) { + case -1: { // Can't Reach + this->State++; unit.Wait = 5; return; } - case 1: // Reached - { - order.SubAction.Res = SUB_RETURN_RESOURCE; + case 1: { // Reached + this->State = SUB_RETURN_RESOURCE; return; } case 0: // Move along. return; - default: - { + default: { Assert(0); return; } @@ -1002,15 +1092,15 @@ void HandleActionResource(COrder& order, CUnit &unit) } // Depot seems to be unreachable - if (order.SubAction.Res == SUB_UNREACHABLE_DEPOT) { + if (this->State == SUB_UNREACHABLE_DEPOT) { ResourceGiveUp(unit); return; } // Unload resources at the depot. - if (order.SubAction.Res == SUB_RETURN_RESOURCE) { + if (this->State == SUB_RETURN_RESOURCE) { if (WaitInDepot(unit)) { - order.SubAction.Res = SUB_START_RESOURCE; + this->State = SUB_START_RESOURCE; // It's posible, though very rare that the unit's goal blows up // this cycle, but after this unit. Thus, next frame the unit @@ -1018,9 +1108,8 @@ void HandleActionResource(COrder& order, CUnit &unit) // are already in SUB_MOVE_TO_RESOURCE then we can handle it. // So, we pass through SUB_START_RESOURCE the very instant it // goes out of the depot. - HandleActionResource(order, unit); +// HandleActionResource(order, unit); } - return; } } diff --git a/src/action/action_returngoods.cpp b/src/action/action_returngoods.cpp index 846ada886..3c4d18084 100644 --- a/src/action/action_returngoods.cpp +++ b/src/action/action_returngoods.cpp @@ -47,7 +47,7 @@ /*---------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------*/ - +#if 0 /** ** Return goods to gold/wood deposit. ** @@ -90,5 +90,5 @@ void HandleActionReturnGoods(COrder& order, CUnit &unit) order.NewResetPath(); order.SubAction.Res = /* SUB_MOVE_TO_DEPOT */ 70; // FIXME : Define value. } - +#endif //@} diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp index ec386d3e9..12d0bdeeb 100644 --- a/src/action/action_still.cpp +++ b/src/action/action_still.cpp @@ -59,7 +59,7 @@ enum { /* virtual */ void COrder_Still::Save(CFile &file, const CUnit &unit) const { if (this->Action == UnitActionStill) { - file.printf("{\"action-still\""); + file.printf("{\"action-still\","); } else { file.printf("{\"action-stand-ground\","); } @@ -76,7 +76,7 @@ enum { file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str()); } - file.printf(", \"state\", %d", this->State); + file.printf("\"state\", %d", this->State); file.printf("}"); } diff --git a/src/action/actions.cpp b/src/action/actions.cpp index 752eaa2c0..a699e67c4 100644 --- a/src/action/actions.cpp +++ b/src/action/actions.cpp @@ -269,7 +269,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures /* static */ COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos) { - COrder *order = new COrder(UnitActionResource); + COrder_Resource *order = new COrder_Resource(harvester); Vec2i ressourceLoc; // Find the closest piece of wood next to a tile where the unit can move @@ -286,16 +286,21 @@ unsigned SyncHash; /// Hash calculated to find sync failures ressourceLoc = pos; } order->goalPos = ressourceLoc; + order->CurrentResource = WoodCost; // Hard-coded resource. order->Range = 1; return order; } -/* static */ COrder* COrder::NewActionResource(CUnit &mine) +/* static */ COrder* COrder::NewActionResource(CUnit &harvester, CUnit &mine) { - COrder *order = new COrder(UnitActionResource); + COrder_Resource *order = new COrder_Resource(harvester); order->SetGoal(&mine); + order->Resource.Mine = &mine; + harvester.AssignWorkerToMine(mine); + order->Resource.Pos = mine.tilePos + mine.Type->GetHalfTileSize(); + order->CurrentResource = mine.Type->GivesResource; order->Range = 1; return order; @@ -303,16 +308,25 @@ unsigned SyncHash; /// Hash calculated to find sync failures -/* static */ COrder* COrder::NewActionReturnGoods(CUnit *depot) +/* static */ COrder* COrder::NewActionReturnGoods(CUnit &harvester, CUnit *depot) { - COrder *order = new COrder(UnitActionReturnGoods); + COrder_Resource *order = new COrder_Resource(harvester); // Destination could be killed. NETWORK! - if (depot && !depot->Destroyed) { - order->SetGoal(depot); + if (depot && depot->Destroyed) { + depot = NULL; } order->Range = 1; + order->CurrentResource = harvester.CurrentResource; + order->DoneHarvesting = true; + if (depot == NULL) { + depot = FindDeposit(harvester, 1000, harvester.CurrentResource); + } + order->Depot = depot; + if (depot) { + order->UnitGotoGoal(harvester, depot, 70); //SUB_MOVE_TO_DEPOT); + } return order; } @@ -403,15 +417,9 @@ COrder* COrder::Clone() const clone->MinRange = this->MinRange; clone->Width = this->Width; clone->Height = this->Height; - clone->CurrentResource = this->CurrentResource; clone->SetGoal(this->Goal); clone->goalPos = this->goalPos; - memcpy(&clone->Arg1, &this->Arg1, sizeof (clone->Arg1)); memcpy(&clone->Data, &this->Data, sizeof (clone->Data)); - //FIXME: Hardcoded wood - if (clone->Action == UnitActionResource && clone->Arg1.Resource.Mine) { - clone->Arg1.Resource.Mine->RefsIncrease(); - } return clone; } @@ -421,47 +429,6 @@ COrder::~COrder() Goal->RefsDecrease(); Goal = NoUnitP; } - if (Action == UnitActionResource && Arg1.Resource.Mine) { - Arg1.Resource.Mine->RefsDecrease(); - Arg1.Resource.Mine = NoUnitP; - } -} - -void COrder::ReleaseRefs(CUnit &unit) -{ - // Release pending references. - if (this->Action == UnitActionResource) { - CUnit *mine = this->Arg1.Resource.Mine; - - if (mine) { - unit.DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); - this->Arg1.Resource.Mine = NULL; - - } - } - if (this->HasGoal()) { - // If mining decrease the active count on the resource. - if (this->Action == UnitActionResource) { - if (this->SubAction.Res == 60 /* SUB_GATHER_RESOURCE */ ) { - CUnit *goal = this->GetGoal(); - - goal->Resource.Active--; - Assert(goal->Resource.Active >= 0); - } - } - // Still shouldn't have a reference unless attacking - Assert(this->Action != UnitActionStill); - this->ClearGoal(); - } -#ifdef DEBUG - else { - if (unit.CurrentResource && - !unit.Type->ResInfo[unit.CurrentResource]->TerrainHarvester) { - Assert(this->Action != UnitActionResource); - } - } -#endif } void COrder::SetGoal(CUnit *const new_goal) @@ -511,21 +478,6 @@ bool COrder::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/) case UnitActionTransformInto: case UnitActionBoard: case UnitActionUnload: - case UnitActionReturnGoods: - // Unit is working ? - // Maybe AI should cancel action and save resources ??? - return true; - case UnitActionResource: - if (SubAction.Res >= 65) { - //Normal return to depot - return true; - } - if (SubAction.Res > 55 && - unit.ResourcesHeld > 0) { - //escape to Depot with this what you have; - Data.ResWorker.DoneHarvesting = 1; - return true; - } break; case UnitActionAttack: { @@ -1350,8 +1302,8 @@ static void (*HandleActionTable[256])(COrder&, CUnit &) = { HandleActionNone, // HandleActionPatrol, HandleActionNone, // HandleActionBuild, HandleActionNone, // HandleActionRepair, - HandleActionResource, - HandleActionReturnGoods, + HandleActionNone, // HandleActionResource, + HandleActionNone, // HandleActionReturnGoods, HandleActionNone, // HandleActionTransformInto, HandleActionNotWritten, diff --git a/src/action/command.cpp b/src/action/command.cpp index 47ef0f163..6a1999fc5 100644 --- a/src/action/command.cpp +++ b/src/action/command.cpp @@ -536,7 +536,7 @@ void CommandResource(CUnit &unit, CUnit &dest, int flush) return; } } - *order = COrder::NewActionResource(dest); + *order = COrder::NewActionResource(unit, dest); ClearSavedAction(unit); } @@ -568,7 +568,7 @@ void CommandReturnGoods(CUnit &unit, CUnit *goal, int flush) return; } } - *order = COrder::NewActionReturnGoods(goal); + *order = COrder::NewActionReturnGoods(unit, goal); ClearSavedAction(unit); } diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp index c4d7f3d62..58cb318b9 100644 --- a/src/ai/ai_resource.cpp +++ b/src/ai/ai_resource.cpp @@ -237,14 +237,13 @@ static int AiBuildBuilding(const CUnitType &type, CUnitType &building, int near_ for (j = 0; j < unit.Orders.size(); ++j) { int action = unit.Orders[j]->Action; if (action == UnitActionBuild || - action == UnitActionRepair || - action == UnitActionReturnGoods) { + action == UnitActionRepair) { break; } if (action == UnitActionResource) { - const COrder &order = *unit.Orders[j]; + const COrder_Resource &order = *static_cast<const COrder_Resource*>(unit.Orders[j]); - if (order.SubAction.Res > 55 /* SUB_START_GATHERING */) { + if (order.IsGatheringStarted()) { break; } } @@ -330,18 +329,10 @@ void AiNewDepotRequest(CUnit &worker) { _C_ worker->Data.Move.Cycles ); */ + Assert(worker.CurrentAction() == UnitActionResource); + COrder_Resource &order = *static_cast<COrder_Resource*>(worker.CurrentOrder()); - Vec2i pos = {-1, -1}; - ResourceInfo *resinfo = worker.Type->ResInfo[worker.CurrentResource]; - - if (resinfo->TerrainHarvester) { - pos = worker.CurrentOrder()->Arg1.Resource.Pos; - } else { - CUnit *mine = worker.CurrentOrder()->Arg1.Resource.Mine; - if (mine) { - pos = mine->tilePos; - } - } + const Vec2i pos = order.GetHarvestLocation(); if (pos.x != -1 && NULL != FindDepositNearLoc(*worker.Player, pos, 10, worker.CurrentResource)) { /* @@ -1098,9 +1089,10 @@ static void AiCollectResources() for (int k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) { unit = units_assigned[src_c][k]; - COrder &order = *unit->CurrentOrder(); + Assert(unit->CurrentAction() == UnitActionResource); + COrder_Resource &order = *static_cast<COrder_Resource*>(unit->CurrentOrder()); - if (order.SubAction.Res >= 65 /* SUB_STOP_GATHERING */ ) { + if (order.IsGatheringFinished()) { //worker returning with resource continue; } @@ -1173,9 +1165,9 @@ static int AiRepairBuilding(const CUnitType &type, CUnit &building) if (unit.CurrentAction() == UnitActionStill) { table[num++] = &unit; } else if (unit.CurrentAction() == UnitActionResource) { - COrder &order = *unit.CurrentOrder(); + COrder_Resource &order = *static_cast<COrder_Resource*>(unit.CurrentOrder()); - if (order.SubAction.Res <= 55 /* SUB_START_GATHERING */) { + if (order.IsGatheringStarted() == false) { table[num++] = &unit; } } diff --git a/src/include/actions.h b/src/include/actions.h index 0786948b6..77ce35a92 100644 --- a/src/include/actions.h +++ b/src/include/actions.h @@ -83,7 +83,7 @@ enum UnitAction { UnitActionRepair, /// unit repairing UnitActionResource, /// unit harvesting resources - UnitActionReturnGoods, /// unit returning any resource + UnitActionDummy, // UnitActionReturnGoods, /// unit returning any resource UnitActionTransformInto /// unit transform into type. }; @@ -104,11 +104,10 @@ class COrder public: COrder(int action) : Goal(NULL), Range(0), MinRange(0), Width(0), - Height(0), Action(action), Finished(false), CurrentResource(0) + Height(0), Action(action), Finished(false) { goalPos.x = -1; goalPos.y = -1; - memset(&Arg1, 0, sizeof (Arg1)); memset(&SubAction, 0, sizeof (SubAction)); memset(&Data, 0, sizeof (Data)); } @@ -127,7 +126,7 @@ public: virtual void FillSeenValues(CUnit &unit) const; virtual void AiUnitKilled(CUnit &unit); - void ReleaseRefs(CUnit &owner); + void ReleaseRefs(CUnit &owner) {} bool CheckRange() const; bool HasGoal() const { return Goal != NULL; } @@ -159,8 +158,8 @@ public: static COrder* NewActionRepair(const Vec2i &pos); static COrder* NewActionResearch(CUnit &unit, CUpgrade &upgrade); static COrder* NewActionResource(CUnit &harvester, const Vec2i &pos); - static COrder* NewActionResource(CUnit &mine); - static COrder* NewActionReturnGoods(CUnit *depot); + static COrder* NewActionResource(CUnit &harvester, CUnit &mine); + static COrder* NewActionReturnGoods(CUnit &harvester, CUnit *depot); static COrder* NewActionSpellCast(SpellType &spell, const Vec2i &pos, CUnit *target); static COrder* NewActionStandGround(); static COrder* NewActionStill(); @@ -172,8 +171,6 @@ public: #if 1 // currently needed for parsing static COrder* NewActionAttack() { return new COrder(UnitActionAttack); } static COrder* NewActionAttackGround() { return new COrder(UnitActionAttackGround); } - static COrder* NewActionResource() { return new COrder(UnitActionResource); } - static COrder* NewActionReturnGoods() { return new COrder(UnitActionReturnGoods); } #endif private: @@ -184,22 +181,13 @@ public: unsigned int MinRange; /// How far away minimum unsigned char Width; /// Goal Width (used when Goal is not) unsigned char Height; /// Goal Height (used when Goal is not) - unsigned char Action; /// global action + const unsigned char Action; /// global action bool Finished; /// true when order is finish - unsigned char CurrentResource; ///used in UnitActionResource and UnitActionReturnGoods Vec2i goalPos; /// or tile coordinate of destination - union { - struct { - Vec2i Pos; /// position for terrain resource. - CUnit *Mine; - } Resource; - } Arg1; /// Extra command argument. - union { int Attack; - int Res; } SubAction; @@ -211,13 +199,10 @@ public: #define MAX_PATH_LENGTH 28 /// max length of precalculated path char Path[MAX_PATH_LENGTH]; /// directions of stored path } Move; /// ActionMove,... - struct _order_resource_worker_ { - int TimeToHarvest; /// how much time until we harvest some more. - unsigned DoneHarvesting:1; /// Harvesting done, wait for action to break. - } ResWorker; /// Worker harvesting } Data; /// Storage room for different commands }; + class COrder_Board : public COrder { friend COrder* COrder::NewActionBoard(CUnit &unit); @@ -409,6 +394,63 @@ private: CUpgrade *Upgrade; }; +class COrder_Resource : public COrder +{ + friend COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos); + friend COrder* COrder::NewActionResource(CUnit &harvester, CUnit &mine); + friend COrder* COrder::NewActionReturnGoods(CUnit &harvester, CUnit *depot); + +public: + COrder_Resource(CUnit &harvester) : COrder(UnitActionResource), worker(&harvester), + CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false) + { + Resource.Pos.x = Resource.Pos.y = -1; + } + + ~COrder_Resource(); + + virtual COrder_Resource *Clone() const { return new COrder_Resource(*this); } + + virtual void Save(CFile &file, const CUnit &unit) const; + virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit); + + virtual void Execute(CUnit &unit); + + bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/); + virtual void ReleaseRefs(CUnit &unit); + + + Vec2i GetHarvestLocation() const; // { return Pos || Mine->tilePos;} + bool IsGatheringStarted() const; + bool IsGatheringFinished() const; + bool IsGatheringWaiting() const; +private: + int MoveToResource_Terrain(CUnit &unit); + int MoveToResource_Unit(CUnit &unit); + int MoveToResource(CUnit &unit); + void UnitGotoGoal(CUnit &unit, CUnit *const goal, int state); + int StartGathering(CUnit &unit); + void LoseResource(CUnit &unit, const CUnit &source); + int GatherResource(CUnit &unit); + int StopGathering(CUnit &unit); + int MoveToDepot(CUnit &unit); + bool WaitInDepot(CUnit &unit); + void DropResource(CUnit &unit); + void ResourceGiveUp(CUnit &unit); + bool ActionResourceInit(CUnit &unit); +private: + CUnitPtr worker; /// unit that own this order. + unsigned char CurrentResource; + struct { + Vec2i Pos; /// position for terrain resource. + CUnitPtr Mine; + } Resource; + CUnitPtr Depot; + int State; + int TimeToHarvest; /// how much time until we harvest some more. + bool DoneHarvesting; /// Harvesting done, wait for action to break. +}; + class COrder_SpellCast : public COrder { public: @@ -614,8 +656,6 @@ extern void CommandSharedVision(int player, bool state, int opponent); -- Actions: in action_<name>.c ----------------------------------------------------------------------------*/ -extern void DropResource(CUnit &unit); -extern void ResourceGiveUp(CUnit &unit); extern int GetNumWaitingWorkers(const CUnit &mine); extern bool AutoAttack(CUnit &unit); extern bool AutoRepair(CUnit &unit); @@ -632,10 +672,6 @@ typedef void HandleActionFunc(COrder& order, CUnit &unit); /// Handle command attack extern HandleActionFunc HandleActionAttack; - /// Handle command resource -extern HandleActionFunc HandleActionResource; - /// Handle command return -extern HandleActionFunc HandleActionReturnGoods; /*---------------------------------------------------------------------------- -- Actions: actions.c diff --git a/src/include/unit.h b/src/include/unit.h index fe50ffac6..3808aa89a 100644 --- a/src/include/unit.h +++ b/src/include/unit.h @@ -1246,7 +1246,7 @@ extern void SelectionCclRegister(); // in ccl_unit.c /// Parse order -extern void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr order); +extern void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr order); /// register CCL units features extern void UnitCclRegister(); diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp index f1dc82a17..d45c27b74 100644 --- a/src/unit/script_unit.cpp +++ b/src/unit/script_unit.cpp @@ -132,39 +132,6 @@ CUnit *CclGetUnitFromRef(lua_State *l) return UnitSlots[slot]; } -/** -** Parse res worker data -** -** @param l Lua state. -** @param unit Unit pointer which should be filled with the data. -*/ -static void CclParseResWorker(lua_State *l, COrderPtr order) -{ - const char *value; - int args; - int j; - - if (!lua_istable(l, -1)) { - LuaError(l, "incorrect argument"); - } - args = lua_objlen(l, -1); - for (j = 0; j < args; ++j) { - lua_rawgeti(l, -1, j + 1); - value = LuaToString(l, -1); - lua_pop(l, 1); - ++j; - if (!strcmp(value, "time-to-harvest")) { - lua_rawgeti(l, -1, j + 1); - order->Data.ResWorker.TimeToHarvest = LuaToNumber(l, -1); - lua_pop(l, 1); - } else if (!strcmp(value, "done-harvesting")) { - order->Data.ResWorker.DoneHarvesting = 1; - --j; - } else { - LuaError(l, "ParseResWorker: Unsupported tag: %s" _C_ value); - } - } -} bool COrder::ParseGenericData(lua_State *l, int &j, const char *value) { @@ -261,59 +228,8 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU } else if (!strcmp(value, "subaction")) { ++j; lua_rawgeti(l, -1, j + 1); - this->SubAction.Attack = this->SubAction.Res = LuaToNumber(l, -1); + this->SubAction.Attack = LuaToNumber(l, -1); lua_pop(l, 1); - } else if (!strcmp(value, "current-resource")) { - ++j; - lua_rawgeti(l, -1, j + 1); - this->CurrentResource = CclGetResourceByName(l); - lua_pop(l, 1); - } else if (!strcmp(value, "resource-pos")) { - ++j; - lua_rawgeti(l, -1, j + 1); - this->Arg1.Resource.Mine = NULL; - CclGetPos(l, &this->Arg1.Resource.Pos.x , &this->Arg1.Resource.Pos.y); - lua_pop(l, 1); - - Assert(this->CurrentResource); - } else if (!strcmp(value, "resource-mine")) { - ++j; - lua_rawgeti(l, -1, j + 1); - Vec2i invalidPos = {-1, -1}; - this->Arg1.Resource.Pos = invalidPos; - this->Arg1.Resource.Mine = CclGetUnitFromRef(l); - lua_pop(l, 1); - } else if (!strcmp(value, "data-res-worker")) { - ++j; - lua_rawgeti(l, -1, j + 1); - CclParseResWorker(l, this); - lua_pop(l, 1); - } else if (!strcmp(value, "mine")) { /* old save format */ - int pos; - ++j; - lua_rawgeti(l, -1, j + 1); - pos = LuaToNumber(l, -1); - lua_pop(l, 1); - - const Vec2i mpos = {pos >> 16, pos & 0xFFFF}; - CUnit *mine = NULL; - pos = 0; - do { - pos++; - mine = ResourceOnMap(mpos, pos, true); - } while (!mine && pos < MaxCosts); - if (mine) { - Vec2i invalidPos = {-1, -1}; - this->Arg1.Resource.Pos = invalidPos; - - mine->RefsIncrease(); - this->Arg1.Resource.Mine = mine; - this->CurrentResource = pos; - } else { - this->CurrentResource = WoodCost; - this->Arg1.Resource.Mine = NULL; - this->Arg1.Resource.Pos = mpos; - } } else { return false; } @@ -326,7 +242,7 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU ** @param l Lua state. ** @param order OUT: resulting order. */ -void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr) +void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr *orderPtr) { const int args = lua_objlen(l, -1); @@ -369,9 +285,7 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr) } else if (!strcmp(actiontype, "action-repair")) { *orderPtr = new COrder_Repair; } else if (!strcmp(actiontype, "action-resource")) { - *orderPtr = COrder::NewActionResource(); - } else if (!strcmp(actiontype, "action-return-goods")) { - *orderPtr = COrder::NewActionReturnGoods(); + *orderPtr = new COrder_Resource(unit); } else if (!strcmp(actiontype, "action-transform-into")) { *orderPtr = new COrder_TransformInto; } else { diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp index 6163199b0..24c0b2077 100644 --- a/src/unit/unit.cpp +++ b/src/unit/unit.cpp @@ -376,7 +376,6 @@ bool CUnit::RestoreOrder() //copy this->Orders.insert(this->Orders.begin() + 1, this->SavedOrder); - this->CurrentResource = this->SavedOrder->CurrentResource; this->SavedOrder = NULL; return true; @@ -3410,18 +3409,6 @@ void CleanUnits() continue; } if (!unit->Destroyed) { - if (unit->CurrentAction() == UnitActionResource) { - ResourceInfo *resinfo = unit->Type->ResInfo[unit->CurrentResource]; - if (resinfo && !resinfo->TerrainHarvester) { - CUnit *mine = unit->CurrentOrder()->Arg1.Resource.Mine; - if (mine && !mine->Destroyed) { - unit->DeAssignWorkerFromMine(*mine); - mine->RefsDecrease(); - unit->CurrentOrder()->Arg1.Resource.Mine = NULL; - } - } - } - unit->CurrentOrder()->ClearGoal(); if (!unit->Removed) { unit->Remove(NULL); } diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp index f6673c774..b56876ea1 100644 --- a/src/unit/unit_draw.cpp +++ b/src/unit/unit_draw.cpp @@ -819,11 +819,6 @@ static void ShowSingleOrder(const CUnit &unit, const PixelPos &pos, const COrder dest = true; break; - case UnitActionReturnGoods: - e_color = color = ColorYellow; - dest = true; - break; - default: e_color = color = ColorGray; DebugPrint("Unknown action %d\n" _C_ order.Action); diff --git a/src/unit/unit_save.cpp b/src/unit/unit_save.cpp index d8c5dc0a3..d1e1db55b 100644 --- a/src/unit/unit_save.cpp +++ b/src/unit/unit_save.cpp @@ -102,12 +102,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file) case UnitActionAttackGround: file.printf("\"action-attack-ground\","); break; - case UnitActionResource: - file.printf("\"action-resource\","); - break; - case UnitActionReturnGoods: - file.printf("\"action-return-goods\","); - break; default: DebugPrint("Unknown action in order\n"); } @@ -137,52 +131,16 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file) case UnitActionAttackGround: file.printf(", \"subaction\", %d", order.SubAction.Attack); break; - case UnitActionResource: - case UnitActionReturnGoods: - file.printf(", \"subaction\", %d", order.SubAction.Res); - break; - } - - - // Extra arg. - switch (order.Action) { - case UnitActionResource : - case UnitActionReturnGoods : - if (order.CurrentResource) { - file.printf(", \"current-resource\", \"%s\",", DefaultResourceNames[order.CurrentResource].c_str()); - const CUnit *mine = order.Arg1.Resource.Mine; - - if (mine == NULL) { - const Vec2i &pos = order.Arg1.Resource.Pos; - - file.printf(" \"resource-pos\", {%d, %d}", pos.x, pos.y); - } else { - if (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(*mine).c_str()); - } - } - break; default: break; } + // // Order data part // switch (order.Action) { case UnitActionStill: - // FIXME: support other resource types - break; case UnitActionResource: - file.printf(", \"data-res-worker\", {\"time-to-harvest\", %d", order.Data.ResWorker.TimeToHarvest); - if (order.Data.ResWorker.DoneHarvesting) { - file.printf(", \"done-harvesting\""); - } - file.printf("}"); - break; case UnitActionBuilt: case UnitActionResearch: case UnitActionUpgradeTo: