/** ** Give up on gathering. ** ** @param unit Pointer to unit. */ void COrder_Resource::ResourceGiveUp(CUnit &unit) { DebugPrint("%d: Worker %d report: Gave up on resource gathering.\n" _C_ unit.Player->Index _C_ UnitNumber(unit)); if (this->HasGoal()) { DropResource(unit); this->ClearGoal(); } this->Finished = true; }
/** ** Start harvesting the resource. ** ** @param unit Pointer to unit. ** ** @return TRUE if ready, otherwise FALSE. */ int COrder_Resource::StartGathering(CUnit &unit) { CUnit *goal; const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource]; Assert(!unit.IX); Assert(!unit.IY); //Wyrmgus start // if (resinfo.TerrainHarvester) { if (Map.Info.IsPointOnMap(this->goalPos)) { //Wyrmgus end // This shouldn't happened? #if 0 if (!Map.IsTerrainResourceOnMap(unit.Orders->goalPos, this->CurrentResource)) { DebugPrint("Wood gone, just like that?\n"); return 0; } #endif UnitHeadingFromDeltaXY(unit, this->goalPos - unit.tilePos); if (resinfo.WaitAtResource) { this->TimeToHarvest = std::max<int>(1, resinfo.WaitAtResource * SPEEDUP_FACTOR / unit.Player->SpeedResourcesHarvest[resinfo.ResourceId]); } else { this->TimeToHarvest = 1; } this->DoneHarvesting = 0; if (this->CurrentResource != unit.CurrentResource) { DropResource(unit); unit.CurrentResource = this->CurrentResource; } return 1; } goal = this->GetGoal(); // Target is dead, stop getting resources. if (!goal || goal->IsVisibleAsGoal(*unit.Player) == false) { // Find an alternative, but don't look too far. this->goalPos.x = -1; this->goalPos.y = -1; if ((goal = UnitFindResource(unit, unit, 15, this->CurrentResource, unit.Player->AiEnabled))) { this->State = SUB_START_RESOURCE; this->SetGoal(goal); } else { this->ClearGoal(); this->Finished = true; } return 0; } // 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. //Wyrmgus start // UnitHeadingFromDeltaXY(unit, goal->tilePos - unit.tilePos + goal->Type->GetHalfTileSize()); UnitHeadingFromDeltaXY(unit, Vec2i(goal->tilePos.x * PixelTileSize.x, goal->tilePos.y * PixelTileSize.y) - Vec2i(unit.tilePos.x * PixelTileSize.x, unit.tilePos.y * PixelTileSize.y) + goal->Type->GetHalfTilePixelSize() - unit.Type->GetHalfTilePixelSize()); //Wyrmgus end // If resource is still under construction, wait! if ((goal->Type->MaxOnBoard && goal->Resource.Active >= goal->Type->MaxOnBoard) || goal->CurrentAction() == UnitActionBuilt) { // FIXME: Determine somehow when the resource will be free to use // FIXME: Could we somehow find another resource? Think minerals // FIXME: We should add a flag for that, and a limited range. // However the CPU usage is really low (no pathfinding stuff). unit.Wait = 10; return 0; } // Place unit inside the resource //Wyrmgus start // if (!resinfo.HarvestFromOutside) { if (!goal->Type->BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) { //Wyrmgus end if (goal->Variable[MAXHARVESTERS_INDEX].Value == 0 || goal->Variable[MAXHARVESTERS_INDEX].Value > goal->InsideCount) { this->ClearGoal(); int selected = unit.Selected; unit.Remove(goal); if (selected && !Preference.DeselectInMine) { unit.Removed = 0; SelectUnit(unit); SelectionChanged(); unit.Removed = 1; } } else if (goal->Variable[MAXHARVESTERS_INDEX].Value <= goal->InsideCount) { //Resource is full, wait unit.Wait = 10; return 0; } } if (this->CurrentResource != unit.CurrentResource) { DropResource(unit); unit.CurrentResource = this->CurrentResource; } // Activate the resource goal->Resource.Active++; if (resinfo.WaitAtResource) { //Wyrmgus start // this->TimeToHarvest = std::max<int>(1, resinfo.WaitAtResource * SPEEDUP_FACTOR / unit.Player->SpeedResourcesHarvest[resinfo.ResourceId]); int wait_at_resource = resinfo.WaitAtResource; if (!goal->Type->BoolFlag[HARVESTFROMOUTSIDE_INDEX].value) { wait_at_resource = resinfo.WaitAtResource * 100 / resinfo.ResourceStep; } this->TimeToHarvest = std::max<int>(1, wait_at_resource * SPEEDUP_FACTOR / (unit.Player->SpeedResourcesHarvest[resinfo.ResourceId] + goal->Variable[TIMEEFFICIENCYBONUS_INDEX].Value)); //Wyrmgus end } else { this->TimeToHarvest = 1; } this->DoneHarvesting = 0; return 1; }
void SSResourceManager::UpdateSimLayer( const float timestep ) { fVector<int> resourceCounts( m_Resources.size( ) ); for ( auto& it : resourceCounts ) it = 0; // Get number of resources on spawn point Entity entityID = 0; for ( auto& entity : g_EntityManager.GetEntityMasks( ) ) { if ( entity & GetDenseComponentFlag<ResourceComponent>( ) ) { ResourceComponent* resourceComponent = GetDenseComponent<ResourceComponent>( entityID ); if ( resourceComponent->SpawnedBy != -1 ) ++resourceCounts[resourceComponent->SpawnedBy]; } ++entityID; } // Initiate resource drop m_FirstSpawnDelay -= timestep; if ( m_FirstSpawnDelay <= 0.0f && m_InitialSpawn == nullptr ) { int spawnID = 0; for ( auto& resource : m_Resources ) { float respawnRate = m_RespawnTypes[resource.RespawnType].RespawnRate; resource.LastSpawn -= timestep; if ( resource.LastSpawn <= 0.0f ) { resource.LastSpawn = respawnRate / 2.0f + respawnRate * (float) g_Randomizer.SimGenerateRandom( ); float dropOrgX = 50.0f * (2.0f * (float) g_Randomizer.SimGenerateRandom( ) - 1.0f); float dropOrgZ = 50.0f * (2.0f * (float) g_Randomizer.SimGenerateRandom( ) - 1.0f); glm::vec3 spawnOffset = glm::vec3( dropOrgX, RESOURCE_RESPAWN_DROP_HEIGHT, dropOrgZ ); int respawnCount = GetRespawnAmount( resourceCounts[spawnID], resource.RespawnType ); for ( int i = 0; i < respawnCount; ++i ) { float spawnAngle = (float) g_Randomizer.SimGenerateRandom( ) * glm::pi<float>( ) * 2.0f; float spawnDist = (float) g_Randomizer.SimGenerateRandom( ) * resource.RespawnRadius; glm::vec3 spawnPos; spawnPos.x = resource.Position.x + glm::cos( spawnAngle ) * spawnDist; spawnPos.z = resource.Position.z + glm::sin( spawnAngle ) * spawnDist; spawnPos.y = gfx::g_GFXTerrain.GetHeightAtWorldCoord( spawnPos.x, spawnPos.z ); float orientationAngle = (float) g_Randomizer.SimGenerateRandom( ) * glm::pi<float>( ) * 2.0f; glm::quat spawnOrientation = glm::rotate( resource.Orientation, orientationAngle, glm::vec3( 0.0f, 1.0f, 0.0f ) ); pString model = m_ResourceModels.at( g_Randomizer.SimRand( 0, (unsigned int) m_ResourceModels.size( ) ) ); DropResource( spawnPos, resource.Scale, spawnOrientation, model, spawnOffset, spawnID ); } } ++spawnID; } } // Drop in initial resources else if ( m_FirstSpawnDelay <= 0.0f && m_InitialSpawn ) { for ( auto& resource : *m_InitialSpawn ) DropResource( resource.Position, resource.Scale, resource.Orientation, resource.ModelPath, glm::vec3( 0.0f, RESOURCE_RESPAWN_DROP_HEIGHT, 0.0f ), -1 ); tDelete( m_InitialSpawn ); m_InitialSpawn = nullptr; m_FirstSpawnDelay = RESOURCE_SPAWN_INITIAL_DELAY; } // Update resource drops for ( auto& drop : m_ResourceSpawn ) { if ( drop.Active ) { drop.DropTime -= timestep; if ( drop.DropTime <= 0.0f ) { drop.Active = false; if ( drop.Effect ) drop.Effect->TimeToLive = drop.Effect->ParticlesTimeToLive; EntityFactory::CreateResource( drop.Position.x, drop.Position.z, drop.Scale, drop.Orientation, drop.ModelPath.c_str( ), drop.SpawnedBy ); g_SSMiniMap.PingLocation( drop.Position ); } } } }