// Fill out your copyright notice in the Description page of Project Settings. #include "Merchant.h" // Called when the game starts or when spawned void AMerchant::BeginPlay() { Super::BeginPlay(); timeManager = Cast(UGameplayStatics::GetActorOfClass(GetWorld(), ATimeOfDayManager::StaticClass())); timeManager->OnDayPassed.AddDynamic(this, &AMerchant::ShiftDemands); } // Called every frame void AMerchant::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void AMerchant::AddItem(UItem* item, bool generateDemand) { FDemandDay newDemandDay; if (generateDemand) { int32 lastDayDemand = newDemandDay.GenerateRandomDemands30Days(); CurrentDayItemsDemands.FindOrAdd(item, lastDayDemand); } ItemsDemands.Add(item, newDemandDay); } void AMerchant::ChangeItemDemand(UItem* item, int32 amount) { if (CurrentDayItemsDemands.Contains(item)) { CurrentDayItemsDemands[item] = amount; } } void AMerchant::IncreaseItemDemand(UItem* item, int32 amount) { if (CurrentDayItemsDemands.Contains(item)) { CurrentDayItemsDemands[item] += amount; if (CurrentDayItemsDemands[item] > 200) CurrentDayItemsDemands[item] = 200; } } void AMerchant::DecreaseItemDemand(UItem* item, int32 amount) { if (CurrentDayItemsDemands.Contains(item)) { CurrentDayItemsDemands[item] -= amount; if (CurrentDayItemsDemands[item] < 0) CurrentDayItemsDemands[item] = 0; } } int32 AMerchant::GetDemandForItem(UItem* item) { int32* itemDemand = CurrentDayItemsDemands.Find(item); if (itemDemand == nullptr || itemDemand == NULL) return 100; return *itemDemand; } TArray AMerchant::GetLast30DaysDemand(UItem* item) { FDemandDay* itemDemands = ItemsDemands.Find(item); TArray defaultDemands; if (itemDemands == nullptr || itemDemands == NULL) { for (size_t i = 0; i < 30; i++) { defaultDemands.Add(100); } return defaultDemands; } FDemandDay defaultDemandsDay = (*itemDemands); //Algo::Reverse(defaultDemandsDay.dayDemands); return defaultDemandsDay.dayDemands; } void AMerchant::GetDemandForItemLastDay(UItem* item, int32& demand) { TMap mapToReturn; auto demandDay = ItemsDemands.Find(item); if (demandDay == nullptr || demandDay == NULL) { demand = 100; } else { demand = demandDay->GetLastDayDemand(); } } int32 AMerchant::GetBuyCost(UItem* item) { int32* itemDemand = CurrentDayItemsDemands.Find(item); if (itemDemand == nullptr || itemDemand == NULL) { UE_LOG(LogTemp, Warning, TEXT("Buying cost for item not found!")); return item->BaseCost; } int32 demand = *itemDemand; float multiplier = ((float(demand) - 100.0f) / 200.0f) + 1.0f; return item->BaseCost * multiplier; } int32 AMerchant::GetSellCost(UItem* item) { int32 buyCost = GetBuyCost(item); const float multiplier = 0.8f; return buyCost * multiplier; } int32 AMerchant::CalculateCostForDemand(UItem* item, int32 demand) { float modifiedMultiplier = ((demand - 100.0f) / 200.0f) + 1.0f; float priceCorrection = float(item->BaseCost) * modifiedMultiplier; return FMath::RoundToInt(priceCorrection); } int32 AMerchant::CalculateCostForDemandPrice(int32 cost, int32 demand) { float modifiedMultiplier = ((demand - 100.0f) / 200.0f) + 1.0f; float priceCorrection = float(cost) * modifiedMultiplier; return FMath::RoundToInt(priceCorrection); } void AMerchant::ShiftDemands() { for (auto& itemDemand : ItemsDemands) { for (int32 i = itemDemand.Value.dayDemands.Num() - 1; i > 0; i--) { itemDemand.Value.dayDemands[i] = itemDemand.Value.dayDemands[i - 1]; } itemDemand.Value.dayDemands[0] = CurrentDayItemsDemands[itemDemand.Key]; int32 firstDayLower = itemDemand.Value.dayDemands[0] - 50; if (firstDayLower < 0) firstDayLower = 0; int32 firstDayUpper = itemDemand.Value.dayDemands[0] + 50; if (firstDayUpper > 200) firstDayUpper = 200; CurrentDayItemsDemands[itemDemand.Key] = FMath::RandRange(firstDayLower, firstDayUpper); } } /// /// Picks 3 most in demand items, excluding seeds and returns them /// /// An array of items which are in demand TArray AMerchant::PickMostInDemandItems() { TArray indexesToIgnore; TArray keys; ItemsDemands.GenerateKeyArray(keys); if (ItemsMostDemands.Num() == 0) { for (size_t i = 0; i < 3; i++) { ItemsMostDemands.Add(keys[0]); } } for (int32 i = 0; i < 3; i++) { int32 highestDemand = 0; int32 highestDemandIndex = 0; for (int32 j = 0; j < keys.Num(); j++) { if (indexesToIgnore.Contains(j) || keys[j]->Category == Category::Seed) continue; if (ItemsDemands[keys[j]].GetLastDayDemand() >= highestDemand) { highestDemand = ItemsDemands[keys[j]].GetLastDayDemand(); highestDemandIndex = j; } } indexesToIgnore.Add(highestDemandIndex); ItemsMostDemands[i] = (keys[highestDemandIndex]); } return ItemsMostDemands; } float AMerchant::GetPriceChangeFromLastDay(UItem* item) { int32 currentDemand = 100; int32 lastDayDemand = 100; auto currentDemandPtr = CurrentDayItemsDemands.Find(item); auto lastDayMemandPtr = ItemsDemands.Find(item); if (currentDemandPtr != nullptr) currentDemand = *currentDemandPtr; if (lastDayMemandPtr != nullptr) lastDayDemand = (*lastDayMemandPtr).GetLastDayDemand(); UE_LOG(LogTemp, Warning, TEXT("Current demand %d"), currentDemand); UE_LOG(LogTemp, Warning, TEXT("Last day demand %d"), lastDayDemand); int32 currentCost = CalculateCostForDemand(item, currentDemand); int32 lastDayCost = CalculateCostForDemand(item, lastDayDemand); UE_LOG(LogTemp, Warning, TEXT("Current cost %d"), currentCost); UE_LOG(LogTemp, Warning, TEXT("Last day cost %d"), lastDayCost); return (((float)currentCost - (float)lastDayCost) / (float)lastDayCost) * 100.0f; }