diff --git a/Adventures in Lestoria/CharacterMenuWindow.cpp b/Adventures in Lestoria/CharacterMenuWindow.cpp index 4c5ca8d6..5f11987c 100644 --- a/Adventures in Lestoria/CharacterMenuWindow.cpp +++ b/Adventures in Lestoria/CharacterMenuWindow.cpp @@ -50,6 +50,9 @@ All rights reserved. #include "SoundEffect.h" #include "ProgressBar.h" #include "MenuItemLabel.h" +#ifndef __EMSCRIPTEN__ + #include +#endif INCLUDE_game INCLUDE_GFX @@ -99,6 +102,19 @@ namespace CharacterMenuWindow{ if(!comp.expired()){ if(SelectedEquipIsDifferent(comp)){ //If we find that the opposite ring slot is equipped to us, this would be an item swap or the exact same ring, therefore no stat calculations apply. Inventory::EquipItem(comp.lock()->GetItem(),EquipSlot(comp.lock()->I(Attribute::EQUIP_TYPE))); + + #pragma region Achievement Stuff + if(SteamUserStats()){ + #pragma region Fully Decked Out Achievement + datafile&unlock=DATA.GetProperty("Achievement.Equip Unlocks.Fully Decked Out"); + if(Inventory::EquipsFullyMaxedOut(unlock["Weapon Max Level"].GetInt(),unlock["Armor Max Level"].GetInt())){ + SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str()); + SteamUserStats()->StoreStats(); + } + #pragma endregion + } + #pragma endregion + if(Menu::IsCurrentlyActive(data.menu.GetType())){ SoundEffect::PlaySFX(comp.lock()->GetItem().lock()->UseSound(),SoundEffect::CENTERED); } diff --git a/Adventures in Lestoria/Item.cpp b/Adventures in Lestoria/Item.cpp index 635f04a7..6d125899 100644 --- a/Adventures in Lestoria/Item.cpp +++ b/Adventures in Lestoria/Item.cpp @@ -47,6 +47,9 @@ All rights reserved. #include "SoundEffect.h" #include "ClassInfo.h" #include "RowInventoryScrollableWindowComponent.h" +#ifndef __EMSCRIPTEN__ + #include +#endif INCLUDE_game INCLUDE_DATA @@ -840,8 +843,10 @@ void Inventory::EquipItem(const std::weak_ptrit,EquipSlot slot){ if(equippedSlot!=EquipSlot::NONE)UnequipItem(equippedSlot); if(!GetEquip(slot).expired())UnequipItem(slot); Inventory::equipment[slot]=it; + game->GetPlayer()->RecalculateEquipStats(); }; + void Inventory::UnequipItem(EquipSlot slot){ Inventory::equipment[slot]=Item::BLANK; game->GetPlayer()->RecalculateEquipStats(); @@ -923,6 +928,33 @@ void Item::EnhanceItem(uint8_t qty){ if(enhancementLevel+1>"Item.Item Max Enhancement Level"_I)ERR("WARNING! Attempted to enhance "<SetAchievement(unlock["API Name"].GetString().c_str()); + SteamUserStats()->StoreStats(); + } + #pragma endregion + #pragma region Equipment achievement unlocks + for(auto&[key,size]:DATA.GetProperty("Achievement.Equip Unlocks")){ + datafile&unlock=DATA.GetProperty(std::format("Achievement.Equip Unlocks.{}",key)); + if(!(unlock.HasProperty("Upgrade Requirement")&&unlock.HasProperty("Equip Slot")))continue; //Ignore any achievements that don't have an upgrade requirement/equipment slot defined. + if(EnhancementLevel()>=unlock["Upgrade Requirement"].GetInt()){ + EquipSlot validSlots=EquipSlot::NONE; + for(const std::string&slot:unlock["Equip Slot"].GetValues()){ + validSlots|=ItemInfo::StringToEquipSlot(slot); //Collect all the bits that this equipment can fall under. + } + if(GetEquipSlot()&validSlots){ + //This piece of gear matches one of the provided slots. + SteamUserStats()->SetAchievement(unlock["API Name"].GetString().c_str()); + SteamUserStats()->StoreStats(); + } + } + } + #pragma endregion + } const CraftingRequirement&consumedResources=GetEnhancementInfo()[EnhancementLevel()].craftingRequirement; @@ -1284,4 +1316,25 @@ void Item::Lock(){ } void Item::Unlock(){ locked=false; +} + +//Specifically for the "Fully Decked Out" achievement. +const bool Inventory::EquipsFullyMaxedOut(int maxWeaponLevel,int maxArmorLevel){ + for(int i=int(EquipSlot::HELMET);i<=int(EquipSlot::RING2);i<<=1){ + EquipSlot slot=EquipSlot(i); + if(!ISBLANK(Inventory::GetEquip(slot))){ + std::shared_ptrequip=Inventory::GetEquip(slot).lock(); + if(!(equip->IsAccessory()|| + (equip->IsWeapon()&&equip->EnhancementLevel()>=maxWeaponLevel)|| + (equip->IsArmor()&&equip->EnhancementLevel()>=maxArmorLevel)) + ){ + return false; + } + }else return false; + } + return true; +} + +const EquipSlot ItemInfo::StringToEquipSlot(std::string_view slotName){ + return nameToEquipSlot[std::string(slotName)]; } \ No newline at end of file diff --git a/Adventures in Lestoria/Item.h b/Adventures in Lestoria/Item.h index a6ee1974..66673a37 100644 --- a/Adventures in Lestoria/Item.h +++ b/Adventures in Lestoria/Item.h @@ -269,6 +269,7 @@ public: static void AddLoadoutItemUsed(IT item,int slot); static void ResetLoadoutItemsUsed(); static void GivePlayerLoadoutItemsUsed(); + static const bool EquipsFullyMaxedOut(int maxWeaponLevel=10,int maxArmorLevel=10); static bool SwapItems(ITCategory itemCategory,uint32_t slot1,uint32_t slot2); //Makes sure this is a valid category. Will error out if it doesn't exist! Use for ERROR HANDLING! @@ -338,6 +339,7 @@ public: const std::string&Description()const; const ITCategory Category()const; const::Decal*const Decal()const; + static const EquipSlot StringToEquipSlot(std::string_view slotName); /* For the useFunc, return true if the item can be used, false otherwise. */ diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index 2bd4a06c..e682e7cd 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -56,6 +56,8 @@ FULLY_DECKED_OUT Include a Reset Achievements button in Settings +Enhancing can also trigger the "fully decked out" achievement + ============================================ Consider a "killed by player" / "marked by player" flag for monsters to determine if a player gets credit for a monster kill (for achievements) diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 184a844c..0b6e2e6f 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 0 #define VERSION_PATCH 0 -#define VERSION_BUILD 8534 +#define VERSION_BUILD 8548 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/Achievements.txt b/Adventures in Lestoria/assets/config/Achievements.txt index a1f95c36..c5e78647 100644 --- a/Adventures in Lestoria/assets/config/Achievements.txt +++ b/Adventures in Lestoria/assets/config/Achievements.txt @@ -91,21 +91,26 @@ Achievement Weapon Lv5 { API Name = "WEAPON_LV5" + Equip Slot = Weapon Upgrade Requirement = 5 } Armor Lv5 { API Name = "ARMOR_LV5" + Equip Slot = Helmet,Armor,Gloves,Pants,Shoes Upgrade Requirement = 5 } Armor Lv10 { API Name = "ARMOR_LV10" + Equip Slot = Helmet,Armor,Gloves,Pants,Shoes Upgrade Requirement = 10 } Fully Decked Out { API Name = "FULLY_DECKED_OUT" + Weapon Max Level = 5 + Armor Max Level = 10 } } } \ No newline at end of file diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 9d2e84e0..b4d1406e 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ