void COrder_Resource::DropResource(CUnit &unit) { if (unit.CurrentResource) { const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource]; //Wyrmgus start // if (!resinfo.TerrainHarvester) { if (!Map.Info.IsPointOnMap(this->goalPos)) { //Wyrmgus end CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); } } //fast clean both resource data: pos and mine this->Resource.Mine = NULL; unit.CurrentResource = 0; unit.ResourcesHeld = 0; } }
bool COrder_Resource::FindAnotherResource(CUnit &unit) { if (this->CurrentResource) { const ResourceInfo *resinfo = unit.Type->ResInfo[this->CurrentResource]; if (resinfo) { //Wyrmgus start // if (!resinfo.TerrainHarvester) { if (!Map.Info.IsPointOnMap(this->goalPos)) { //Wyrmgus end CUnit *newGoal = UnitFindResource(unit, this->Resource.Mine ? *this->Resource.Mine : unit, 8, this->CurrentResource, 1); if (newGoal) { CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); } unit.AssignWorkerToMine(*newGoal); this->Resource.Mine = newGoal; this->goalPos.x = -1; this->goalPos.y = -1; this->State = SUB_MOVE_TO_RESOURCE; this->SetGoal(newGoal); return true; } } else { Vec2i resPos; //Wyrmgus start // if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 8, *unit.Player, unit.tilePos, &resPos)) { if ((this->CurrentResource == WoodCost && FindTerrainType(unit.Type->MovementMask, MapFieldForest, 8, *unit.Player, unit.tilePos, &resPos)) || (this->CurrentResource == StoneCost && FindTerrainType(unit.Type->MovementMask, MapFieldRocks, 8, *unit.Player, unit.tilePos, &resPos))) { //Wyrmgus end this->goalPos = resPos; this->State = SUB_MOVE_TO_RESOURCE; DebugPrint("Found a better place to harvest %d,%d\n" _C_ resPos.x _C_ resPos.y); return true; } } } } return false; }
/** ** Initialize ** ** return false if action is canceled, true otherwise. */ bool COrder_Resource::ActionResourceInit(CUnit &unit) { Assert(this->State == SUB_START_RESOURCE); this->Range = 0; CUnit *const goal = this->GetGoal(); CUnit *mine = this->Resource.Mine; if (mine) { unit.DeAssignWorkerFromMine(*mine); this->Resource.Mine = NULL; } if (goal && goal->IsAlive() == false) { return false; } if (goal && goal->CurrentAction() != UnitActionBuilt) { unit.AssignWorkerToMine(*goal); this->Resource.Mine = goal; } UnitGotoGoal(unit, goal, SUB_MOVE_TO_RESOURCE); return 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; }