Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Fill out your copyright notice in the Description page of Project Settings.
- #pragma once
- #include "CoreMinimal.h"
- #include "Components/ActorComponent.h"
- #include "MasterBank.generated.h"
- // Declare custom struct to hold player resources and expose to blueprints
- USTRUCT(BlueprintType)
- struct FResource_Data_Master
- {
- GENERATED_USTRUCT_BODY()
- public:
- // The name of the resource
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
- FString Resource_Name;
- // The amount of this resource in the player's bank
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
- int32 Resource_Balance;
- // The amount of resource per premium unit (100 here means 1 premium unit would be equivalent to 100 units of this resource)
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
- int32 Conversion_Ratio;
- // Identifies the resource as a premium resource (can have only one of these)
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
- bool Is_Premium;
- };
- // Declare custom struct for storing upgrade cost data and expose to blueprints
- USTRUCT(BlueprintType)
- struct FCost_Data_Master
- {
- GENERATED_USTRUCT_BODY()
- public:
- // The name of the resource
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
- FString Resource_Name;
- // The amount of this resource needed for the upgrade/purchase item
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
- int32 Resource_Cost;
- };
- UCLASS( ClassGroup=(Custom), Blueprintable, meta=(BlueprintSpawnableComponent) )
- class CODE_TEST_API UMasterBank : public UActorComponent
- {
- GENERATED_BODY()
- public:
- // Sets default values for this component's properties
- UMasterBank();
- // Function called to initially attempt to spend the player's resources
- UFUNCTION(BlueprintCallable, Category = "Purchases and Upgrades", meta = (Keywords = "call, spend, purchase, resource, upgrade"))
- void Spend_Resources(UPARAM(ref) TArray<FResource_Data_Master> &Available_Resources, TArray<FCost_Data_Master> Cost);
- // Blueprint implemented event that fires if the player has sufficient resources **DOES NOT SPEND THE RESOURCES**
- UFUNCTION(BlueprintImplementableEvent, Category = "Purchases and Upgrades")
- void Confirm_Purchase();
- // Blueprint implemented event that fires if the player does not have sufficient resources **DOES NOT INCLUDE THE PREMIUM CURRENCY**
- UFUNCTION(BlueprintImplementableEvent, Category = "Purchases and Upgrades")
- void Insufficient_Funds();
- // Function that will actually adjust the player's resources to accomodate the upgrade/purchase, will fire 'Insufficient Funds' if premium currency is not enough (assuming this was necessary)
- UFUNCTION(BlueprintCallable, Category = "Purchases and Upgrades", meta = (Keywords = "call, spend, purchase, resource, upgrade, confirm, premium"))
- void Utilize_Resources();
- // Internal function to calculate the amount of premium currency needed to cover resource deficits
- void Calculate_Premium_Coverage(TArray<FCost_Data_Master>Cost);
- // The running total of premium currency needed to cover the deficits in other resources
- UPROPERTY(BlueprintReadOnly, Category = "Master Bank Data")
- int32 PremiumCurrencyTotal;
- // Error handling string
- UPROPERTY(BlueprintReadOnly, Category = "Master Bank Data")
- FString ErrorMessage;
- // Keeps track of whether or not the player has sufficient funds to go through with the upgrade/purchase
- bool HasSufficientFunds;
- // Alerts user to an error in naming of the resources (mismatch between the cost and player's resource array names)
- bool ResourceNameError;
- // Ensures the user first calls "Spend Resources" prior to the function call that actually reduces these resources in the player's bank
- bool SpendResourcesCalled;
- // If a resource was improperly named this will idetify it and append it to the error message
- FString ImproperName;
- // Create a pointer to the player's actual resource data
- TArray<FResource_Data_Master>*StoredArrayData;
- // Create a copy of the player's resource data for internal use and modification
- TArray<FResource_Data_Master>TempResourceArray;
- // Called every frame
- virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
- protected:
- // Called when the game starts
- virtual void BeginPlay() override;
- };
- ----------------------------------------------------------------------------------------------------------------------------
- // Fill out your copyright notice in the Description page of Project Settings.
- #include "MasterBank.h"
- // Sets default values for this component's properties
- UMasterBank::UMasterBank()
- {
- //Turn tick off for this component
- PrimaryComponentTick.bCanEverTick = false;
- // Set variable defaults
- HasSufficientFunds = true;
- ResourceNameError = false;
- SpendResourcesCalled = false;
- PremiumCurrencyTotal = 0;
- }
- // Called when the game starts
- void UMasterBank::BeginPlay()
- {
- Super::BeginPlay();
- }
- // Called every frame
- void UMasterBank::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
- {
- Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
- }
- void UMasterBank::Spend_Resources(UPARAM(ref)TArray<FResource_Data_Master>&Available_Resources, TArray<FCost_Data_Master>Cost)
- {
- // Ensure the user has entered at least one player resource and one cost resource
- if (Available_Resources.Num() > 0 && Cost.Num() > 0)
- {
- // Create a copy and a pointer to the player's resource data
- StoredArrayData = &Available_Resources;
- TempResourceArray = Available_Resources;
- // Loop through each cost resource and find the matching resource by name in the player's resource data array
- for (int x = 0; x < Cost.Num(); ++x)
- {
- for (int y = 0; y < TempResourceArray.Num(); ++y)
- {
- // If the name from the player's resource array matches the cost array subtract the cost from the player's resources
- if (TempResourceArray[y].Resource_Name == Cost[x].Resource_Name)
- {
- TempResourceArray[y].Resource_Balance -= Cost[x].Resource_Cost;
- // If the player now has a negative value for a particular resource set 'HasSufficientFunds' to false
- if (TempResourceArray[y].Resource_Balance <= 0)
- {
- HasSufficientFunds = false;
- }
- break;
- }
- // If we have looped through the entire array and have not identified the resource throw an error and give the name of the resource that could not be identified
- else if (y == (TempResourceArray.Num() -1))
- {
- HasSufficientFunds = false;
- ResourceNameError = true;
- ImproperName = Cost[x].Resource_Name;
- }
- }
- }
- // If we have sufficient funds and there were no naming errors proceed with confirmation of the upgrade/purchase
- if (HasSufficientFunds == true && ResourceNameError == false)
- {
- // This ensures a successful call of the 'Spend Resource' function has occured, otherwise calling 'Utilize Resources' will not be appropriate
- SpendResourcesCalled = true;
- // Fires the blueprint implemented event to allow for confirmation prior to deducting resources
- Confirm_Purchase();
- }
- // If we don't have sufficient funds BUT there were no errors we can proceed and check if our premium currency can cover the deficits
- else if (HasSufficientFunds == false && ResourceNameError == false)
- {
- // This ensures a successful call of the 'Spend Resource' function has occured, otherwise calling 'Utilize Resources' will not be appropriate
- SpendResourcesCalled = true;
- // Call to calculate the total resource deficit and the amount of premium currency required to cover it
- Calculate_Premium_Coverage(Cost);
- // Fires the blueprint implemented event to allow for the option to spend a premium currency (similar to 'Confirm Purchase', just an extra event)
- Insufficient_Funds();
- }
- // If we had a naming do not allow further progress ('SpendResourcesCalled' will remain false) and throw an error identifying the culprit resource
- else
- {
- ErrorMessage = ImproperName + " did not match any resource name listed in the Available Resources Array, resource utilization declined!";
- }
- }
- // If no members have been added to either the Available Resource or the Cost array, throw an error and prevent further progress
- else
- {
- ErrorMessage = "Available Resources and/or Cost Arrays Have No Members or There are more members in the Cost array than Avaiable Resources";
- }
- }
- // Function that calculates the premium currency coverage
- void UMasterBank::Calculate_Premium_Coverage(TArray<FCost_Data_Master>Cost)
- {
- // Start each call of this function assuming 0 premium currency is necessary
- PremiumCurrencyTotal = 0;
- // Loop through the player's resource array and identify all the non-premium resources with a negative balance
- for (int x = 0; x <TempResourceArray.Num(); ++x)
- {
- if (TempResourceArray[x].Resource_Balance < 0 && TempResourceArray[x].Is_Premium == false)
- {
- // For each resource with a negative balance, take the absolute value and divide by the conversion ratio always rounding up (partial use of a premium unit is = to the full unit)
- PremiumCurrencyTotal += FMath::DivideAndRoundUp(FMath::Abs(TempResourceArray[x].Resource_Balance), TempResourceArray[x].Conversion_Ratio);
- TempResourceArray[x].Resource_Balance = 0;
- }
- }
- // For troubleshooting purposes the error message will display the total amount of premium currency necessary to cover the deficit after this function call
- ErrorMessage = "The total amount of premium currency needed is " + FString::FromInt(PremiumCurrencyTotal);
- }
- // This function will actually deduct resources from the player's bank
- void UMasterBank::Utilize_Resources()
- {
- // Double check and make sure we have a successful call to 'Spend Resources' prior to using this function
- if (SpendResourcesCalled == true)
- {
- // If the player had sufficient resources outright then we simply set the player's resource data pointer to the temporary array values
- if (HasSufficientFunds == true)
- {
- *StoredArrayData = TempResourceArray;
- }
- // If the player did not have sufficient resources check and see if they have enough premium currency
- else if (HasSufficientFunds == false)
- {
- // Loop through the player's resource array until the premium currency index is found
- for (int x = 0; x < TempResourceArray.Num(); ++x)
- // If the player has enough of the premium currency deduct the total and set the array pointer to the temporary array values
- if (TempResourceArray[x].Is_Premium == true && ((TempResourceArray[x].Resource_Balance - PremiumCurrencyTotal) >= 0))
- {
- TempResourceArray[x].Resource_Balance -= PremiumCurrencyTotal;
- *StoredArrayData = TempResourceArray;
- ErrorMessage = "Premium Resource Spent";
- break;
- }
- // If the player did not have enough premium currency fire the 'Insufficient Funds' event again and return an error indicating this occurrence
- else if (TempResourceArray[x].Is_Premium == true && ((TempResourceArray[x].Resource_Balance - PremiumCurrencyTotal) < 0))
- {
- Insufficient_Funds();
- ErrorMessage = "Premium Resource Insufficient to Cover All Deficits";
- break;
- }
- else;
- }
- // Once this has completed set the 'SpendResourcesCalled' back to false to ensure proper calling of the 'SpendResources' function before using this again
- SpendResourcesCalled = false;
- }
- // If the user did not first call 'Spend Resources' we will alert them with this error message
- else
- {
- ErrorMessage = "Must call the function 'Spend Resources' prior to calling 'Utilize_Resources'";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment