NebulaGames

Update To Purchase Node

May 20th, 2019
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.65 KB | None | 0 0
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2.  
  3. #pragma once
  4.  
  5. #include "CoreMinimal.h"
  6. #include "Components/ActorComponent.h"
  7. #include "MasterBank.generated.h"
  8.  
  9.  
  10.  // Declare custom struct to hold player resources and expose to blueprints
  11. USTRUCT(BlueprintType)
  12. struct FResource_Data_Master
  13. {
  14.     GENERATED_USTRUCT_BODY()
  15.  
  16. public:
  17.  
  18.     // The name of the resource
  19.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
  20.         FString Resource_Name;
  21.     // The amount of this resource in the player's bank
  22.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
  23.         int32 Resource_Balance;
  24.     // The amount of resource per premium unit (100 here means 1 premium unit would be equivalent to 100 units of this resource)
  25.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
  26.         int32 Conversion_Ratio;
  27.     // Identifies the resource as a premium resource (can have only one of these)
  28.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
  29.         bool Is_Premium;
  30. };
  31.  
  32. // Declare custom struct for storing upgrade cost data and expose to blueprints
  33. USTRUCT(BlueprintType)
  34. struct FCost_Data_Master
  35. {
  36.     GENERATED_USTRUCT_BODY()
  37.  
  38. public:
  39.  
  40.     // The name of the resource
  41.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
  42.         FString Resource_Name;
  43.     // The amount of this resource needed for the upgrade/purchase item
  44.     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Master Bank Data")
  45.         int32 Resource_Cost;
  46. };
  47.  
  48. UCLASS( ClassGroup=(Custom), Blueprintable, meta=(BlueprintSpawnableComponent) )
  49. class CODE_TEST_API UMasterBank : public UActorComponent
  50. {
  51.     GENERATED_BODY()
  52.  
  53. public:
  54.     // Sets default values for this component's properties
  55.     UMasterBank();
  56.  
  57.     // Function called to initially attempt to spend the player's resources
  58.     UFUNCTION(BlueprintCallable, Category = "Purchases and Upgrades", meta = (Keywords = "call, spend, purchase, resource, upgrade"))
  59.         void Spend_Resources(UPARAM(ref) TArray<FResource_Data_Master> &Available_Resources, TArray<FCost_Data_Master> Cost);
  60.     // Blueprint implemented event that fires if the player has sufficient resources **DOES NOT SPEND THE RESOURCES**
  61.     UFUNCTION(BlueprintImplementableEvent, Category = "Purchases and Upgrades")
  62.         void Confirm_Purchase();
  63.     // Blueprint implemented event that fires if the player does not have sufficient resources **DOES NOT INCLUDE THE PREMIUM CURRENCY**
  64.     UFUNCTION(BlueprintImplementableEvent, Category = "Purchases and Upgrades")
  65.         void Insufficient_Funds();
  66.     // 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)
  67.     UFUNCTION(BlueprintCallable, Category = "Purchases and Upgrades", meta = (Keywords = "call, spend, purchase, resource, upgrade, confirm, premium"))
  68.         void Utilize_Resources();
  69.     // Internal function to calculate the amount of premium currency needed to cover resource deficits
  70.     void Calculate_Premium_Coverage(TArray<FCost_Data_Master>Cost);
  71.  
  72.     // The running total of premium currency needed to cover the deficits in other resources
  73.     UPROPERTY(BlueprintReadOnly, Category = "Master Bank Data")
  74.         int32 PremiumCurrencyTotal;
  75.     // Error handling string
  76.     UPROPERTY(BlueprintReadOnly, Category = "Master Bank Data")
  77.         FString ErrorMessage;
  78.  
  79.     // Keeps track of whether or not the player has sufficient funds to go through with the upgrade/purchase
  80.     bool HasSufficientFunds;
  81.     // Alerts user to an error in naming of the resources (mismatch between the cost and player's resource array names)
  82.     bool ResourceNameError;
  83.     // Ensures the user first calls "Spend Resources" prior to the function call that actually reduces these resources in the player's bank
  84.     bool SpendResourcesCalled;
  85.     // If a resource was improperly named this will idetify it and append it to the error message
  86.     FString ImproperName;
  87.     // Create a pointer to the player's actual resource data
  88.     TArray<FResource_Data_Master>*StoredArrayData;
  89.     // Create a copy of the player's resource data for internal use and modification
  90.     TArray<FResource_Data_Master>TempResourceArray;
  91.  
  92.     // Called every frame
  93.     virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
  94.  
  95. protected:
  96.     // Called when the game starts
  97.     virtual void BeginPlay() override;     
  98. };
  99.  
  100. ----------------------------------------------------------------------------------------------------------------------------
  101.  
  102. // Fill out your copyright notice in the Description page of Project Settings.
  103.  
  104. #include "MasterBank.h"
  105.  
  106. // Sets default values for this component's properties
  107. UMasterBank::UMasterBank()
  108. {
  109.     //Turn tick off for this component
  110.     PrimaryComponentTick.bCanEverTick = false;
  111.  
  112.     // Set variable defaults
  113.     HasSufficientFunds = true;
  114.     ResourceNameError = false;
  115.     SpendResourcesCalled = false;
  116.     PremiumCurrencyTotal = 0;
  117. }
  118.  
  119. // Called when the game starts
  120. void UMasterBank::BeginPlay()
  121. {
  122.     Super::BeginPlay();
  123.    
  124. }
  125.  
  126. // Called every frame
  127. void UMasterBank::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
  128. {
  129.     Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
  130.  
  131. }
  132.  
  133. void UMasterBank::Spend_Resources(UPARAM(ref)TArray<FResource_Data_Master>&Available_Resources, TArray<FCost_Data_Master>Cost)
  134. {
  135.     // Ensure the user has entered at least one player resource and one cost resource
  136.     if (Available_Resources.Num() > 0 && Cost.Num() > 0)
  137.     {
  138.         // Create a copy and a pointer to the player's resource data
  139.         StoredArrayData = &Available_Resources;
  140.         TempResourceArray = Available_Resources;
  141.        
  142.         // Loop through each cost resource and find the matching resource by name in the player's resource data array
  143.         for (int x = 0; x < Cost.Num(); ++x)
  144.         {
  145.             for (int y = 0; y < TempResourceArray.Num(); ++y)
  146.             {
  147.                 // If the name from the player's resource array matches the cost array subtract the cost from the player's resources
  148.                 if (TempResourceArray[y].Resource_Name == Cost[x].Resource_Name)
  149.                 {
  150.                         TempResourceArray[y].Resource_Balance -= Cost[x].Resource_Cost;
  151.  
  152.                         // If the player now has a negative value for a particular resource set 'HasSufficientFunds' to false
  153.                         if (TempResourceArray[y].Resource_Balance <= 0)
  154.                         {
  155.                             HasSufficientFunds = false;
  156.                         }
  157.                         break;
  158.                 }
  159.                 // 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
  160.                 else if (y == (TempResourceArray.Num() -1))
  161.                 {
  162.                         HasSufficientFunds = false;
  163.                         ResourceNameError = true;
  164.                         ImproperName = Cost[x].Resource_Name;
  165.                 }
  166.             }
  167.         }
  168.  
  169.         // If we have sufficient funds and there were no naming errors proceed with confirmation of the upgrade/purchase
  170.         if (HasSufficientFunds == true && ResourceNameError == false)
  171.         {
  172.             // This ensures a successful call of the 'Spend Resource' function has occured, otherwise calling 'Utilize Resources' will not be appropriate
  173.             SpendResourcesCalled = true;
  174.             // Fires the blueprint implemented event to allow for confirmation prior to deducting resources
  175.             Confirm_Purchase();
  176.         }
  177.         // 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
  178.         else if (HasSufficientFunds == false && ResourceNameError == false)
  179.         {
  180.             // This ensures a successful call of the 'Spend Resource' function has occured, otherwise calling 'Utilize Resources' will not be appropriate
  181.             SpendResourcesCalled = true;
  182.             // Call to calculate the total resource deficit and the amount of premium currency required to cover it
  183.             Calculate_Premium_Coverage(Cost);
  184.             // Fires the blueprint implemented event to allow for the option to spend a premium currency (similar to 'Confirm Purchase', just an extra event)
  185.             Insufficient_Funds();
  186.         }
  187.         // If we had a naming do not allow further progress ('SpendResourcesCalled' will remain false) and throw an error identifying the culprit resource
  188.         else
  189.         {
  190.             ErrorMessage =  ImproperName + " did not match any resource name listed in the Available Resources Array, resource utilization declined!";
  191.         }
  192.     }
  193.     // If no members have been added to either the Available Resource or the Cost array, throw an error and prevent further progress
  194.     else
  195.     {
  196.         ErrorMessage = "Available Resources and/or Cost Arrays Have No Members or There are more members in the Cost array than Avaiable Resources";
  197.     }
  198. }
  199.  
  200. // Function that calculates the premium currency coverage
  201. void UMasterBank::Calculate_Premium_Coverage(TArray<FCost_Data_Master>Cost)
  202. {
  203.     // Start each call of this function assuming 0 premium currency is necessary
  204.     PremiumCurrencyTotal = 0;
  205.  
  206.     // Loop through the player's resource array and identify all the non-premium resources with a negative balance
  207.     for (int x = 0; x <TempResourceArray.Num(); ++x)
  208.     {
  209.         if (TempResourceArray[x].Resource_Balance < 0 && TempResourceArray[x].Is_Premium == false)
  210.         {
  211.             // 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)
  212.             PremiumCurrencyTotal += FMath::DivideAndRoundUp(FMath::Abs(TempResourceArray[x].Resource_Balance), TempResourceArray[x].Conversion_Ratio);
  213.             TempResourceArray[x].Resource_Balance = 0;
  214.         }
  215.     }
  216.     // For troubleshooting purposes the error message will display the total amount of premium currency necessary to cover the deficit after this function call
  217.     ErrorMessage = "The total amount of premium currency needed is " + FString::FromInt(PremiumCurrencyTotal);
  218. }
  219.  
  220. // This function will actually deduct resources from the player's bank
  221. void UMasterBank::Utilize_Resources()
  222. {
  223.     // Double check and make sure we have a successful call to 'Spend Resources' prior to using this function
  224.     if (SpendResourcesCalled == true)
  225.     {
  226.         // If the player had sufficient resources outright then we simply set the player's resource data pointer to the temporary array values
  227.         if (HasSufficientFunds == true)
  228.         {
  229.             *StoredArrayData = TempResourceArray;
  230.         }
  231.         // If the player did not have sufficient resources check and see if they have enough premium currency
  232.         else if (HasSufficientFunds == false)
  233.         {
  234.             // Loop through the player's resource array until the premium currency index is found
  235.             for (int x = 0; x < TempResourceArray.Num(); ++x)
  236.                 // If the player has enough of the premium currency deduct the total and set the array pointer to the temporary array values
  237.                 if (TempResourceArray[x].Is_Premium == true && ((TempResourceArray[x].Resource_Balance - PremiumCurrencyTotal) >= 0))
  238.                 {
  239.                     TempResourceArray[x].Resource_Balance -= PremiumCurrencyTotal;
  240.                     *StoredArrayData = TempResourceArray;
  241.                     ErrorMessage = "Premium Resource Spent";
  242.                     break;
  243.                 }
  244.             // If the player did not have enough premium currency fire the 'Insufficient Funds' event again and return an error indicating this occurrence
  245.                 else if (TempResourceArray[x].Is_Premium == true && ((TempResourceArray[x].Resource_Balance - PremiumCurrencyTotal) < 0))
  246.                 {
  247.                     Insufficient_Funds();
  248.                     ErrorMessage = "Premium Resource Insufficient to Cover All Deficits";
  249.                     break;
  250.                 }
  251.                 else;
  252.         }      
  253.        
  254.         // Once this has completed set the 'SpendResourcesCalled' back to false to ensure proper calling of the 'SpendResources' function before using this again
  255.         SpendResourcesCalled = false;
  256.     }
  257.     // If the user did not first call 'Spend Resources' we will alert them with this error message
  258.     else
  259.     {
  260.         ErrorMessage = "Must call the function 'Spend Resources' prior to calling 'Utilize_Resources'";
  261.     }
  262. }
Advertisement
Add Comment
Please, Sign In to add comment