diff --git a/Adventures in Lestoria Tests/EnchantTests.cpp b/Adventures in Lestoria Tests/EnchantTests.cpp index 4e4bebed..db98251e 100644 --- a/Adventures in Lestoria Tests/EnchantTests.cpp +++ b/Adventures in Lestoria Tests/EnchantTests.cpp @@ -118,13 +118,13 @@ namespace EnchantTests std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Aura of the Beast")}; std::unordered_mapstatDistribution; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Health Boost"); + nullRing.lock()->_EnchantItem("Health Boost"); statDistribution[player->GetMaxHealth()]++; } Assert::AreEqual(size_t(3),statDistribution.size(),L"There should be three entries generated. If not, then the RNG picking is likely not working!"); std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Aura of the Beast",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Health Boost"); + nullRing2.lock()->_EnchantItem("Health Boost"); Test::InRange(player->GetMaxHealth(),{106,110},L"Max Health not in expected range with two rings equipped."); } } @@ -133,12 +133,12 @@ namespace EnchantTests Assert::AreEqual(100,player->GetAttack(),L"Player starts with 100 attack."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Attack Boost")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Attack Boost"); + nullRing.lock()->_EnchantItem("Attack Boost"); Test::InRange(player->GetAttack(),{103,105},L"Attack not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Attack Boost",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Attack Boost"); + nullRing2.lock()->_EnchantItem("Attack Boost"); Test::InRange(player->GetAttack(),{106,110},L"Attack not in expected range with two rings equipped."); } } @@ -146,12 +146,12 @@ namespace EnchantTests Assert::AreEqual(100.0_Pct,player->GetMoveSpdMult(),L"Player starts with 100% Movespd."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Movement Boost")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Movement Boost"); + nullRing.lock()->_EnchantItem("Movement Boost"); Test::InRange(player->GetMoveSpdMult(),{103.0_Pct,105.0_Pct},L"Move Speed not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Movement Boost",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Movement Boost"); + nullRing2.lock()->_EnchantItem("Movement Boost"); Test::InRange(player->GetMoveSpdMult(),{106.0_Pct,110.0_Pct},L"Move Speed not in expected range with two rings equipped."); } } @@ -159,12 +159,12 @@ namespace EnchantTests Assert::AreEqual(0.0_Pct,player->GetCooldownReductionPct(),L"Player starts with 0% CDR."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Ability Haste")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Ability Haste"); + nullRing.lock()->_EnchantItem("Ability Haste"); Test::InRange(player->GetCooldownReductionPct(),{3.0_Pct,5.0_Pct},L"CDR not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Ability Haste",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Ability Haste"); + nullRing2.lock()->_EnchantItem("Ability Haste"); Test::InRange(player->GetCooldownReductionPct(),{6.0_Pct,10.0_Pct},L"CDR not in expected range with two rings."); } } @@ -172,12 +172,12 @@ namespace EnchantTests Assert::AreEqual(0.0_Pct,player->GetCritRatePct(),L"Player starts with 0% Crit Rate."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Crit Rate")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Crit Rate"); + nullRing.lock()->_EnchantItem("Crit Rate"); Test::InRange(player->GetCritRatePct(),{3.0_Pct,5.0_Pct},L"Crit Rate not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Crit Rate",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Crit Rate"); + nullRing2.lock()->_EnchantItem("Crit Rate"); Test::InRange(player->GetCritRatePct(),{6.0_Pct,10.0_Pct},L"Crit Rate not in expected range with two rings."); } } @@ -185,12 +185,12 @@ namespace EnchantTests Assert::AreEqual(50.0_Pct,player->GetCritDmgPct(),L"Player starts with 50% Crit Damage."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Crit Damage")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Crit Damage"); + nullRing.lock()->_EnchantItem("Crit Damage"); Test::InRange(player->GetCritDmgPct(),{57.0_Pct,60.0_Pct},L"Crit Damage not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Crit Damage",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Crit Damage"); + nullRing2.lock()->_EnchantItem("Crit Damage"); Test::InRange(player->GetCritDmgPct(),{64.0_Pct,70.0_Pct},L"Crit Damage not in expected range with two rings."); } } @@ -198,12 +198,12 @@ namespace EnchantTests Assert::AreEqual(0.0_Pct,player->GetDamageReductionFromBuffs(),L"Player starts with 0% Damage Reduction."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Stoneskin")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Stoneskin"); + nullRing.lock()->_EnchantItem("Stoneskin"); Test::InRange(player->GetDamageReductionFromBuffs(),{3.0_Pct,5.0_Pct},L"Damage Reduction not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Stoneskin",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Stoneskin"); + nullRing2.lock()->_EnchantItem("Stoneskin"); Test::InRange(player->GetDamageReductionFromBuffs(),{6.0_Pct,10.0_Pct},L"Damage Reduction not in expected range with two rings."); } } @@ -211,12 +211,12 @@ namespace EnchantTests Assert::AreEqual(100,player->GetMaxMana(),L"Player starts with 100 mana."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Mana Pool")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Mana Pool"); + nullRing.lock()->_EnchantItem("Mana Pool"); Test::InRange(player->GetMaxMana(),{107,112},L"Mana Pool not in expected range."); } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Mana Pool",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Mana Pool"); + nullRing2.lock()->_EnchantItem("Mana Pool"); Test::InRange(player->GetMaxMana(),{114,124},L"Mana Pool not in expected range with two rings."); } } @@ -227,7 +227,7 @@ namespace EnchantTests Assert::AreEqual(0.0_Pct,player->GetHP6RecoveryPct(),L"Player starts with 0% HP/6 recovery."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Magical Protection")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Magical Protection"); + nullRing.lock()->_EnchantItem("Magical Protection"); Test::InRange(player->GetMaxHealth(),{102,103},L"Max Health not in expected range."); Test::InRange(player->GetDamageReductionFromBuffs(),{2.0_Pct,3.0_Pct},L"Damage Reduction not in expected range."); Test::InRange(player->GetMoveSpdMult(),{102.0_Pct,103.0_Pct},L"Move Speed % not in expected range."); @@ -235,7 +235,7 @@ namespace EnchantTests } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Magical Protection",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Magical Protection"); + nullRing2.lock()->_EnchantItem("Magical Protection"); Test::InRange(player->GetMaxHealth(),{102,103},L"Max Health not in expected range with two rings."); Test::InRange(player->GetDamageReductionFromBuffs(),{2.0_Pct,3.0_Pct},L"Damage Reduction not in expected range with two rings."); Test::InRange(player->GetMoveSpdMult(),{102.0_Pct,103.0_Pct},L"Move Speed % not in expected range with two rings."); @@ -250,7 +250,7 @@ namespace EnchantTests Assert::AreEqual(50.0_Pct,player->GetCritDmgPct(),L"Player starts with 50% crit rate."); std::weak_ptrnullRing{Game::GiveAndEquipEnchantedRing("Aura of the Beast")}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing.lock()->EnchantItem("Aura of the Beast"); + nullRing.lock()->_EnchantItem("Aura of the Beast"); Test::InRange(player->GetAttack(),{102,103},L"Attack not in expected range."); Test::InRange(player->GetCritRatePct(),{2.0_Pct,3.0_Pct},L"Crit Rate not in expected range."); Test::InRange(player->GetCooldownReductionPct(),{2.0_Pct,3.0_Pct},L"Cooldown Reduction % not in expected range."); @@ -258,7 +258,7 @@ namespace EnchantTests } std::weak_ptrnullRing2{Game::GiveAndEquipEnchantedRing("Aura of the Beast",EquipSlot::RING2)}; for(int i:std::ranges::iota_view(0,1000)){ - nullRing2.lock()->EnchantItem("Aura of the Beast"); + nullRing2.lock()->_EnchantItem("Aura of the Beast"); Test::InRange(player->GetAttack(),{102,103},L"Attack not in expected range with two rings."); Test::InRange(player->GetCritRatePct(),{2.0_Pct,3.0_Pct},L"Crit Rate not in expected range with two rings."); Test::InRange(player->GetCooldownReductionPct(),{2.0_Pct,3.0_Pct},L"Cooldown Reduction % not in expected range with two rings."); diff --git a/Adventures in Lestoria Tests/GameHelper.h b/Adventures in Lestoria Tests/GameHelper.h index 3d4e5d87..4997c9a3 100644 --- a/Adventures in Lestoria Tests/GameHelper.h +++ b/Adventures in Lestoria Tests/GameHelper.h @@ -66,7 +66,7 @@ namespace Game{ inline std::weak_ptrGiveAndEquipEnchantedRing(const std::string_view enchantName,const EquipSlot slot=EquipSlot::RING1){ std::weak_ptrnullRing{Inventory::AddItem("Null Ring"s)}; Inventory::EquipItem(nullRing,slot); - nullRing.lock()->EnchantItem(enchantName); + nullRing.lock()->_EnchantItem(enchantName); return nullRing; } } diff --git a/Adventures in Lestoria Tests/ItemTests.cpp b/Adventures in Lestoria Tests/ItemTests.cpp index 8e225bf2..f841032b 100644 --- a/Adventures in Lestoria Tests/ItemTests.cpp +++ b/Adventures in Lestoria Tests/ItemTests.cpp @@ -251,14 +251,14 @@ namespace ItemTests std::weak_ptrslimeKingRing{Inventory::AddItem("Ring of the Slime King"s)}; Assert::IsFalse(slimeKingRing.lock()->HasEnchant()); for(int i:std::ranges::iota_view(0,1000)){ - slimeKingRing.lock()->EnchantItem(ItemEnchant::RollRandomEnchant()); + slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant()); Assert::IsTrue(slimeKingRing.lock()->HasEnchant()); if(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().has_value())Assert::AreEqual(int(player->GetClass()),int(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().value())); //Validate enchant is only for this class if it's a class-based ability. } testGame->ChangePlayerClass(WIZARD); player=testGame->GetPlayer(); //The player pointer has been reassigned... for(int i:std::ranges::iota_view(0,1000)){ - slimeKingRing.lock()->EnchantItem(ItemEnchant::RollRandomEnchant()); + slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant()); Assert::IsTrue(slimeKingRing.lock()->HasEnchant()); if(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().has_value())Assert::AreEqual(int(player->GetClass()),int(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().value())); //Validate enchant is only for this class if it's a class-based ability. } @@ -277,6 +277,8 @@ namespace ItemTests std::weak_ptrextraRing{Inventory::AddItem("Ring of the Slime King"s)}; std::unordered_mapenchantCounts; for(int i:std::ranges::iota_view(0,1000)){ + Inventory::AddItem(extraRing.lock()->FragmentName(),"Fragment Enchant Cost"_i[0]); + player->AddMoney("Fragment Enchant Cost"_i[1]); ItemEnchantInfo resultEnchant{extraRing.lock()->ApplyRandomEnchant()}; if(resultEnchant.GetClass().has_value())Assert::AreEqual(int(resultEnchant.GetClass().value()),int(player->GetClass()),L"Player's class matches the class of the enchant."); enchantCounts[resultEnchant.Category()]++; @@ -296,5 +298,23 @@ namespace ItemTests Assert::AreEqual("Item Enchants.Class Enchants.Enchant Display Color"_Pixel.n,ItemEnchantInfo::GetEnchant("Quickdraw").DisplayCol().n,L"Expecting a class enchant to have the class enchant pixel display color."); Assert::AreEqual("Item Enchants.Unique Enchants.Enchant Display Color"_Pixel.n,ItemEnchantInfo::GetEnchant("Magical Protection").DisplayCol().n,L"Expecting a unique enchant to have the unique enchant pixel display color."); } + TEST_METHOD(CanBeEnchantedTest){ + std::weak_ptrextraRing{Inventory::AddItem("Ring of the Slime King"s)}; + std::weak_ptrtestArmor{Inventory::AddItem("Test Armor"s)}; + Assert::AreEqual(false,extraRing.lock()->CanBeEnchanted(),L"We don't have the money nor required fragments to enchant this item."); + Assert::AreEqual(false,testArmor.lock()->CanBeEnchanted(),L"We can't enchant armor."); + player->SetMoney(2000U); + Assert::AreEqual(false,extraRing.lock()->CanBeEnchanted(),L"We don't have the required fragments to enchant this item."); + player->SetMoney(0U); + Inventory::AddItem(extraRing.lock()->FragmentName(),"Fragment Enchant Cost"_i[0]); + Assert::AreEqual(false,extraRing.lock()->CanBeEnchanted(),L"We don't have the required money to enchant this item."); + player->SetMoney(2000U); + Assert::AreEqual(true,extraRing.lock()->CanBeEnchanted(),L"We don't have the required money to enchant this item."); + extraRing.lock()->ApplyRandomEnchant(); + Assert::AreEqual(false,extraRing.lock()->CanBeEnchanted(),L"Ring cannot be enchanted again due to consumption of fragments."); + Inventory::AddItem(extraRing.lock()->FragmentName(),"Fragment Enchant Cost"_i[0]); + Assert::AreEqual(true,extraRing.lock()->CanBeEnchanted(),L"Ring can be enchanted again with the right amount of fragments."); + Assert::AreEqual(uint32_t(2000-"Fragment Enchant Cost"_i[1]),player->GetMoney(),util::wformat("Lost {} money due to enchanting ring.","Fragment Enchant Cost"_i[1]).c_str()); + } }; } diff --git a/Adventures in Lestoria Tests/PlayerTests.cpp b/Adventures in Lestoria Tests/PlayerTests.cpp index ba2afa6d..449b170d 100644 --- a/Adventures in Lestoria Tests/PlayerTests.cpp +++ b/Adventures in Lestoria Tests/PlayerTests.cpp @@ -629,17 +629,17 @@ namespace PlayerTests TEST_METHOD(HasEnchantCheck){ std::weak_ptrslimeKingRing{Inventory::AddItem("Ring of the Slime King"s)}; Inventory::EquipItem(slimeKingRing,EquipSlot::RING1); - slimeKingRing.lock()->EnchantItem("Emergency Recovery"); + slimeKingRing.lock()->_EnchantItem("Emergency Recovery"); Assert::IsTrue(player->HasEnchant("Emergency Recovery")); Inventory::EquipItem(slimeKingRing,EquipSlot::RING2); Assert::IsTrue(player->HasEnchant("Emergency Recovery")); Inventory::EquipItem(slimeKingRing,EquipSlot::RING1); - slimeKingRing.lock()->EnchantItem("Reaper of Souls"); + slimeKingRing.lock()->_EnchantItem("Reaper of Souls"); Assert::IsTrue(player->HasEnchant("Reaper of Souls")); Inventory::EquipItem(slimeKingRing,EquipSlot::RING2); Assert::IsTrue(player->HasEnchant("Reaper of Souls")); Inventory::EquipItem(slimeKingRing,EquipSlot::RING1); - slimeKingRing.lock()->EnchantItem("Attack Boost"); + slimeKingRing.lock()->_EnchantItem("Attack Boost"); Assert::IsTrue(player->HasEnchant("Attack Boost")); Inventory::EquipItem(slimeKingRing,EquipSlot::RING2); Assert::IsTrue(player->HasEnchant("Attack Boost")); @@ -658,18 +658,18 @@ namespace PlayerTests Inventory::EquipItem(leatherShoes,EquipSlot::SHOES); Inventory::EquipItem(woodenSword,EquipSlot::WEAPON); - leatherHelmet.lock()->EnchantItem("Wizard's Soul"); + leatherHelmet.lock()->_EnchantItem("Wizard's Soul"); Assert::IsTrue(player->HasEnchant("Wizard's Soul")); - leatherArmor.lock()->EnchantItem("Ability Haste"); + leatherArmor.lock()->_EnchantItem("Ability Haste"); Assert::IsTrue(player->HasEnchant("Ability Haste")); - leatherPants.lock()->EnchantItem("Improved Ground Slam"); + leatherPants.lock()->_EnchantItem("Improved Ground Slam"); Assert::IsTrue(player->HasEnchant("Improved Ground Slam")); - leatherGloves.lock()->EnchantItem("Battle Shout"); + leatherGloves.lock()->_EnchantItem("Battle Shout"); Assert::IsTrue(player->HasEnchant("Battle Shout")); - leatherShoes.lock()->EnchantItem("Attack Boost"); + leatherShoes.lock()->_EnchantItem("Attack Boost"); Inventory::UnequipItem(EquipSlot::RING2); Assert::IsTrue(player->HasEnchant("Attack Boost")); - woodenSword.lock()->EnchantItem("Mana Pool"); + woodenSword.lock()->_EnchantItem("Mana Pool"); Assert::IsTrue(player->HasEnchant("Mana Pool")); Inventory::UnequipItem(EquipSlot::HELMET); @@ -744,7 +744,7 @@ namespace PlayerTests player->GetAbility3().cooldown=player->GetAbility3().GetCooldownTime(); std::weak_ptrnullRing{Inventory::AddItem("Null Ring"s)}; Inventory::EquipItem(nullRing,EquipSlot::RING1); - nullRing.lock()->EnchantItem("Multi-Multishot"); + nullRing.lock()->_EnchantItem("Multi-Multishot"); testKey->bHeld=true; //Force the key to be held down for testing purposes. Assert::AreEqual(player->GetAbility3().GetCooldownTime(),oldCooldownTime-oldCooldownTime*"Multi-Multishot"_ENC["COOLDOWN REDUCTION PCT"]/100.f,L"Old cooldown time with multishot cooldown reduction pct matches."); testGame->SetElapsedTime(0.f); diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 55da4413..607b049e 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -436,7 +436,7 @@ bool AiL::OnConsoleCommand(const std::string& sCommand){ if(args[0]=="/accessory"){ if(args.size()<2)ConsoleOut()<<"Usage: /accessory [Enchant Name]"<accessory{Inventory::AddItem(args[1])}; - if(args.size()>=3)accessory.lock()->EnchantItem(args[2]); + if(args.size()>=3)accessory.lock()->_EnchantItem(args[2]); ConsoleOut()<<"Added "<OnLevelStart(); player->timers=oldTimers; player->shield=previousShield; + player->SetAbility4(Thief::GetOriginalAbility2()); } void AiL::InitializeClasses(){ diff --git a/Adventures in Lestoria/ArtificerEnchantConfirmWindow.cpp b/Adventures in Lestoria/ArtificerEnchantConfirmWindow.cpp index b7494a4a..c82f57e3 100644 --- a/Adventures in Lestoria/ArtificerEnchantConfirmWindow.cpp +++ b/Adventures in Lestoria/ArtificerEnchantConfirmWindow.cpp @@ -38,11 +38,41 @@ All rights reserved. #include "Menu.h" #include "AdventuresInLestoria.h" +#include "MenuLabel.h" +#include "MenuIconButton.h" INCLUDE_game void Menu::InitializeArtificerEnchantConfirmWindow(){ - Menu*artificerEnchantConfirmWindow=CreateMenu(ARTIFICER_ENCHANT_CONFIRM,CENTERED,vi2d{144,144}); + Menu*artificerEnchantConfirmWindow=CreateMenu(ARTIFICER_ENCHANT_CONFIRM,CENTERED,vi2d{240,144}); + + auto enchantSuccessLabel{artificerEnchantConfirmWindow->ADD("Enchant Success Label",MenuLabel)(geom2d::rect{{0.f,-14.f},vf2d{artificerEnchantConfirmWindow->size.x,12.f}},"Enchantment Success!",1.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END}; + + auto chooseResultLabel{artificerEnchantConfirmWindow->ADD("Choose Result Label",MenuLabel)(geom2d::rect{vf2d{0.f,0.f},vf2d{artificerEnchantConfirmWindow->size.x,12.f}},"Choose a Result",1.f,ComponentAttr::SHADOW)END}; + + const float oldLabelTextWidth{game->GetTextSize("OLD").x*2.f}; + auto oldLabel{artificerEnchantConfirmWindow->ADD("Old Item Label",MenuLabel)(geom2d::rect{{artificerEnchantConfirmWindow->size.x/4.f-oldLabelTextWidth/2-4.f,14.f},vf2d{oldLabelTextWidth+8.f,24.f}},"OLD",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END}; + + const float newLabelTextWidth{game->GetTextSize("NEW").x*2.f}; + auto newLabel{artificerEnchantConfirmWindow->ADD("New Item Label",MenuLabel)(geom2d::rect{{artificerEnchantConfirmWindow->size.x/2.f+artificerEnchantConfirmWindow->size.x/4.f-oldLabelTextWidth/2+2.f,14.f},vf2d{oldLabelTextWidth+8.f,24.f}},"NEW",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END}; + + auto oldIcon{artificerEnchantConfirmWindow->ADD("Old Item Icon",MenuIconButton)(geom2d::rect{{artificerEnchantConfirmWindow->size.x/4.f-12.f,42.f},{24,24}},nullptr,DO_NOTHING,IconButtonAttr::NOT_SELECTABLE)END}; + auto newIcon{artificerEnchantConfirmWindow->ADD("New Item Icon",MenuIconButton)(geom2d::rect{{artificerEnchantConfirmWindow->size.x/2.f+artificerEnchantConfirmWindow->size.x/4.f-12.f+4.f,42.f},{24,24}},nullptr,DO_NOTHING,IconButtonAttr::NOT_SELECTABLE)END}; + + auto oldItemDescription{artificerEnchantConfirmWindow->ADD("Old Item Description",MenuLabel)(geom2d::rect{{0.f,74.f},{artificerEnchantConfirmWindow->size.x/2.f-8.f,60.f}},"",0.5f,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END}; + auto newItemDescription{artificerEnchantConfirmWindow->ADD("New Item Description",MenuLabel)(geom2d::rect{{artificerEnchantConfirmWindow->size.x/2.f+8.f,74.f},{artificerEnchantConfirmWindow->size.x/2.f-8.f,60.f}},"",0.5f,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END}; + + const float takeOldTextWidth{float(game->GetTextSize("Take Old").x)*2.f}; + auto takeOldButton{artificerEnchantConfirmWindow->ADD("Take Old Button",MenuComponent)(geom2d::rect{{artificerEnchantConfirmWindow->size.x/4.f-takeOldTextWidth/2.f,138.f},{takeOldTextWidth,20.f}},"Take Old",[](MenuFuncData data){ + onClick: + return true; + },vf2d{2.f,2.f})END}; + + const float takeNewTextWidth{float(game->GetTextSize("Take New").x)*2.f}; + auto takeNewButton{artificerEnchantConfirmWindow->ADD("Take New Button",MenuComponent)(geom2d::rect{vf2d{artificerEnchantConfirmWindow->size.x/2.f+8.f+artificerEnchantConfirmWindow->size.x/4.f-takeNewTextWidth/2.f,138.f},{takeNewTextWidth,20.f}},"Take New",[](MenuFuncData data){ + onClick: + return true; + },vf2d{2.f,2.f})END}; artificerEnchantConfirmWindow->SetupKeyboardNavigation( [](MenuType type,Data&returnData){ //On Open @@ -51,7 +81,7 @@ void Menu::InitializeArtificerEnchantConfirmWindow(){ { //Button Key {game->KEY_SCROLL,{"Navigate",[](MenuType type){}}}, {game->KEY_BACK,{"Stay",[](MenuType type){ - Menu::CloseMenu(); + }}}, {game->KEY_CONFIRM,{"Select",[](MenuType type){}}}, } diff --git a/Adventures in Lestoria/ArtificerEnchantWindow.cpp b/Adventures in Lestoria/ArtificerEnchantWindow.cpp index 26a4d7e4..8bc3adff 100644 --- a/Adventures in Lestoria/ArtificerEnchantWindow.cpp +++ b/Adventures in Lestoria/ArtificerEnchantWindow.cpp @@ -43,6 +43,7 @@ All rights reserved. #include "MenuLabel.h" #include "MenuDecal.h" #include "PlayerMoneyLabel.h" +#include "SoundEffect.h" INCLUDE_game @@ -59,18 +60,43 @@ void Menu::InitializeArtificerEnchantWindow(){ auto accessoryDescription{artificerEnchantWindow->ADD("Item Description",MenuLabel)(geom2d::rect{{artificerEnchantWindow->size.x/2+56.f,16.f},{artificerEnchantWindow->size.x/2-40.f,72.f}},"",0.5f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END}; - const auto ResetRefineDisplay{[artificerEnchantWindow](){ + const auto ResetEnchantDisplay{[artificerEnchantWindow](){ MenuType menuType{artificerEnchantWindow->GetType()}; Component(menuType,"Item Icon")->SetItem(Item::BLANK); + Component(menuType,"Enchant Container")->Disable(); + Component(menuType,"Enchant List Header")->Disable(); + Component(menuType,"Enchant Cost Label")->Disable(); + Component(menuType,"Fragment Cost Icon")->Disable(); + Component(menuType,"Fragment Label")->Disable(); + Component(menuType,"Fragment Money Cost Label")->Disable(); + Component(menuType,"Fragment Enchant Button")->Disable(); }}; - const auto EnableRefineDisplay{[artificerEnchantWindow](){ + const auto EnableEnchantDisplay{[artificerEnchantWindow](){ MenuType menuType{artificerEnchantWindow->GetType()}; const std::weak_ptr&selectedItem{Component(menuType,"Item Icon")->GetItem()}; std::vectoravailableEnchants{ItemEnchant::GetAvailableEnchants()}; + std::sort(availableEnchants.begin(),availableEnchants.end(),[](const ItemEnchantInfo&enchant1,const ItemEnchantInfo&enchant2){ + return enchant1.Category()!=enchant2.Category()?int(enchant1.Category())(menuType,"Enchant Container")->Enable(); Component(menuType,"Enchant List")->SetLabel(enchantList); + Component(menuType,"Enchant List Header")->Enable(); + Component(menuType,"Enchant Cost Label")->Enable(); + Component(menuType,"Fragment Cost Icon")->Enable(); + Component(menuType,"Fragment Cost Icon")->SetImage(GFX.at(selectedItem.lock()->FragmentIcon().value())); + Component(menuType,"Fragment Label")->Enable(); + Component(menuType,"Fragment Money Cost Label")->Enable(); + Component(menuType,"Fragment Enchant Button")->Enable(); + Component(menuType,"Fragment Enchant Button")->SetGrayedOut(!selectedItem.lock()->CanBeEnchanted()); + + const std::string_view fragmentName{selectedItem.lock()->FragmentName()}; + const Pixel fragmentItemDisplayCol{Inventory::GetItemCount(fragmentName)>="Fragment Enchant Cost"_i[0]?WHITE:RED}; + const Pixel moneyCostDisplayCol{game->GetPlayer()->GetMoney()>="Fragment Enchant Cost"_i[1]?WHITE:RED}; + Component(menuType,"Fragment Label")->SetLabel(std::format("{}{} x{} ({})",fragmentItemDisplayCol.toHTMLColorCode(),fragmentName,"Fragment Enchant Cost"_i[0],Inventory::GetItemCount(fragmentName))); + Component(menuType,"Fragment Money Cost Label")->SetLabel(std::format("{}{} gold",moneyCostDisplayCol.toHTMLColorCode(),"Fragment Enchant Cost"_i[1])); }}; auto inventoryDisplay{artificerEnchantWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect{{0.f,28.f},{artificerEnchantWindow->size.x/2-4.f,artificerEnchantWindow->size.y-44}},"","",[](MenuFuncData data){ @@ -78,18 +104,18 @@ void Menu::InitializeArtificerEnchantWindow(){ RowItemDisplay&item{*DYNAMIC_POINTER_CAST(data.component)}; DYNAMIC_POINTER_CAST(data.parentComponent.lock())->SelectChild(DYNAMIC_POINTER_CAST(data.component)); return true; - },[EnableRefineDisplay](MenuFuncData data){OnHover: + },[EnableEnchantDisplay](MenuFuncData data){OnHover: RowItemDisplay&item{*DYNAMIC_POINTER_CAST(data.component)}; Component(data.menu.type,"Item Icon")->SetItem(item.GetItem()); - EnableRefineDisplay(); + EnableEnchantDisplay(); return true; - },[ResetRefineDisplay,EnableRefineDisplay](MenuFuncData data){OnMouseOut: - ResetRefineDisplay(); + },[ResetEnchantDisplay,EnableEnchantDisplay](MenuFuncData data){OnMouseOut: + ResetEnchantDisplay(); auto childComponent{DYNAMIC_POINTER_CAST(data.parentComponent.lock())->GetSelectedChild()}; if(childComponent){ RowItemDisplay&item{childComponent.value().get()}; Component(data.menu.type,"Item Icon")->SetItem(item.GetItem()); - EnableRefineDisplay(); + EnableEnchantDisplay(); } return true; }, @@ -107,9 +133,15 @@ void Menu::InitializeArtificerEnchantWindow(){ auto fragmentDisplayLabel{artificerEnchantWindow->ADD("Fragment Label",MenuLabel)(geom2d::rect{{artificerEnchantWindow->size.x/2+80.f,152.f},{artificerEnchantWindow->size.x/2-60.f,12.f}},"",1.f,ComponentAttr::SHADOW|ComponentAttr::FIT_TO_LABEL|ComponentAttr::LEFT_ALIGN)END}; auto fragmentMoneyCostLabel{artificerEnchantWindow->ADD("Fragment Money Cost Label",MenuLabel)(geom2d::rect{{artificerEnchantWindow->size.x/2+80.f,164.f},{artificerEnchantWindow->size.x/2-60.f,12.f}},"",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END}; - auto fragmentEnchantButton{artificerEnchantWindow->ADD("Fragment Enchant Button",MenuComponent)(geom2d::rect{{artificerEnchantWindow->size.x/2+96.f,180.f},{artificerEnchantWindow->size.x/2-80.f,12.f}},"Enchant",[EnableRefineDisplay](MenuFuncData data){ + auto fragmentEnchantButton{artificerEnchantWindow->ADD("Fragment Enchant Button",MenuComponent)(geom2d::rect{{artificerEnchantWindow->size.x/2+96.f,180.f},{artificerEnchantWindow->size.x/2-80.f,12.f}},"Enchant",[EnableEnchantDisplay](MenuFuncData data){ onClick: - EnableRefineDisplay(); //Refresh the current display contents. + EnableEnchantDisplay(); //Refresh the current display contents. + SoundEffect::PlaySFX("Enchant Item",SoundEffect::CENTERED); + std::weak_ptritem{Component(data.menu.type,"Item Icon")->GetItem()}; + std::optionalpreviousEnchant{item.lock()->GetEnchant()}; + item.lock()->ApplyRandomEnchant(); + const ItemEnchant&newEnchant{item.lock()->GetEnchant().value()}; + //TODO: Do stuff with this info. Menu::OpenMenu(ARTIFICER_ENCHANT_CONFIRM,true); return true; })END}; diff --git a/Adventures in Lestoria/ArtificerRefineWindow.cpp b/Adventures in Lestoria/ArtificerRefineWindow.cpp index 67841f5f..53c4fd7f 100644 --- a/Adventures in Lestoria/ArtificerRefineWindow.cpp +++ b/Adventures in Lestoria/ArtificerRefineWindow.cpp @@ -124,7 +124,7 @@ void Menu::InitializeArtificerRefineWindow(){ auto fragmentRefineButton{artificerRefineWindow->ADD("Fragment Refine Button",MenuComponent)(geom2d::rect{{artificerRefineWindow->size.x/2+96.f,180.f},{artificerRefineWindow->size.x/2-80.f,12.f}},"Refine",[EnableRefineDisplay](MenuFuncData data){ onClick: - SoundEffect::PlaySFX("Sprint",SoundEffect::CENTERED); + SoundEffect::PlaySFX("Refine Item",SoundEffect::CENTERED); std::weak_ptritem{Component(data.menu.type,"Item Icon")->GetItem()}; RefineResult result{item.lock()->Refine()}; Component(ARTIFICER_REFINE_RESULT,"Item Icon")->SetItem(item); diff --git a/Adventures in Lestoria/ArtificerWindow.cpp b/Adventures in Lestoria/ArtificerWindow.cpp index 10ff1e5e..aef63c45 100644 --- a/Adventures in Lestoria/ArtificerWindow.cpp +++ b/Adventures in Lestoria/ArtificerWindow.cpp @@ -62,6 +62,7 @@ void Menu::InitializeArtificerWindow(){ },vf2d{2.f,2.f},ButtonAttr::FIT_TO_LABEL)END; artificerWindow->ADD("Enchant Button",MenuComponent)(geom2d::rect{{0.f,60.f},{144.f,24.f}},"Enchant",[](MenuFuncData data){ Menu::OpenMenu(MenuType::ARTIFICER_ENCHANT); + Component(MenuType::ARTIFICER_ENCHANT,"Accessory List")->ClearSelectedChild(); return true; },vf2d{2.f,2.f},ButtonAttr::FIT_TO_LABEL)END; artificerWindow->ADD("Help Button",MenuComponent)(geom2d::rect{{0.f,88.f},{144.f,24.f}},"Help",[](MenuFuncData data){ diff --git a/Adventures in Lestoria/CraftItemWindow.cpp b/Adventures in Lestoria/CraftItemWindow.cpp index 4932a196..7cec620d 100644 --- a/Adventures in Lestoria/CraftItemWindow.cpp +++ b/Adventures in Lestoria/CraftItemWindow.cpp @@ -70,7 +70,7 @@ void Menu::InitializeCraftItemWindow(){ for(const auto&[name,amt]:consumedResources.GetItems()){ Inventory::RemoveItem(Inventory::GetItem(name)[0],amt); } - game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost()); + game->GetPlayer()->RemoveMoney(consumedResources.GetCost()); Inventory::UpdateBlacksmithInventoryLists(); SoundEffect::PlaySFX("Craft Equip",SoundEffect::CENTERED); diff --git a/Adventures in Lestoria/DEFINES.h b/Adventures in Lestoria/DEFINES.h index 70247a5b..da2b8de9 100644 --- a/Adventures in Lestoria/DEFINES.h +++ b/Adventures in Lestoria/DEFINES.h @@ -121,6 +121,10 @@ Ability&class::GetAbility1(){return ability1;}; \ Ability&class::GetAbility2(){return ability2;}; \ Ability&class::GetAbility3(){return ability3;}; \ Ability&class::GetAbility4(){return ability4;}; \ +Ability&class::_GetOriginalAbility1(){return GetOriginalAbility1();}; \ +Ability&class::_GetOriginalAbility2(){return GetOriginalAbility2();}; \ +Ability&class::_GetOriginalAbility3(){return GetOriginalAbility2();}; \ +Ability&class::_GetOriginalRightClickAbility(){return GetOriginalRightClickAbility();}; \ Ability&class::GetOriginalAbility1(){return original_ability1;}; \ Ability&class::GetOriginalAbility2(){return original_ability2;}; \ Ability&class::GetOriginalAbility3(){return original_ability3;}; \ diff --git a/Adventures in Lestoria/Item.cpp b/Adventures in Lestoria/Item.cpp index 0abf824d..6889ccbc 100644 --- a/Adventures in Lestoria/Item.cpp +++ b/Adventures in Lestoria/Item.cpp @@ -1034,7 +1034,7 @@ void Item::EnhanceItem(uint8_t qty){ for(const auto&[name,amt]:consumedResources.GetItems()){ Inventory::RemoveItem(Inventory::GetItem(name)[0],amt); } - game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost()); + game->GetPlayer()->RemoveMoney(consumedResources.GetCost()); SoundEffect::PlaySFX("Enhance Item",SoundEffect::CENTERED); @@ -1047,7 +1047,7 @@ void Item::EnhanceItem(uint8_t qty){ for(const auto&[name,amt]:consumedResources.GetItems()){ Inventory::RemoveItem(Inventory::GetItem(name)[0],amt); } - game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost()); + game->GetPlayer()->RemoveMoney(consumedResources.GetCost()); } } SoundEffect::PlaySFX("Craft Item",SoundEffect::CENTERED); @@ -1441,10 +1441,14 @@ const bool Item::CanBeRefined()const{ return false; //Maxed out, so cannot be refined. } +const bool Item::CanBeEnchanted()const{ + return IsAccessory()&&Inventory::GetItemCount(FragmentName())>="Fragment Enchant Cost"_i[0]&&game->GetPlayer()->GetMoney()>="Fragment Enchant Cost"_i[1]; +} + 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]); + game->GetPlayer()->RemoveMoney("Fragment Refine Cost"_i[1]); std::vectorstatsAvailableForRefining; for(const auto&[attr,val]:randomizedStats){ float maxVal{ITEM_DATA[ActualName()].GetMaxStats().A_Read(attr)}; @@ -1461,13 +1465,13 @@ RefineResult Item::Refine(){ return RefineResult{chosenAttr,newAmt-oldAmt}; } -void Item::EnchantItem(const std::string_view enchantName){ +void Item::_EnchantItem(const std::string_view enchantName){ enchant=ItemEnchant{enchantName}; game->GetPlayer()->RecalculateEquipStats(); } -std::optionalItem::GetEnchant()const{ +const std::optional&Item::GetEnchant()const{ return enchant; } const bool Item::HasEnchant()const{ @@ -1524,7 +1528,10 @@ const std::optional&Item::FragmentIcon()const{ } const ItemEnchantInfo Item::ApplyRandomEnchant(){ + if(!CanBeEnchanted())ERR("WARNING! Trying to enchant an item that cannot be enchanted! Make sure you are checking with CanBeEnchanted() before calling this function!"); EnchantName randomEnchantName{ItemEnchant::RollRandomEnchant()}; - EnchantItem(randomEnchantName); + _EnchantItem(randomEnchantName); + Inventory::RemoveItem(FragmentName(),"Fragment Enchant Cost"_i[0]); + game->GetPlayer()->RemoveMoney("Fragment Enchant Cost"_i[1]); return ItemEnchantInfo::GetEnchant(randomEnchantName); } \ No newline at end of file diff --git a/Adventures in Lestoria/Item.h b/Adventures in Lestoria/Item.h index 23899964..81570d28 100644 --- a/Adventures in Lestoria/Item.h +++ b/Adventures in Lestoria/Item.h @@ -254,11 +254,15 @@ public: //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(); + const bool CanBeEnchanted()const; void Lock(); void Unlock(); - void EnchantItem(const std::string_view enchantName); + void _EnchantItem(const std::string_view enchantName); + //Applies a random valid enchant to an item and consumes the materials in the process. + //Assumes an item can be enchanted. CHECK WITH CanBeEnchanted() First!!! + //Enchants the item based on its class parameters defined in the ItemEnchants.txt configuration file. Also takes away the costs required to refine the item (Located in Accessories.txt). const ItemEnchantInfo ApplyRandomEnchant(); - std::optionalGetEnchant()const; + const std::optional&GetEnchant()const; const bool HasEnchant()const; friend const bool operator==(std::shared_ptrlhs,std::shared_ptrrhs){return lhs->it==rhs->it&&lhs->randomizedStats==rhs->randomizedStats;}; friend const bool operator==(std::shared_ptrlhs,const IT&rhs){return lhs->ActualName()==const_cast(rhs);}; diff --git a/Adventures in Lestoria/Merchant.cpp b/Adventures in Lestoria/Merchant.cpp index e7db5c2e..02a99cc6 100644 --- a/Adventures in Lestoria/Merchant.cpp +++ b/Adventures in Lestoria/Merchant.cpp @@ -184,7 +184,7 @@ void Merchant::PurchaseItem(IT item,uint32_t amt){ } Inventory::AddItem(item,amt); - game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-totalCost); + game->GetPlayer()->RemoveMoney(totalCost); } void Merchant::SellItem(std::weak_ptritem,uint32_t amt){ sellFunctionPrimed.Validate(item.lock()->ActualName(),amt); @@ -222,7 +222,7 @@ void Merchant::SellItem(std::weak_ptritem,uint32_t amt){ std::string itemName=item.lock()->ActualName(); //We need the item name since our reference to the item is about to be deleted. Inventory::RemoveItem(item,amt); - game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()+totalCost); + game->GetPlayer()->AddMoney(totalCost); //If we still have some in our inventory, we'll add them back in. if(foundLoadoutSlot!=-1&&Inventory::GetItemCount(itemName)>0){ diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index ae52533e..7e2ed347 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -1288,7 +1288,6 @@ void Player::SetAnimationBasedOnTargetingDirection(const std::string_view animat std::string newAnimState{std::format("{}_{}_{}",Capitalize(GetClassName()),animation_name,facingChar)}; if(animation.HasState(newAnimState))UpdateAnimation(newAnimState); - else ERR(std::format("WARNING! Animation {} does not exist on the player! THIS SHOULD NOT BE HAPPENING!",newAnimState)); } void Player::ApplyIframes(float duration){ @@ -1539,12 +1538,12 @@ void Player::RecalculateEquipStats(){ if(GetClass()&WIZARD){ if(HasEnchant("Blink Portal"))GetRightClickAbility().COOLDOWN_TIME="Blink Portal"_ENC["COOLDOWN"]; if(HasEnchant("Summon Comet")){ - float castTimeDiff{GetOriginalAbility3().precastInfo.castTime-"Summon Comet"_ENC["METEOR CAST TIME"]}; + float castTimeDiff{_GetOriginalAbility3().precastInfo.castTime-"Summon Comet"_ENC["METEOR CAST TIME"]}; GetAbility3().precastInfo.castTime-=castTimeDiff; GetAbility3().COOLDOWN_TIME+="Summon Comet"_ENC["COOLDOWN REDUCTION"]; //This is not a typo, we add because the cooldown reduction in the config is NEGATIVE! } if(HasEnchant("Solar Flare")){ - float castTimeDiff{GetOriginalAbility3().precastInfo.castTime-"Solar Flare"_ENC["METEOR CAST TIME"]}; + float castTimeDiff{_GetOriginalAbility3().precastInfo.castTime-"Solar Flare"_ENC["METEOR CAST TIME"]}; GetAbility3().precastInfo.castTime-=castTimeDiff; GetAbility3().COOLDOWN_TIME+="Solar Flare"_ENC["COOLDOWN INCREASE"]; } @@ -2290,4 +2289,13 @@ void Player::SetTestScreenAimingLocation(vf2d forcedAimingLoc){ } void Player::SetAbility4(const Ability&ability){ +} + +void Player::RemoveMoney(const uint32_t moneyCost){ + if(moneyCost>GetMoney())ERR(std::format("WARNING! Trying to spend more money than we actually have! THIS SHOULD NOT BE HAPPENING! Current Money: {} Trying to spend: {}",GetMoney(),moneyCost)); + SetMoney(GetMoney()-moneyCost); +} + +void Player::AddMoney(const uint32_t moneyCost){ + SetMoney(GetMoney()+moneyCost); } \ No newline at end of file diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index 108686df..aa81d892 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -231,10 +231,6 @@ public: virtual Ability&GetAbility3()=0; virtual Ability&GetAbility4()=0; virtual void SetAbility4(const Ability&originalAbility)=0; //NOTE: Make sure to provide the original ability and not a current ability! - virtual Ability&GetOriginalAbility1()=0; - virtual Ability&GetOriginalAbility2()=0; - virtual Ability&GetOriginalAbility3()=0; - virtual Ability&GetOriginalRightClickAbility()=0; virtual std::string&GetWalkNAnimation()=0; virtual std::string&GetWalkEAnimation()=0; virtual std::string&GetWalkSAnimation()=0; @@ -268,6 +264,8 @@ public: static void AddMoneyListener(std::weak_ptrcomponent); uint32_t GetMoney()const; void SetMoney(uint32_t newMoney); + void AddMoney(const uint32_t moneyCost); + void RemoveMoney(const uint32_t moneyCost); void AddXP(const uint64_t xpGain); void OnLevelUp(); const uint8_t LevelCap()const; @@ -485,6 +483,10 @@ protected: vf2d leapStartingPos{}; float poisonArrowReadyTimer{}; void ActivateCatForm(); + virtual Ability&_GetOriginalAbility1()=0; + virtual Ability&_GetOriginalAbility2()=0; + virtual Ability&_GetOriginalAbility3()=0; + virtual Ability&_GetOriginalRightClickAbility()=0; }; #pragma region Warrior @@ -507,10 +509,14 @@ struct Warrior:Player{ Ability&GetAbility2()override; Ability&GetAbility3()override; Ability&GetAbility4()override; - Ability&GetOriginalAbility1()override; - Ability&GetOriginalAbility2()override; - Ability&GetOriginalAbility3()override; - Ability&GetOriginalRightClickAbility()override; + virtual Ability&_GetOriginalAbility1()override; + virtual Ability&_GetOriginalAbility2()override; + virtual Ability&_GetOriginalAbility3()override; + virtual Ability&_GetOriginalRightClickAbility()override; + static Ability&GetOriginalAbility1(); + static Ability&GetOriginalAbility2(); + static Ability&GetOriginalAbility3(); + static Ability&GetOriginalRightClickAbility(); void SetAbility4(const Ability&originalAbility)override; //NOTE: Make sure to provide the original ability and not a current ability! std::string&GetWalkNAnimation()override; std::string&GetWalkEAnimation()override; @@ -547,10 +553,14 @@ struct Thief:Player{ Ability&GetAbility2()override; Ability&GetAbility3()override; Ability&GetAbility4()override; - Ability&GetOriginalAbility1()override; - Ability&GetOriginalAbility2()override; - Ability&GetOriginalAbility3()override; - Ability&GetOriginalRightClickAbility()override; + virtual Ability&_GetOriginalAbility1()override; + virtual Ability&_GetOriginalAbility2()override; + virtual Ability&_GetOriginalAbility3()override; + virtual Ability&_GetOriginalRightClickAbility()override; + static Ability&GetOriginalAbility1(); + static Ability&GetOriginalAbility2(); + static Ability&GetOriginalAbility3(); + static Ability&GetOriginalRightClickAbility(); void SetAbility4(const Ability&originalAbility)override; //NOTE: Make sure to provide the original ability and not a current ability! std::string&GetWalkNAnimation()override; std::string&GetWalkEAnimation()override; @@ -587,10 +597,14 @@ struct Ranger:Player{ Ability&GetAbility2()override; Ability&GetAbility3()override; Ability&GetAbility4()override; - Ability&GetOriginalAbility1()override; - Ability&GetOriginalAbility2()override; - Ability&GetOriginalAbility3()override; - Ability&GetOriginalRightClickAbility()override; + virtual Ability&_GetOriginalAbility1()override; + virtual Ability&_GetOriginalAbility2()override; + virtual Ability&_GetOriginalAbility3()override; + virtual Ability&_GetOriginalRightClickAbility()override; + static Ability&GetOriginalAbility1(); + static Ability&GetOriginalAbility2(); + static Ability&GetOriginalAbility3(); + static Ability&GetOriginalRightClickAbility(); void SetAbility4(const Ability&originalAbility)override; //NOTE: Make sure to provide the original ability and not a current ability! std::string&GetWalkNAnimation()override; std::string&GetWalkEAnimation()override; @@ -627,10 +641,14 @@ struct Trapper:Player{ Ability&GetAbility2()override; Ability&GetAbility3()override; Ability&GetAbility4()override; - Ability&GetOriginalAbility1()override; - Ability&GetOriginalAbility2()override; - Ability&GetOriginalAbility3()override; - Ability&GetOriginalRightClickAbility()override; + virtual Ability&_GetOriginalAbility1()override; + virtual Ability&_GetOriginalAbility2()override; + virtual Ability&_GetOriginalAbility3()override; + virtual Ability&_GetOriginalRightClickAbility()override; + static Ability&GetOriginalAbility1(); + static Ability&GetOriginalAbility2(); + static Ability&GetOriginalAbility3(); + static Ability&GetOriginalRightClickAbility(); void SetAbility4(const Ability&originalAbility)override; //NOTE: Make sure to provide the original ability and not a current ability! std::string&GetWalkNAnimation()override; std::string&GetWalkEAnimation()override; @@ -663,14 +681,18 @@ struct Wizard:Player{ static void InitializeClassAbilities(); const std::string&GetClassName()override; Ability&GetRightClickAbility()override; - Ability&GetAbility1()override; - Ability&GetAbility2()override; - Ability&GetAbility3()override; - Ability&GetAbility4()override; - Ability&GetOriginalAbility1()override; - Ability&GetOriginalAbility2()override; - Ability&GetOriginalAbility3()override; - Ability&GetOriginalRightClickAbility()override; + Ability&GetAbility1(); + Ability&GetAbility2(); + Ability&GetAbility3(); + Ability&GetAbility4(); + virtual Ability&_GetOriginalAbility1()override; + virtual Ability&_GetOriginalAbility2()override; + virtual Ability&_GetOriginalAbility3()override; + virtual Ability&_GetOriginalRightClickAbility()override; + static Ability&GetOriginalAbility1(); + static Ability&GetOriginalAbility2(); + static Ability&GetOriginalAbility3(); + static Ability&GetOriginalRightClickAbility(); void SetAbility4(const Ability&originalAbility)override; //NOTE: Make sure to provide the original ability and not a current ability! std::string&GetWalkNAnimation()override; std::string&GetWalkEAnimation()override; @@ -707,10 +729,14 @@ struct Witch:Player{ Ability&GetAbility2()override; Ability&GetAbility3()override; Ability&GetAbility4()override; - Ability&GetOriginalAbility1()override; - Ability&GetOriginalAbility2()override; - Ability&GetOriginalAbility3()override; - Ability&GetOriginalRightClickAbility()override; + virtual Ability&_GetOriginalAbility1()override; + virtual Ability&_GetOriginalAbility2()override; + virtual Ability&_GetOriginalAbility3()override; + virtual Ability&_GetOriginalRightClickAbility()override; + static Ability&GetOriginalAbility1(); + static Ability&GetOriginalAbility2(); + static Ability&GetOriginalAbility3(); + static Ability&GetOriginalRightClickAbility(); void SetAbility4(const Ability&originalAbility)override; //NOTE: Make sure to provide the original ability and not a current ability! std::string&GetWalkNAnimation()override; std::string&GetWalkEAnimation()override; diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 02dd97f7..2e5c9807 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 3 #define VERSION_PATCH 0 -#define VERSION_BUILD 11564 +#define VERSION_BUILD 11598 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/audio/events.txt b/Adventures in Lestoria/assets/config/audio/events.txt index 0e052b81..ac752ad4 100644 --- a/Adventures in Lestoria/assets/config/audio/events.txt +++ b/Adventures in Lestoria/assets/config/audio/events.txt @@ -137,6 +137,12 @@ Events # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) File[0] = disassemble.ogg, 70% } + Enchant Item + { + CombatSound = True + # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) + File[0] = enchant_item.ogg, 100% + } Equip Armor { # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) @@ -323,6 +329,12 @@ Events # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) File[0] = ranger_charged_shot.ogg, 70% } + Refine Item + { + CombatSound = True + # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) + File[0] = refine_item.ogg, 60%, 110%, 130% + } Rise { CombatSound = True diff --git a/Adventures in Lestoria/assets/sounds/enchant_item.ogg b/Adventures in Lestoria/assets/sounds/enchant_item.ogg new file mode 100644 index 00000000..522a84fa Binary files /dev/null and b/Adventures in Lestoria/assets/sounds/enchant_item.ogg differ diff --git a/Adventures in Lestoria/assets/sounds/refine_item.ogg b/Adventures in Lestoria/assets/sounds/refine_item.ogg new file mode 100644 index 00000000..4b4e18b5 Binary files /dev/null and b/Adventures in Lestoria/assets/sounds/refine_item.ogg differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index fd506bb6..ab18d48b 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ