/* ** Wait in wood deposit. */ local int WaitInWoodDeposit(Unit* unit) { Unit* destu; DebugLevel3("Waiting\n"); if( !unit->Value ) { // // Drop out unit at nearest point to target. // destu=WoodDepositOnMap(unit->X,unit->Y); DropOutNearest(unit ,unit->Command.Data.Move.SX ,unit->Command.Data.Move.SY ,destu->Type->TileWidth ,destu->Type->TileHeight); // // Return to chop point. // unit->Command.Action=UnitActionHarvest; unit->Command.Data.Move.Fast=1; unit->Command.Data.Move.Goal=NoUnitP; unit->Command.Data.Move.Range=0; unit->Command.Data.Move.DX=unit->Command.Data.Move.SX; unit->Command.Data.Move.DY=unit->Command.Data.Move.SY; if( UnitVisible(unit) ) { MustRedraw|=RedrawMap; } unit->Wait=1; unit->WoodToHarvest=CHOP_FOR_WOOD; return 1; } if( unit->Value<UNIT_MAX_WAIT ) { unit->Wait=unit->Value; } else { unit->Wait=UNIT_MAX_WAIT; } unit->Value-=unit->Wait; return 0; }
/** ** Find something else to do when the resource is exhausted. ** This is called from GatherResource when the resource is empty. ** ** @param unit pointer to harvester unit. ** @param source pointer to resource unit. */ void COrder_Resource::LoseResource(CUnit &unit, CUnit &source) { CUnit *depot; const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource]; //Wyrmgus start const CUnitType &source_type = *source.Type; // Assert((unit.Container == &source && !resinfo.HarvestFromOutside) // || (!unit.Container && resinfo.HarvestFromOutside)); Assert((unit.Container == &source && !source_type.BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) || (!unit.Container && source_type.BoolFlag[HARVESTFROMOUTSIDE_INDEX].value)); //Wyrmgus end //Wyrmgus start // if (resinfo.HarvestFromOutside) { if (source_type.BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) { //Wyrmgus end this->ClearGoal(); --source.Resource.Active; } // Continue to harvest if we aren't fully loaded //Wyrmgus start // if (resinfo.HarvestFromOutside && unit.ResourcesHeld < resinfo.ResourceCapacity) { if (source_type.BoolFlag[HARVESTFROMOUTSIDE_INDEX].value && unit.ResourcesHeld < resinfo.ResourceCapacity) { //Wyrmgus end CUnit *goal = UnitFindResource(unit, unit, 15, this->CurrentResource, 1); if (goal) { this->goalPos.x = -1; this->goalPos.y = -1; this->State = SUB_START_RESOURCE; this->SetGoal(goal); 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //unit.CurrentOrder()->Arg1.ResourcePos = (unit.X << 16) | unit.Y; this->DoneHarvesting = true; UnitGotoGoal(unit, depot, SUB_MOVE_TO_DEPOT); DebugPrint("%d: Worker %d report: Resource is exhausted, Going to depot\n" _C_ unit.Player->Index _C_ UnitNumber(unit)); return; } // No depot found, or harvester empty // Dump the unit outside and look for something to do. if (unit.Container) { //Wyrmgus start // Assert(!resinfo.HarvestFromOutside); Assert(!source_type.BoolFlag[HARVESTFROMOUTSIDE_INDEX].value); //Wyrmgus end DropOutOnSide(unit, LookingW, &source); } this->goalPos.x = -1; this->goalPos.y = -1; //use depot as goal depot = UnitFindResource(unit, unit, 15, this->CurrentResource, unit.Player->AiEnabled); if (depot) { DebugPrint("%d: Worker %d report: Resource is exhausted, Found another resource.\n" _C_ unit.Player->Index _C_ UnitNumber(unit)); this->State = SUB_START_RESOURCE; this->SetGoal(depot); } else { DebugPrint("%d: Worker %d report: Resource is exhausted, Just sits around confused.\n" _C_ unit.Player->Index _C_ UnitNumber(unit)); this->Finished = true; } }
/** ** Stop gathering from the resource, go home. ** ** @param unit Poiner to unit. ** ** @return TRUE if ready, otherwise FALSE. */ int COrder_Resource::StopGathering(CUnit &unit) { CUnit *source = 0; const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource]; //Wyrmgus start // if (!resinfo.TerrainHarvester) { if (!Map.Info.IsPointOnMap(this->goalPos)) { //Wyrmgus end //Wyrmgus start // if (resinfo.HarvestFromOutside) { if (this->GetGoal() && this->GetGoal()->Type->BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) { //Wyrmgus end source = this->GetGoal(); this->ClearGoal(); } else { source = unit.Container; } source->Resource.Active--; Assert(source->Resource.Active >= 0); //Store resource position. this->Resource.Mine = source; if (Preference.MineNotifications && unit.Player->Index == ThisPlayer->Index && source->IsAlive() && !source->MineLow && source->ResourcesHeld * 100 / source->Variable[GIVERESOURCE_INDEX].Max <= 10 //Wyrmgus start // && source->Variable[GIVERESOURCE_INDEX].Max > DefaultIncomes[this->CurrentResource]) { && source->Variable[GIVERESOURCE_INDEX].Max > (DefaultIncomes[this->CurrentResource] * 10)) { //Wyrmgus end //Wyrmgus start // unit.Player->Notify(NotifyYellow, source->tilePos, _("%s is running low!"), source->Type->Name.c_str()); unit.Player->Notify(NotifyYellow, source->tilePos, _("Our %s is nearing depletion!"), source->Type->Name.c_str()); //Wyrmgus end source->MineLow = 1; } if (source->Type->MaxOnBoard) { int count = 0; CUnit *worker = source->Resource.Workers; CUnit *next = NULL; for (; NULL != worker; worker = worker->NextWorker) { 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) { next = worker; } } else { next = worker; } } } if (next) { if (!unit.Player->AiEnabled) { DebugPrint("%d: Worker %d report: Unfreez resource gathering of %d <Wait %d> on %d [Assigned: %d Waiting %d].\n" _C_ unit.Player->Index _C_ UnitNumber(unit) _C_ UnitNumber(*next) _C_ next->Wait _C_ UnitNumber(*source) _C_ source->Resource.Assigned _C_ count); } next->Wait = 0; //source->Data.Resource.Waiting = count - 1; //Assert(source->Data.Resource.Assigned >= source->Data.Resource.Waiting); //StartGathering(next); } } } else { // Store resource position. this->Resource.Pos = unit.tilePos; Assert(this->Resource.Mine == NULL); } #ifdef DEBUG if (!unit.ResourcesHeld) { DebugPrint("Unit %d is empty???\n" _C_ UnitNumber(unit)); } #endif // Find and send to resource deposit. CUnit *depot = FindDeposit(unit, 1000, unit.CurrentResource); if (!depot || !unit.ResourcesHeld || this->Finished) { //Wyrmgus start // if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) { if (!((source && source->Type->BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) || Map.Info.IsPointOnMap(this->goalPos))) { //Wyrmgus end Assert(unit.Container); DropOutOnSide(unit, LookingW, source); } CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); this->Resource.Mine = NULL; } DebugPrint("%d: Worker %d report: Can't find a resource [%d] deposit.\n" _C_ unit.Player->Index _C_ UnitNumber(unit) _C_ unit.CurrentResource); this->Finished = true; return 0; } else { //Wyrmgus start // if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) { if (!((source && source->Type->BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) || Map.Info.IsPointOnMap(this->goalPos))) { //Wyrmgus end Assert(unit.Container); DropOutNearest(unit, depot->tilePos + depot->Type->GetHalfTileSize(), source); } UnitGotoGoal(unit, depot, SUB_MOVE_TO_DEPOT); } if (IsOnlySelected(unit)) { SelectedUnitChanged(); } #if 1 return 1; #endif }
/** ** Wait in depot, for the resources stored. ** ** @param unit Pointer to unit. ** ** @return TRUE if ready, otherwise FALSE. */ bool COrder_Resource::WaitInDepot(CUnit &unit) { const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource]; const CUnit *depot = ResourceDepositOnMap(unit.tilePos, resinfo.ResourceId); //Assert(depot); // Range hardcoded. don't stray too far though //Wyrmgus start // if (resinfo.TerrainHarvester) { if (!this->Resource.Mine) { //Wyrmgus end Vec2i pos = this->Resource.Pos; //Wyrmgus start // if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 10, *unit.Player, pos, &pos)) { if ((this->CurrentResource == WoodCost && FindTerrainType(unit.Type->MovementMask, MapFieldForest, 10, *unit.Player, pos, &pos)) || (this->CurrentResource == StoneCost && FindTerrainType(unit.Type->MovementMask, MapFieldRocks, 10, *unit.Player, pos, &pos))) { //Wyrmgus end if (depot) { DropOutNearest(unit, pos, depot); } this->goalPos = pos; //Wyrmgus start if (this->CurrentResource == WoodCost) { //tree tiles can regrow, so we need to check if any have regrown closer to the worker Vec2i forestPos; int max_forest_range = std::max<int>(abs(unit.tilePos.x - this->goalPos.x), abs(unit.tilePos.y - this->goalPos.y)); if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, max_forest_range, *unit.Player, unit.tilePos, &forestPos)) { if (PlaceReachable(unit, forestPos, 1, 1, 0, 1, max_forest_range * 4)) { this->goalPos = forestPos; } } } //Wyrmgus end } else { if (depot) { DropOutOnSide(unit, LookingW, depot); } this->Finished = true; return false; } } else { const unsigned int tooManyWorkers = 15; CUnit *mine = this->Resource.Mine; const int range = 15; CUnit *newdepot = NULL; CUnit *goal = NULL; const bool longWay = unit.pathFinderData->output.Cycles > 500; //Wyrmgus start // if (unit.Player->AiEnabled && AiPlayer && AiPlayer->BuildDepots) { if (depot && unit.Player->AiEnabled && AiPlayer && AiPlayer->BuildDepots) { //check if the depot is valid //Wyrmgus end // If the depot is overused, we need first to try to switch into another depot // Use depot's ref counter for that if (longWay || !mine || (depot->Refs > tooManyWorkers)) { newdepot = AiGetSuitableDepot(unit, *depot, &goal); if (newdepot == NULL && longWay) { // We need a new depot AiNewDepotRequest(unit); } } } // If goal is not NULL, then we got it in AiGetSuitableDepot if (!goal) { goal = UnitFindResource(unit, newdepot ? *newdepot : (mine ? *mine : unit), mine ? range : 1000, this->CurrentResource, unit.Player->AiEnabled, newdepot ? newdepot : depot); } if (goal) { if (depot) { DropOutNearest(unit, goal->tilePos + goal->Type->GetHalfTileSize(), depot); } if (goal != mine) { if (mine) { unit.DeAssignWorkerFromMine(*mine); } unit.AssignWorkerToMine(*goal); this->Resource.Mine = goal; } this->SetGoal(goal); this->goalPos.x = this->goalPos.y = -1; } else { #ifdef DEBUG const Vec2i &pos = mine ? mine->tilePos : unit.tilePos; 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_ UnitNumber(unit) _C_ unit.tilePos.x _C_ unit.tilePos.y _C_ pos.x _C_ pos.y _C_ range); #endif // DEBUG if (depot) { DropOutOnSide(unit, LookingW, depot); } if (mine) { unit.DeAssignWorkerFromMine(*mine); this->Resource.Mine = NULL; } this->Finished = true; return false; } } return true; }