Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #5
0
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;
}
Beispiel #10
0
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);
}