Add helper function for removing an item from the player's inventory via item name. Add accessory refining check and refine functions. Release Build 10487.

mac-build
sigonasr2 4 months ago
parent 21dee760dd
commit ee4d250370
  1. 21
      Adventures in Lestoria Tests/ItemTests.cpp
  2. 35
      Adventures in Lestoria/Item.cpp
  3. 12
      Adventures in Lestoria/Item.h
  4. 2
      Adventures in Lestoria/Version.h
  5. 11
      Adventures in Lestoria/assets/config/items/Accessories.txt
  6. BIN
      x64/Release/Adventures in Lestoria.exe

@ -194,6 +194,7 @@ namespace ItemTests
Assert::AreEqual(1U,Inventory::GetItemCount(ITEM_DATA["Ring of the Slime King"].FragmentName()),L"Disassembly has given us a Slime King Ring Fragment.");
}
TEST_METHOD(DisassembleNonAccessoryTest){
Inventory::AddItem("Ring of the Slime King"s);
try{
Inventory::Disassemble(Inventory::AddItem("Test Armor"s));
Assert::Fail(L"Disassembling Test Armor succeeded! This should NOT be allowed!");
@ -207,5 +208,25 @@ namespace ItemTests
Assert::Fail(L"Disassembling a Health Potion succeeded! This should NOT be allowed!");
}catch(std::runtime_error&e){}
}
TEST_METHOD(RefiningTest){
util::random();
util::random();
std::weak_ptr<Item>slimeKingRing{Inventory::AddItem("Ring of the Slime King"s)};
Assert::IsFalse(slimeKingRing.lock()->CanBeRefined(),L"Ring of the Slime King should not be allowed to be refined since we have no fragments.");
std::weak_ptr<Item>testArmor{Inventory::AddItem("Test Armor"s)};
Assert::IsFalse(testArmor.lock()->CanBeRefined(),L"Test Armor should not be allowed to be refined since it's not an accessory.");
Inventory::AddItem(slimeKingRing.lock()->FragmentName(),50U);
Assert::IsTrue(slimeKingRing.lock()->CanBeRefined(),L"Ring of the Slime King should now be allowed to be refined since we meet all requirements.");
player->SetMoney(0);
Assert::IsFalse(slimeKingRing.lock()->CanBeRefined(),L"Ring of the Slime King should not be allowed to be refined since we do not have enough money.");
player->SetMoney(10000);
while(slimeKingRing.lock()->CanBeRefined()){
RefineResult result{slimeKingRing.lock()->Refine()};
LOG(std::format("Enhanced {} by {}",result.first.Name(),result.second));
}
for(const auto&[attr,val]:slimeKingRing.lock()->RandomStats()){
Assert::AreEqual(ITEM_DATA[slimeKingRing.lock()->ActualName()].GetMaxStats().A_Read(attr),val,L"The current stats should be equal to the maximum stats when refinement is done.");
}
}
};
}

@ -620,6 +620,13 @@ bool Inventory::RemoveItem(std::weak_ptr<Item>itemRef,ITCategory inventory,uint3
}
}
bool Inventory::RemoveItem(IT it,uint32_t amt){
if(GetItemCount(it)==0)return false;
std::weak_ptr<Item>foundItem{GetItem(it)[0]};
ITCategory cat = foundItem.lock()->Category();
return RemoveItem(foundItem, cat, amt);
}
//Returns true if the item has been consumed completely and there are 0 remaining of that type in our inventory.
bool Inventory::RemoveItem(std::weak_ptr<Item>itemRef,uint32_t amt){
ITCategory cat = itemRef.lock()->Category();
@ -1402,4 +1409,32 @@ const std::string&Item::FragmentName()const{
const std::string&ItemInfo::FragmentName()const{
if(!fragmentName.has_value())ERR(std::format("WARNING! Item {} does not break down into a fragment (fragment name not set)!",Name()));
return fragmentName.value();
}
const bool Item::CanBeRefined()const{
if(!IsAccessory()||Inventory::GetItemCount(FragmentName())<"Fragment Refine Cost"_i[0]||game->GetPlayer()->GetMoney()<"Fragment Refine Cost"_i[1])return false;
for(const auto&[attr,val]:randomizedStats){
float maxVal{ITEM_DATA[ActualName()].GetMaxStats().A_Read(attr)};
if(val!=maxVal)return true;
}
return false; //Maxed out, so cannot be refined.
}
RefineResult Item::Refine(){
if(!CanBeRefined())ERR("WARNING! Trying to refine an item that cannot be refined! Make sure you are checking with CanBeRefined() before calling this function!");
Inventory::RemoveItem(FragmentName(),"Fragment Refine Cost"_i[0]);
game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-"Fragment Refine Cost"_i[1]);
std::vector<ItemAttribute>statsAvailableForRefining;
for(const auto&[attr,val]:randomizedStats){
float maxVal{ITEM_DATA[ActualName()].GetMaxStats().A_Read(attr)};
if(val!=maxVal)statsAvailableForRefining.push_back(attr);
}
ItemAttribute&chosenAttr{statsAvailableForRefining[util::random()%statsAvailableForRefining.size()]};
const float pctIncreaseAmount{"Refine Stat Increase Amount"_F/100.f};
const float maxStat{ITEM_DATA[ActualName()].GetMaxStats().A_Read(chosenAttr)};
const int increaseAmt{int(ceil(maxStat*pctIncreaseAmount))};
const float oldAmt{randomizedStats.A_Read(chosenAttr)};
randomizedStats.A(chosenAttr)=std::min(maxStat,oldAmt+increaseAmt);
const float newAmt{randomizedStats.A_Read(chosenAttr)};
return RefineResult{chosenAttr,newAmt-oldAmt};
}

@ -168,6 +168,9 @@ namespace PlayerTests{
class PlayerTest;
};
using IncreaseAmount=int;
using RefineResult=std::pair<ItemAttribute,IncreaseAmount>;
class Item{
friend class Inventory;
friend class AiL;
@ -238,9 +241,12 @@ public:
static bool IsBlank(std::weak_ptr<Item>item);
const bool IsLocked()const;
const std::string&FragmentName()const;
const bool CanBeRefined()const; //An item can be refined if the item has less than max stats and the player has enough fragments in their inventory.
//Assumes an item can be refined. CHECK WITH CanBeRefined() First!!!
//Refines a random stat by the parameters defined in the Accessories.txt configuration file. Also takes away the costs required to refine the item.
RefineResult Refine();
void Lock();
void Unlock();
void Disassemble();
friend const bool operator==(std::shared_ptr<Item>lhs,std::shared_ptr<Item>rhs){return lhs->it==rhs->it&&lhs->randomizedStats==rhs->randomizedStats;};
friend const bool operator==(std::shared_ptr<Item>lhs,const IT&rhs){return lhs->ActualName()==const_cast<IT&>(rhs);};
friend const bool operator==(std::weak_ptr<Item>lhs,std::weak_ptr<Item>rhs){return !lhs.expired()&&!rhs.expired()&&lhs.lock()->it==rhs.lock()->it&&lhs.lock()->randomizedStats==rhs.lock()->randomizedStats;};
@ -263,8 +269,12 @@ public:
static std::vector<std::weak_ptr<Item>>GetItem(IT it);
//Auto-executes its use function and removes the amt specified from the inventory. Multiple amounts will cause the item to execute its useFunc multiple times.
static bool UseItem(IT it,uint32_t amt=1);
//Returns true if the item has been consumed completely and there are 0 remaining of that type in our inventory.
static bool RemoveItem(std::weak_ptr<Item>itemRef,ITCategory inventory,uint32_t amt = 1);
//Returns true if the item has been consumed completely and there are 0 remaining of that type in our inventory.
static bool RemoveItem(std::weak_ptr<Item>itemRef,uint32_t amt=1);
//Returns true if the item has been consumed completely and there are 0 remaining of that type in our inventory.
static bool RemoveItem(IT it,uint32_t amt=1);
static const std::vector<std::shared_ptr<Item>>&get(ITCategory itemCategory);
static const std::weak_ptr<Item>GetInventorySlot(ITCategory itemCategory,size_t slot);
static void Clear(ITCategory itemCategory);

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 3
#define VERSION_BUILD 10482
#define VERSION_BUILD 10487
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -1,10 +1,13 @@
Fragment Description = "A small piece of concentrated material from broken down jewelry."
# Number of fragments earned when breaking down an accessory.
Fragment Disassemble Gain Amount = 1
# Number of fragments required to Refine an accessory.
Fragment Refine Cost = 1
# Number of fragments required to Enchant an accessory.
Fragment Enchant Cost = 3
# Number of fragments and gold required to Refine an accessory.
Fragment Refine Cost = 1, 20g
# Number of fragments and gold required to Enchant an accessory.
Fragment Enchant Cost = 3, 35g
# How much to increase refined stats by with each refinement. (Ex. if the value is 20%, it takes 5 refinements at most from an item with the lowest possible stat to the max stat with 20% increments.)
Refine Stat Increase Amount = 20%
Equipment
{

Loading…
Cancel
Save