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.
This commit is contained in:
parent
56f731db36
commit
eae5c2915d
@ -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.");
|
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){
|
TEST_METHOD(DisassembleNonAccessoryTest){
|
||||||
|
Inventory::AddItem("Ring of the Slime King"s);
|
||||||
try{
|
try{
|
||||||
Inventory::Disassemble(Inventory::AddItem("Test Armor"s));
|
Inventory::Disassemble(Inventory::AddItem("Test Armor"s));
|
||||||
Assert::Fail(L"Disassembling Test Armor succeeded! This should NOT be allowed!");
|
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!");
|
Assert::Fail(L"Disassembling a Health Potion succeeded! This should NOT be allowed!");
|
||||||
}catch(std::runtime_error&e){}
|
}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.
|
//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){
|
bool Inventory::RemoveItem(std::weak_ptr<Item>itemRef,uint32_t amt){
|
||||||
ITCategory cat = itemRef.lock()->Category();
|
ITCategory cat = itemRef.lock()->Category();
|
||||||
@ -1403,3 +1410,31 @@ 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()));
|
if(!fragmentName.has_value())ERR(std::format("WARNING! Item {} does not break down into a fragment (fragment name not set)!",Name()));
|
||||||
return fragmentName.value();
|
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;
|
class PlayerTest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using IncreaseAmount=int;
|
||||||
|
using RefineResult=std::pair<ItemAttribute,IncreaseAmount>;
|
||||||
|
|
||||||
class Item{
|
class Item{
|
||||||
friend class Inventory;
|
friend class Inventory;
|
||||||
friend class AiL;
|
friend class AiL;
|
||||||
@ -238,9 +241,12 @@ public:
|
|||||||
static bool IsBlank(std::weak_ptr<Item>item);
|
static bool IsBlank(std::weak_ptr<Item>item);
|
||||||
const bool IsLocked()const;
|
const bool IsLocked()const;
|
||||||
const std::string&FragmentName()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 Lock();
|
||||||
void Unlock();
|
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,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::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;};
|
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);
|
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.
|
//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);
|
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);
|
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);
|
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::vector<std::shared_ptr<Item>>&get(ITCategory itemCategory);
|
||||||
static const std::weak_ptr<Item>GetInventorySlot(ITCategory itemCategory,size_t slot);
|
static const std::weak_ptr<Item>GetInventorySlot(ITCategory itemCategory,size_t slot);
|
||||||
static void Clear(ITCategory itemCategory);
|
static void Clear(ITCategory itemCategory);
|
||||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
|||||||
#define VERSION_MAJOR 1
|
#define VERSION_MAJOR 1
|
||||||
#define VERSION_MINOR 2
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_PATCH 3
|
#define VERSION_PATCH 3
|
||||||
#define VERSION_BUILD 10482
|
#define VERSION_BUILD 10487
|
||||||
|
|
||||||
#define stringify(a) stringify_(a)
|
#define stringify(a) stringify_(a)
|
||||||
#define stringify_(a) #a
|
#define stringify_(a) #a
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
Fragment Description = "A small piece of concentrated material from broken down jewelry."
|
Fragment Description = "A small piece of concentrated material from broken down jewelry."
|
||||||
# Number of fragments earned when breaking down an accessory.
|
# Number of fragments earned when breaking down an accessory.
|
||||||
Fragment Disassemble Gain Amount = 1
|
Fragment Disassemble Gain Amount = 1
|
||||||
# Number of fragments required to Refine an accessory.
|
# Number of fragments and gold required to Refine an accessory.
|
||||||
Fragment Refine Cost = 1
|
Fragment Refine Cost = 1, 20g
|
||||||
# Number of fragments required to Enchant an accessory.
|
# Number of fragments and gold required to Enchant an accessory.
|
||||||
Fragment Enchant Cost = 3
|
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
|
Equipment
|
||||||
{
|
{
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user