void AFlareGame::Scrap(FName ShipImmatriculation, FName TargetStationImmatriculation) { DeactivateSector(); UFlareSimulatedSpacecraft* ShipToScrap = World->FindSpacecraft(ShipImmatriculation); UFlareSimulatedSpacecraft* ScrapingStation = World->FindSpacecraft(TargetStationImmatriculation); if(!ShipToScrap || !ScrapingStation) { FLOG("Scrap failed: ship to scrap or station not found"); return; } if(ShipToScrap->GetCurrentSector() != ScrapingStation->GetCurrentSector()) { FLOG("Scrap failed: ship and station not in the same sector"); return; } UFlareSimulatedSector* CurrentSector = ShipToScrap->GetCurrentSector(); int64 ScrapRevenue = 0; for (int ResourceIndex = 0; ResourceIndex < ShipToScrap->GetDescription()->CycleCost.InputResources.Num() ; ResourceIndex++) { FFlareFactoryResource* Resource = &ShipToScrap->GetDescription()->CycleCost.InputResources[ResourceIndex]; ScrapRevenue += Resource->Quantity * CurrentSector->GetResourcePrice(&Resource->Resource->Data, EFlareResourcePriceContext::Default); int ResourceToGive = Resource->Quantity; ResourceToGive -= ScrapingStation->GetCargoBay()->GiveResources(&Resource->Resource->Data, Resource->Quantity); CurrentSector->GiveResources(ScrapingStation->GetCompany(), &Resource->Resource->Data, ResourceToGive, true); } ScrapRevenue = FMath::Min(ScrapRevenue, ScrapingStation->GetCompany()->GetMoney()); FLOGV("Scrap success for %d", ScrapRevenue); if (ScrapingStation->GetCompany() != ShipToScrap->GetCompany()) { ScrapingStation->GetCompany()->TakeMoney(ScrapRevenue); ShipToScrap->GetCompany()->GiveMoney(ScrapRevenue); GetPC()->Notify(LOCTEXT("ShipSellScrap", "Ship scrap complete"), FText::Format(LOCTEXT("ShipSellScrapFormat", "Your ship {0} has been scrapped for {1} credits!"), FText::FromString(ShipToScrap->GetImmatriculation().ToString()), FText::AsNumber(UFlareGameTools::DisplayMoney(ScrapRevenue))), FName("ship-own-scraped"), EFlareNotification::NT_Economy); } else { GetPC()->Notify(LOCTEXT("ShipOwnScrap", "Ship scrap complete"), FText::Format(LOCTEXT("ShipOwnScrapFormat", "Your ship {0} has been scrapped !"), FText::FromString(ShipToScrap->GetImmatriculation().ToString())), FName("ship-own-scraped"), EFlareNotification::NT_Economy); } ShipToScrap->GetCompany()->DestroySpacecraft(ShipToScrap); }
void UFlareFactory::PerformCreateShipAction(const FFlareFactoryAction* Action) { FFlareSpacecraftDescription* ShipDescription = GetGame()->GetSpacecraftCatalog()->Get(FactoryData.TargetShipClass); if (ShipDescription) { UFlareCompany* Company = Parent->GetCompany(); if(FactoryData.TargetShipCompany != NAME_None) { Company = Game->GetGameWorld()->FindCompany(FactoryData.TargetShipCompany); } FVector SpawnPosition = Parent->GetSpawnLocation(); for (uint32 Index = 0; Index < Action->Quantity; Index++) { // Get data UFlareSimulatedSpacecraft* Spacecraft = Parent->GetCurrentSector()->CreateSpacecraft(ShipDescription, Company, SpawnPosition); AFlarePlayerController* PC = Parent->GetGame()->GetPC(); FFlareMenuParameterData Data; Data.Spacecraft = Spacecraft; // Notify PC if (PC && Spacecraft && Spacecraft->GetCompany() == PC->GetCompany()) { PC->Notify(LOCTEXT("ShipBuilt", "Ship production complete"), FText::Format(LOCTEXT("ShipBuiltFormat", "Your ship {0} is ready to use !"), UFlareGameTools::DisplaySpacecraftName(Spacecraft)), FName("ship-production-complete"), EFlareNotification::NT_Economy, false, EFlareMenu::MENU_Ship, Data); Game->GetQuestManager()->OnEvent(FFlareBundle().PutTag("build-ship").PutInt32("size", Spacecraft->GetSize())); PC->SetAchievementProgression("ACHIEVEMENT_SHIP", 1); } } } FactoryData.TargetShipClass = NAME_None; FactoryData.TargetShipCompany = NAME_None; // No more ship to produce Stop(); }
void SectorHelper::GetRefillFleetSupplyNeeds(UFlareSimulatedSector* Sector, UFlareCompany* Company, int32& CurrentNeededFleetSupply, int32& TotalNeededFleetSupply, int64& MaxDuration, bool OnlyPossible) { TArray<UFlareSimulatedSpacecraft*> CompanySpacecraft; if(OnlyPossible && Sector->IsInDangerousBattle(Company)) { // Don't add any spacecraft } else { for (int32 SpacecraftIndex = 0; SpacecraftIndex < Sector->GetSectorSpacecrafts().Num(); SpacecraftIndex++) { UFlareSimulatedSpacecraft* Spacecraft = Sector->GetSectorSpacecrafts()[SpacecraftIndex]; if (Company != Spacecraft->GetCompany()) { continue; } CompanySpacecraft.Add(Spacecraft); } } GetRefillFleetSupplyNeeds(Sector, CompanySpacecraft, CurrentNeededFleetSupply, TotalNeededFleetSupply, MaxDuration, OnlyPossible); }
void SectorHelper::GetAvailableFleetSupplyCount(UFlareSimulatedSector* Sector, UFlareCompany* Company, int32& OwnedFS, int32& AvailableFS, int32& AffordableFS) { OwnedFS = 0; int32 NotOwnedFS = 0; FFlareResourceDescription* FleetSupply = Sector->GetGame()->GetScenarioTools()->FleetSupply; for (int32 SpacecraftIndex = 0; SpacecraftIndex < Sector->GetSectorSpacecrafts().Num(); SpacecraftIndex++) { UFlareSimulatedSpacecraft* Spacecraft = Sector->GetSectorSpacecrafts()[SpacecraftIndex]; if (Spacecraft->IsHostile(Company)) { // At war, no trade possible continue; } int32 AvailableQuantity = Spacecraft->GetActiveCargoBay()->GetResourceQuantity(FleetSupply, Company); if (Company == Spacecraft->GetCompany()) { OwnedFS += AvailableQuantity; } else { NotOwnedFS += AvailableQuantity; } } AvailableFS = OwnedFS + NotOwnedFS; int32 ResourcePrice = Sector->GetResourcePrice(FleetSupply, EFlareResourcePriceContext::MaintenanceConsumption); int32 MaxAffordableQuantity = FMath::Max(0, int32(Company->GetMoney() / ResourcePrice)); AffordableFS = OwnedFS + FMath::Min(MaxAffordableQuantity, NotOwnedFS); }
FText FFlareTransactionLogEntry::GetComment(AFlareGame* Game) const { FText Comment; // FLOGV("--- Type %d", int(Type)); // FLOGV(" Spacecraft %s", *Spacecraft.ToString()); // FLOGV(" Sector %s", *Sector.ToString()); // FLOGV(" ExtraIdentifier1 %s", *ExtraIdentifier1.ToString()); // FLOGV(" ExtraIdentifier2 %s", *ExtraIdentifier2.ToString()); UFlareSimulatedSpacecraft* SpacecraftCache = nullptr; FFlareResourceDescription* ResourceCache = nullptr; if(Spacecraft != NAME_None) { SpacecraftCache = Game->GetGameWorld()->FindSpacecraft(Spacecraft); } if(Resource != NAME_None) { ResourceCache = Game->GetResourceCatalog()->Get(Resource); } auto FindFactoryDescription = [](UFlareSimulatedSpacecraft* SpacecraftWithFactory, FName Identifier) -> FFlareFactoryDescription const* { for(UFlareFactory* Factory : SpacecraftWithFactory->GetFactories()) { FFlareFactoryDescription const* FactoryDescription = Factory->GetDescription(); if(FactoryDescription->Identifier == Identifier) { return FactoryDescription; } } return nullptr; }; auto GetFactoryName = [this, &SpacecraftCache, &FindFactoryDescription]() { FFlareFactoryDescription const* FactoryDescription = FindFactoryDescription(SpacecraftCache, ExtraIdentifier1); if(FactoryDescription) { return FactoryDescription->Name; } return FText(); }; auto IsAITransaction = [](UFlareSimulatedSpacecraft* SpacecraftCache, UFlareSimulatedSpacecraft* OtherSpacecraftCache) { if(SpacecraftCache && OtherSpacecraftCache) { if((!SpacecraftCache->IsStation() && !SpacecraftCache->GetCompany()->IsPlayerCompany()) || (!OtherSpacecraftCache->IsStation() && !OtherSpacecraftCache->GetCompany()->IsPlayerCompany())) { return true; } } return false; }; switch(Type) { case EFlareTransactionLogEntry::ManualResourcePurchase: { UFlareSimulatedSpacecraft* OtherSpacecraftCache = Game->GetGameWorld()->FindSpacecraft(ExtraIdentifier1); if(OtherSpacecraftCache && ResourceCache) { FText ResourceComment = FText::Format(LOCTEXT("ManualResourcePurchaseResources", "{0} {1}"), ResourceQuantity, ResourceCache->Name); if(IsAITransaction(SpacecraftCache, OtherSpacecraftCache)) { Comment = FText::Format(LOCTEXT("AIManualResourcePurchase", "{0} sold {1} with {2}"), OtherSpacecraftCache->GetCompany()->GetCompanyName(), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache)); } else { Comment = FText::Format(LOCTEXT("ManualResourcePurchase", "Bought {0} from {1}"), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache)); } } break; } case EFlareTransactionLogEntry::ManualResourceSell: { UFlareSimulatedSpacecraft* OtherSpacecraftCache = Game->GetGameWorld()->FindSpacecraft(ExtraIdentifier1); if(OtherSpacecraftCache && ResourceCache) { FText ResourceComment = FText::Format(LOCTEXT("ManualResourceSellResources", "{0} {1}"), ResourceQuantity, ResourceCache->Name); if(IsAITransaction(SpacecraftCache, OtherSpacecraftCache)) { Comment = FText::Format(LOCTEXT("AIManualResourceSell", "{0} bought {1} with {2}"), OtherSpacecraftCache->GetCompany()->GetCompanyName(), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache)); } else { Comment = FText::Format(LOCTEXT("ManualResourceSell", "Sold {0} to {1}"), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache)); } } break; } case EFlareTransactionLogEntry::TradeRouteResourcePurchase: { UFlareSimulatedSpacecraft* OtherSpacecraftCache = Game->GetGameWorld()->FindSpacecraft(ExtraIdentifier1); UFlareTradeRoute* TradeRouteCache = Game->GetGameWorld()->FindTradeRoute(ExtraIdentifier2); if(OtherSpacecraftCache && ResourceCache) { FText ResourceComment = FText::Format(LOCTEXT("TradeRouteResourcePurchaseComment", "{0} {1}"), ResourceQuantity, ResourceCache->Name); if(TradeRouteCache) { Comment = FText::Format(LOCTEXT("TradeRouteResourcePurchase", "Bought {0} from {1} on trade route {2}"), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache), TradeRouteCache->GetTradeRouteName()); } else { Comment = FText::Format(LOCTEXT("NotTradeRouteResourcePurchase", "Bought {0} from {1} on an old trade route"), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache)); } } break; } case EFlareTransactionLogEntry::TradeRouteResourceSell: { UFlareSimulatedSpacecraft* OtherSpacecraftCache = Game->GetGameWorld()->FindSpacecraft(ExtraIdentifier1); UFlareTradeRoute* TradeRouteCache = Game->GetGameWorld()->FindTradeRoute(ExtraIdentifier2); if(OtherSpacecraftCache && ResourceCache) { FText ResourceComment = FText::Format(LOCTEXT("TradeRouteResourceSellResources", "{0} {1}"), ResourceQuantity, ResourceCache->Name); if(TradeRouteCache) { Comment = FText::Format(LOCTEXT("TradeRouteResourceSell", "Sold {0} to {1} on trade route {2}"), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache), TradeRouteCache->GetTradeRouteName()); } else { Comment = FText::Format(LOCTEXT("NotTradeRouteResourceSell", "Sold {0} to {1} on an old trade route"), ResourceComment, UFlareGameTools::DisplaySpacecraftName(OtherSpacecraftCache)); } } break; } case EFlareTransactionLogEntry::FactoryWages: { if(SpacecraftCache) { Comment = FText::Format(LOCTEXT("FactoryWages", "Factory wages for {0}"), GetFactoryName()); } break; } case EFlareTransactionLogEntry::CancelFactoryWages: { if(SpacecraftCache) { Comment = FText::Format(LOCTEXT("CancelFactoryWages", "Cancelled factory wages for {0}"), GetFactoryName()); } break; } case EFlareTransactionLogEntry::StationConstructionFees: { FFlareSpacecraftDescription* Description = Game->GetSpacecraftCatalog()->Get(ExtraIdentifier1); if(Description) { Comment = FText::Format(LOCTEXT("StationConstructionFees", "Contruction fees for {0}"), Description->Name); } break; } case EFlareTransactionLogEntry::StationUpgradeFees: { Comment = LOCTEXT("StationUpgradeFees", "Station upgrade fees"); break; } case EFlareTransactionLogEntry::CancelStationUpgradeFees: { Comment = LOCTEXT("CancelStationUpgradeFees", "Cancelled station upgrade fees"); break; } case EFlareTransactionLogEntry::UpgradeShipPart: { Comment = LOCTEXT("UpgradeShipFees", "Upgrade ship fees"); break; } case EFlareTransactionLogEntry::OrderShip: { FFlareSpacecraftDescription* Description = Game->GetSpacecraftCatalog()->Get(ExtraIdentifier1); if(Description) { Comment = FText::Format(LOCTEXT("OrderShip", "Ordered ship ({0}})"), Description->Name); } break; } case EFlareTransactionLogEntry::CancelOrderShip: { FFlareSpacecraftDescription* Description = Game->GetSpacecraftCatalog()->Get(ExtraIdentifier1); if(Description) { Comment = FText::Format(LOCTEXT("CancelOrderShip", "Cancelled ship order ({0}})"), Description->Name); } break; } case EFlareTransactionLogEntry::OrderShipAdvance: { FFlareSpacecraftDescription* Description = Game->GetSpacecraftCatalog()->Get(ExtraIdentifier1); if(Description) { Comment = FText::Format(LOCTEXT("OrderShipAdvance", "Paid for ship order ({0}})"), Description->Name); } break; } case EFlareTransactionLogEntry::PeoplePurchase: { //UFlareSimulatedSpacecraft* OtherSpacecraftCache = Game->GetGameWorld()->FindSpacecraft(ExtraIdentifier1); if(ResourceCache) { FText ResourceComment = FText::Format(LOCTEXT("PeoplePurchaseResources", "{0} {1}"), ResourceQuantity, ResourceCache->Name); Comment = FText::Format(LOCTEXT("PeoplePurchase", "Population bought {0}"), ResourceComment); } break; } case EFlareTransactionLogEntry::InitialMoney: { Comment = LOCTEXT("InitialMoney", "Initial company capital"); break; } case EFlareTransactionLogEntry::PayRepair: { Comment = FText::Format(LOCTEXT("PayRepair", "Spacecraft repairs ({0} fleet supply)"), ResourceQuantity); break; } case EFlareTransactionLogEntry::PayRefill: { Comment = FText::Format(LOCTEXT("PayRefill", "Weapons refilling ({0} fleet supply)"), ResourceQuantity); break; } case EFlareTransactionLogEntry::PaidForRepair: { Comment = FText::Format(LOCTEXT("PaidForRepair", "Paid for repairs ({0} fleet supply)"), ResourceQuantity); break; } case EFlareTransactionLogEntry::PaidForRefill: { Comment = FText::Format(LOCTEXT("PaidForRefill", "Paid for refilling ({0} fleet supply)"), ResourceQuantity); break; } case EFlareTransactionLogEntry::SendTribute: { Comment = LOCTEXT("SendTribute", "Paid tribute"); break; } case EFlareTransactionLogEntry::ReceiveTribute: { Comment = LOCTEXT("ReceiveTribute", "Received tribute"); break; } case EFlareTransactionLogEntry::RecoveryFees: { Comment = LOCTEXT("RecoveryFees", "Recovery fees"); break; } case EFlareTransactionLogEntry::ScrapGain: { Comment = LOCTEXT("ScrapGain", "Scrap money"); break; } case EFlareTransactionLogEntry::Cheat: { Comment = LOCTEXT("Cheat", "Unlawful transaction"); break; } case EFlareTransactionLogEntry::QuestReward: { Comment = LOCTEXT("QuestReward", "Contract reward"); break; } // AI only: // MutualAssistance, // ScrapCost default: Comment = FText::Format(LOCTEXT("Dummy", "Dummy comment {0}"), int(Type)); } return Comment; }
void SectorHelper::ConsumeFleetSupply(UFlareSimulatedSector* Sector, UFlareCompany* Company, int32 ConsumedFS, bool ForRepair) { // First check for owned FS Sector->OnFleetSupplyConsumed(ConsumedFS); FFlareResourceDescription* FleetSupply = Sector->GetGame()->GetScenarioTools()->FleetSupply; for (int32 SpacecraftIndex = 0; SpacecraftIndex < Sector->GetSectorSpacecrafts().Num(); SpacecraftIndex++) { UFlareSimulatedSpacecraft* Spacecraft = Sector->GetSectorSpacecrafts()[SpacecraftIndex]; if (Company != Spacecraft->GetCompany()) { continue; } int TakenQuantity = Spacecraft->GetActiveCargoBay()->TakeResources(FleetSupply, ConsumedFS, Company); ConsumedFS -= TakenQuantity; if(ConsumedFS == 0) { return; } } for (int32 SpacecraftIndex = 0; SpacecraftIndex < Sector->GetSectorSpacecrafts().Num(); SpacecraftIndex++) { UFlareSimulatedSpacecraft* Spacecraft = Sector->GetSectorSpacecrafts()[SpacecraftIndex]; if (Company == Spacecraft->GetCompany()) { continue; } if (Spacecraft->IsHostile(Company)) { // At war, no trade possible continue; } int TakenQuantity = Spacecraft->GetActiveCargoBay()->TakeResources(FleetSupply, ConsumedFS, Company); if(TakenQuantity > 0) { int32 ResourcePrice = Sector->GetResourcePrice(FleetSupply, EFlareResourcePriceContext::MaintenanceConsumption); int64 Cost = TakenQuantity * ResourcePrice; Company->TakeMoney(Cost, true, FFlareTransactionLogEntry::LogPayMaintenance(Spacecraft, TakenQuantity, ForRepair)); Spacecraft->GetCompany()->GiveMoney(Cost, FFlareTransactionLogEntry::LogPaidForMaintenance(Spacecraft, Company, TakenQuantity, ForRepair)); if(Spacecraft->GetCurrentFleet() && Spacecraft->GetCurrentFleet()->IsAutoTrading()) { Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsUnloadResources += TakenQuantity; Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsMoneySell += Cost; #if DEBUG_AI_TRADING_STATS FLOGV("Auto trading %s sell %d %s to %s for %lld", *Spacecraft->GetImmatriculation().ToString(), TakenQuantity, *FleetSupply->Name.ToString(), *Company->GetCompanyName().ToString(), Cost); FLOGV("AutoTradeStatsDays=%d LoadResources=%d UnloadResources=%d MoneyBuy=%lld MoneySell=%lld", Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsDays, Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsLoadResources, Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsUnloadResources, Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsMoneyBuy, Spacecraft->GetCurrentFleet()->GetData()->AutoTradeStatsMoneySell); #endif } ConsumedFS -= TakenQuantity; if(ConsumedFS == 0) { return; } } } }
void SectorHelper::RefillFleets(UFlareSimulatedSector* Sector, UFlareCompany* Company) { SCOPE_CYCLE_COUNTER(STAT_FlareSectorHelper_RefillFleets); int32 CurrentNeededFleetSupply; int32 TotalNeededFleetSupply; int32 OwnedFS; int32 AvailableFS; int32 AffordableFS; int64 MaxDuration; GetRefillFleetSupplyNeeds(Sector, Company, CurrentNeededFleetSupply, TotalNeededFleetSupply, MaxDuration, true); GetAvailableFleetSupplyCount(Sector, Company, OwnedFS, AvailableFS, AffordableFS); // Note not available fleet supply as consumed Sector->OnFleetSupplyConsumed(FMath::Max(0, TotalNeededFleetSupply - AvailableFS)); if(Sector->IsInDangerousBattle(Company) || AffordableFS == 0 || TotalNeededFleetSupply == 0) { // No refill possible return; } float MaxRefillRatio = FMath::Min(1.f,(float) AffordableFS / (float) TotalNeededFleetSupply); float RemainingFS = (float) AffordableFS; UFlareSpacecraftComponentsCatalog* Catalog = Company->GetGame()->GetShipPartsCatalog(); for (int32 SpacecraftIndex = 0; SpacecraftIndex < Sector->GetSectorSpacecrafts().Num(); SpacecraftIndex++) { UFlareSimulatedSpacecraft* Spacecraft = Sector->GetSectorSpacecrafts()[SpacecraftIndex]; if (Company != Spacecraft->GetCompany() || !Spacecraft->GetDamageSystem()->IsAlive()) { continue; } float SpacecraftPreciseTotalNeededFleetSupply = 0; // List components for (int32 ComponentIndex = 0; ComponentIndex < Spacecraft->GetData().Components.Num(); ComponentIndex++) { FFlareSpacecraftComponentSave* ComponentData = &Spacecraft->GetData().Components[ComponentIndex]; FFlareSpacecraftComponentDescription* ComponentDescription = Catalog->Get(ComponentData->ComponentIdentifier); if(ComponentDescription->Type == EFlarePartType::Weapon) { int32 MaxAmmo = ComponentDescription->WeaponCharacteristics.AmmoCapacity; int32 CurrentAmmo = MaxAmmo - ComponentData->Weapon.FiredAmmo; float FillRatio = (float) CurrentAmmo / (float) MaxAmmo; float TotalRefillRatio = 1.f - FillRatio; SpacecraftPreciseTotalNeededFleetSupply += TotalRefillRatio * UFlareSimulatedSpacecraftDamageSystem::GetRefillCost(ComponentDescription); } } float SpacecraftNeededWithoutStock = SpacecraftPreciseTotalNeededFleetSupply - Spacecraft->GetRefillStock(); float SpacecraftNeededWithoutStockScaled = FMath::Max(0.f, SpacecraftNeededWithoutStock * MaxRefillRatio); float ConsumedFS = FMath::Min(RemainingFS, SpacecraftNeededWithoutStockScaled); Spacecraft->OrderRefillStock(ConsumedFS); RemainingFS -= ConsumedFS; if(RemainingFS <= 0) { break; } } int32 ConsumedFS = FMath::CeilToInt((float) AffordableFS - RemainingFS); ConsumeFleetSupply(Sector, Company, ConsumedFS, false); if(ConsumedFS > 0 && Company == Sector->GetGame()->GetPC()->GetCompany()) { Sector->GetGame()->GetQuestManager()->OnEvent(FFlareBundle().PutTag("refill-start")); } }
void SectorHelper::RepairFleets(UFlareSimulatedSector* Sector, UFlareCompany* Company) { SCOPE_CYCLE_COUNTER(STAT_FlareSectorHelper_RepairFleets); int32 CurrentNeededFleetSupply; int32 TotalNeededFleetSupply; int32 OwnedFS; int32 AvailableFS; int32 AffordableFS; int64 MaxDuration; GetRepairFleetSupplyNeeds(Sector, Company, CurrentNeededFleetSupply, TotalNeededFleetSupply, MaxDuration, true); GetAvailableFleetSupplyCount(Sector, Company, OwnedFS, AvailableFS, AffordableFS); // Note not available fleet supply as consumed Sector->OnFleetSupplyConsumed(FMath::Max(0, TotalNeededFleetSupply - AvailableFS)); if(Sector->IsInDangerousBattle(Company) || AffordableFS == 0 || TotalNeededFleetSupply == 0) { // No repair possible //FLOGV("No repair possible for %s in %s", *Company->GetCompanyName().ToString(), *Sector->GetSectorName().ToString()) return; } float RepairRatio = FMath::Min(1.f,(float) AffordableFS / (float) TotalNeededFleetSupply); float RemainingFS = (float) AffordableFS; UFlareSpacecraftComponentsCatalog* Catalog = Company->GetGame()->GetShipPartsCatalog(); for (int32 SpacecraftIndex = 0; SpacecraftIndex < Sector->GetSectorSpacecrafts().Num(); SpacecraftIndex++) { UFlareSimulatedSpacecraft* Spacecraft = Sector->GetSectorSpacecrafts()[SpacecraftIndex]; if (Company != Spacecraft->GetCompany() || !Spacecraft->GetDamageSystem()->IsAlive()) { continue; } float SpacecraftPreciseTotalNeededFleetSupply = 0; // List components for (int32 ComponentIndex = 0; ComponentIndex < Spacecraft->GetData().Components.Num(); ComponentIndex++) { FFlareSpacecraftComponentSave* ComponentData = &Spacecraft->GetData().Components[ComponentIndex]; FFlareSpacecraftComponentDescription* ComponentDescription = Catalog->Get(ComponentData->ComponentIdentifier); float DamageRatio = Spacecraft->GetDamageSystem()->GetDamageRatio(ComponentDescription, ComponentData); float TotalRepairRatio = 1.f - DamageRatio; SpacecraftPreciseTotalNeededFleetSupply += TotalRepairRatio * UFlareSimulatedSpacecraftDamageSystem::GetRepairCost(ComponentDescription); } float SpacecraftNeededWithoutStock = SpacecraftPreciseTotalNeededFleetSupply - Spacecraft->GetRepairStock(); float SpacecraftNeededWithoutStockScaled = FMath::Max(0.f, SpacecraftNeededWithoutStock * RepairRatio); float ConsumedFS = FMath::Min(RemainingFS, SpacecraftNeededWithoutStockScaled); Spacecraft->OrderRepairStock(ConsumedFS); RemainingFS -= ConsumedFS; if(RemainingFS <= 0) { break; } } int32 ConsumedFS = FMath::CeilToInt((float) AffordableFS - RemainingFS); ConsumeFleetSupply(Sector, Company, ConsumedFS, true); if(ConsumedFS > 0 && Company == Sector->GetGame()->GetPC()->GetCompany()) { Sector->GetGame()->GetQuestManager()->OnEvent(FFlareBundle().PutTag("repair-start")); } }
UFlareSimulatedSpacecraft* SectorHelper::FindTradeStation(FlareTradeRequest Request) { //FLOGV("FindTradeStation of %s for %s (%d)", *Request.Resource->Acronym.ToString(), *Request.Client->GetImmatriculation().ToString(), (Request.Operation + 0)); if(!Request.Client || !Request.Client->GetCurrentSector()) { FLOG("Invalid find trade query"); return NULL; } UFlareCompany* ClientCompany = Request.AllowUseNoTradeForMe ? Request.Client->GetCompany() : nullptr; UFlareSimulatedSector* Sector = Request.Client->GetCurrentSector(); TArray<UFlareSimulatedSpacecraft*>& SectorStations = Sector->GetSectorStations(); float UnloadQuantityScoreMultiplier = 0; float LoadQuantityScoreMultiplier = 0; float SellQuantityScoreMultiplier = 0; float BuyQuantityScoreMultiplier = 0; float FullRatioBonus = 0; float EmptyRatioBonus = 0; bool NeedInput = false; bool NeedOutput = false; switch(Request.Operation) { case EFlareTradeRouteOperation::Buy: BuyQuantityScoreMultiplier = 10.f; FullRatioBonus = 0.1; NeedOutput = true; break; case EFlareTradeRouteOperation::Sell: SellQuantityScoreMultiplier = 10.f; EmptyRatioBonus = 0.1; NeedInput = true; break; case EFlareTradeRouteOperation::Load: LoadQuantityScoreMultiplier = 10.f; FullRatioBonus = 0.1; NeedOutput = true; break; case EFlareTradeRouteOperation::Unload: UnloadQuantityScoreMultiplier = 10.f; EmptyRatioBonus = 0.1; NeedInput = true; break; case EFlareTradeRouteOperation::LoadOrBuy: LoadQuantityScoreMultiplier = 10.f; BuyQuantityScoreMultiplier = 1.f; FullRatioBonus = 0.1; NeedOutput = true; break; case EFlareTradeRouteOperation::UnloadOrSell: UnloadQuantityScoreMultiplier = 10.f; SellQuantityScoreMultiplier = 1.f; EmptyRatioBonus = 0.1; NeedInput = true; break; } float BestScore = 0; UFlareSimulatedSpacecraft* BestStation = NULL; uint32 AvailableQuantity = Request.Client->GetActiveCargoBay()->GetResourceQuantity(Request.Resource, ClientCompany); uint32 FreeSpace = Request.Client->GetActiveCargoBay()->GetFreeSpaceForResource(Request.Resource, ClientCompany); for (int32 StationIndex = 0; StationIndex < SectorStations.Num(); StationIndex++) { UFlareSimulatedSpacecraft* Station = SectorStations[StationIndex]; //FLOGV(" Check trade for %s", *Station->GetImmatriculation().ToString()); FText Unused; if(!Request.Client->CanTradeWith(Station, Unused)) { //FLOG(" cannot trade with"); continue; } if(!Request.AllowStorage && Station->HasCapability(EFlareSpacecraftCapability::Storage)) { continue; } FFlareResourceUsage StationResourceUsage = Station->GetResourceUseType(Request.Resource); if(NeedOutput && (!StationResourceUsage.HasUsage(EFlareResourcePriceContext::FactoryOutput) && !StationResourceUsage.HasUsage(EFlareResourcePriceContext::ConsumerConsumption) && !StationResourceUsage.HasUsage(EFlareResourcePriceContext::HubOutput))) { //FLOG(" need output but dont provide it"); continue; } if(NeedInput && (!StationResourceUsage.HasUsage(EFlareResourcePriceContext::FactoryInput) && !StationResourceUsage.HasUsage(EFlareResourcePriceContext::ConsumerConsumption) && !StationResourceUsage.HasUsage(EFlareResourcePriceContext::MaintenanceConsumption) && !StationResourceUsage.HasUsage(EFlareResourcePriceContext::HubInput))) { //FLOG(" need input but dont provide it"); continue; } int32 StationFreeSpace = Station->GetActiveCargoBay()->GetFreeSpaceForResource(Request.Resource, ClientCompany); int32 StationResourceQuantity = Station->GetActiveCargoBay()->GetResourceQuantity(Request.Resource, ClientCompany); if (!Station->IsUnderConstruction() && Station->IsComplex() && !Request.AllowFullStock) { if(Station->GetActiveCargoBay()->WantBuy(Request.Resource, ClientCompany) && Station->GetActiveCargoBay()->WantSell(Request.Resource, ClientCompany)) { int32 TotalCapacity = Station->GetActiveCargoBay()->GetTotalCapacityForResource(Request.Resource, ClientCompany); StationFreeSpace = FMath::Max(0, StationFreeSpace - TotalCapacity / 2); StationResourceQuantity = FMath::Max(0, StationResourceQuantity - TotalCapacity / 2); } } if (StationFreeSpace == 0 && StationResourceQuantity == 0) { //FLOG(" need quantity or resource"); continue; } float Score = 0; float FullRatio = (float) StationResourceQuantity / (float) (StationResourceQuantity + StationFreeSpace); float EmptyRatio = 1 - FullRatio; uint32 UnloadMaxQuantity = 0; uint32 LoadMaxQuantity = 0; if(!Station->IsUnderConstruction()) { // Check cargo limit if(NeedOutput && Request.CargoLimit != -1 && FullRatio < Request.CargoLimit / Station->GetLevel()) { continue; } if(NeedInput && Request.CargoLimit != -1 && FullRatio > (1.f - (1.f - Request.CargoLimit) / Station->GetLevel())) { continue; } } else if (Station->HasCapability(EFlareSpacecraftCapability::Storage)) { continue; } if(Station->GetActiveCargoBay()->WantBuy(Request.Resource, ClientCompany)) { UnloadMaxQuantity = StationFreeSpace; UnloadMaxQuantity = FMath::Min(UnloadMaxQuantity , AvailableQuantity); } if(Station->GetActiveCargoBay()->WantSell(Request.Resource, ClientCompany)) { LoadMaxQuantity = StationResourceQuantity; LoadMaxQuantity = FMath::Min(LoadMaxQuantity , FreeSpace); } if(Station->GetCompany() == Request.Client->GetCompany()) { Score += UnloadMaxQuantity * UnloadQuantityScoreMultiplier; Score += LoadMaxQuantity * LoadQuantityScoreMultiplier; } else { FFlareResourceUsage ResourceUsage = Station->GetResourceUseType(Request.Resource); int32 ResourcePrice = 0; if(NeedInput) { ResourcePrice = Sector->GetTransfertResourcePrice(NULL, Station, Request.Resource); } else { ResourcePrice = Sector->GetTransfertResourcePrice(Station, NULL, Request.Resource); } uint32 MaxBuyableQuantity = Request.Client->GetCompany()->GetMoney() / SectorHelper::GetBuyResourcePrice(Sector, Request.Resource, ResourceUsage); LoadMaxQuantity = FMath::Min(LoadMaxQuantity , MaxBuyableQuantity); uint32 MaxSellableQuantity = Station->GetCompany()->GetMoney() / SectorHelper::GetSellResourcePrice(Sector, Request.Resource, ResourceUsage); UnloadMaxQuantity = FMath::Min(UnloadMaxQuantity , MaxSellableQuantity); Score += UnloadMaxQuantity * SellQuantityScoreMultiplier; Score += LoadMaxQuantity * BuyQuantityScoreMultiplier; } Score *= 1 + (FullRatio * FullRatioBonus) + (EmptyRatio * EmptyRatioBonus); if(Station->IsUnderConstruction()) { Score *= 10000; /*FLOGV("Station %s is under construction. Score %f, BestScore %f", *Station->GetImmatriculation().ToString(), Score, BestScore)*/ } else if(Station->HasCapability(EFlareSpacecraftCapability::Storage)) { Score *= 0.01; } if(Score > 0 && Score > BestScore) { BestScore = Score; BestStation = Station; } } //FLOGV("FindTradeStation result %p", BestStation); return BestStation; }
void AFlareGame::ActivateSector(UFlareSimulatedSector* Sector) { if (!Sector) { // No sector to activate return; } // Load the sector level - Will call OnLevelLoaded() LoadStreamingLevel(Sector->GetDescription()->LevelName); // Check if we should really activate FLOGV("AFlareGame::ActivateSector : %s", *Sector->GetSectorName().ToString()); if (ActiveSector) { FLOG("AFlareGame::ActivateSector : There is already an active sector"); if (ActiveSector->GetSimulatedSector()->GetIdentifier() == Sector->GetIdentifier()) { // Sector to activate is already active return; } // Deactivate the sector DeactivateSector(); } // Ships FLOGV("AFlareGame::ActivateSector : Ship count = %d", Sector->GetSectorShips().Num()); bool PlayerHasShip = false; for (int ShipIndex = 0; ShipIndex < Sector->GetSectorShips().Num(); ShipIndex++) { UFlareSimulatedSpacecraft* Ship = Sector->GetSectorShips()[ShipIndex]; FLOGV("AFlareGame::ActivateSector : Found ship %s", *Ship->GetImmatriculation().ToString()); if (Ship->GetCompany()->GetPlayerHostility() == EFlareHostility::Owned) { PlayerHasShip = true; break; } } // Planetarium & sector setup FLOGV("AFlareGame::ActivateSector : PlayerHasShip = %d", PlayerHasShip); if (PlayerHasShip) { // Create the new sector ActiveSector = NewObject<UFlareSector>(this, UFlareSector::StaticClass()); FFlareSectorSave* SectorData = Sector->Save(); if ((SectorData->LocalTime / UFlareGameTools::SECONDS_IN_DAY) < GetGameWorld()->GetDate()) { // TODO Find time with light SectorData->LocalTime = GetGameWorld()->GetDate() * UFlareGameTools::SECONDS_IN_DAY; } // Load and setup the sector Planetarium->ResetTime(); Planetarium->SkipNight(UFlareGameTools::SECONDS_IN_DAY); ActiveSector->Load(Sector); DebrisFieldSystem->Setup(this, Sector); GetPC()->OnSectorActivated(ActiveSector); } GetQuestManager()->OnSectorActivation(Sector); }