diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index 67d911ca..21190f13 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -359,15 +359,15 @@ - + - + - + @@ -599,6 +599,10 @@ + + + + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index 8eb713fc..a4884c87 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -423,9 +423,6 @@ Header Files\Interface - - Header Files - Header Files @@ -447,6 +444,9 @@ Header Files\State + + Header Files + @@ -776,6 +776,9 @@ Source Files\Interface + + Source Files + diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 61c5442a..c64bfa79 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -243,33 +243,8 @@ bool AiL::OnUserCreate(){ Menu::InitializeMenus(); - Inventory::AddItem("Minor Health Potion",16); - Inventory::AddItem("Bandages",10); - Inventory::AddItem("Green Slime Remains",40); - Inventory::AddItem("Blue Slime Remains",22); - Inventory::AddItem("Copper Armor"); - Inventory::AddItem("Copper Pants"); - Inventory::AddItem("Copper Helmet"); - Inventory::AddItem("Copper Shoes"); - Inventory::AddItem("Shell Helmet"); - Inventory::AddItem("Shell Armor"); - Inventory::AddItem("Shell Armor"); - Inventory::AddItem("Shell Armor"); - Inventory::AddItem("Bone Armor"); - Inventory::AddItem("Shell Gloves"); - Inventory::AddItem("Shell Gloves",3); - Inventory::AddItem("Shell Shoes"); - Inventory::AddItem("Bone Pants"); - Inventory::AddItem("Bone Gloves"); - Inventory::AddItem("Elixir of Bear Strength",3); - Inventory::AddItem("Leather Helmet"); - Inventory::AddItem("Leather Pants"); - Inventory::AddItem("Leather Gloves"); - Inventory::AddItem("Leather Shoes"); - Inventory::AddItem("Wooden Sword"); - Inventory::AddItem("Laser Sword"); - Inventory::AddItem("Shell Sword"); - Inventory::AddItem("Ring of the Slime King",3); + Inventory::AddItem("Minor Health Potion"s,3); + Inventory::AddItem("Bandages"s,10); Audio::Initialize(); EnvironmentalAudio::Initialize(); diff --git a/Adventures in Lestoria/BlacksmithCraftingWindow.cpp b/Adventures in Lestoria/BlacksmithCraftingWindow.cpp index d0902d97..15d73bca 100644 --- a/Adventures in Lestoria/BlacksmithCraftingWindow.cpp +++ b/Adventures in Lestoria/BlacksmithCraftingWindow.cpp @@ -142,14 +142,25 @@ void Menu::InitializeBlacksmithCraftingWindow(){ const std::weak_ptritem=comp.lock()->GetItem(); std::string label=""; - if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ - label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); + if(Inventory::GetItemCount(item.lock()->ActualName())==0){ //If we don't own the item we have to create it first. + if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ + label=""; + } + Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); + Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); + Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); + }else{ //We will open the menu that lets us enhance by one level. + if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ + label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); + } + Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); + Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Enhancing {}",item.lock()->DisplayName())); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); + Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); } - Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); - Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); - Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); - Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); - Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); return true; }, [](MenuFuncData data){ diff --git a/Adventures in Lestoria/CraftItemWindow.cpp b/Adventures in Lestoria/CraftItemWindow.cpp index f1546f14..1629a62e 100644 --- a/Adventures in Lestoria/CraftItemWindow.cpp +++ b/Adventures in Lestoria/CraftItemWindow.cpp @@ -56,10 +56,12 @@ void Menu::InitializeCraftItemWindow(){ craftItemWindow->ADD("Back Button",MenuComponent)(geom2d::rect{{36,116},{48,12}},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;})END; craftItemWindow->ADD("Craft Button",MenuComponent)(geom2d::rect{{craftItemWindow->size.x-84,116},{48,12}},"Craft",[](MenuFuncData data){ - const std::weak_ptritem=Component(data.menu.GetType(),"Enhancement Stats Label")->GetItem(); + std::weak_ptritem=Component(data.menu.GetType(),"Enhancement Stats Label")->GetItem(); if(item.lock()->CanEnhanceItem()){ if(Inventory::GetItemCount(item.lock()->ActualName())==0){ //We don't own this item, so we need to give the player this item and refresh the blacksmith's inventory. - Inventory::AddItem(item.lock()->ActualName()); + item=Inventory::AddItem(item.lock()->ActualName()); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); //Update the item refs in the enhancement level screen to now display the correct item. Inventory::UpdateBlacksmithInventoryLists(); }else{ //Since we already own this equipment, just enhance it. item.lock()->EnhanceItem(); diff --git a/Adventures in Lestoria/DEFINES.h b/Adventures in Lestoria/DEFINES.h index df972138..6dd69956 100644 --- a/Adventures in Lestoria/DEFINES.h +++ b/Adventures in Lestoria/DEFINES.h @@ -57,6 +57,7 @@ using BackdropName=std::string; #define INCLUDE_ITEM_CATEGORIES extern safemap>ITEM_CATEGORIES; #define DO_NOTHING [](MenuFuncData data){return true;} #define INCLUDE_WINDOW_SIZE extern vi2d WINDOW_SIZE; +#define INCLUDE_ITEM_CONVERSIONS extern safemapITEM_CONVERSIONS; #define INCLUDE_BACKDROP_DATA extern std::mapBACKDROP_DATA; @@ -75,7 +76,7 @@ class::class() \ class::class(Player*player) \ :Player::Player(player){} \ Class class::GetClass(){return cl;} \ -std::string class::GetClassName(){return name;} \ +const std::string&class::GetClassName(){return name;} \ Ability&class::GetRightClickAbility(){return rightClickAbility;}; \ Ability&class::GetAbility1(){return ability1;}; \ Ability&class::GetAbility2(){return ability2;}; \ diff --git a/Adventures in Lestoria/EnhancementStatsLabel.h b/Adventures in Lestoria/EnhancementStatsLabel.h index eda66391..c2fdd9c5 100644 --- a/Adventures in Lestoria/EnhancementStatsLabel.h +++ b/Adventures in Lestoria/EnhancementStatsLabel.h @@ -90,16 +90,13 @@ protected: std::string percentageSign=attr.DisplayAsPercent()?"%":""; if(Inventory::GetItemCount(itemRef.lock()->ActualName())==0){ //This item hasn't been created yet, so just show that we are developing the item first. - window.DrawShadowStringDecal(drawPos+vf2d{maxAttributeLabelSize+4+24,yOffset},std::format("{:<5}", - attr.ShowAsDecimal()?std::format("{:>4.2f}{}",value,percentageSign):std::format("{}{}",value,percentageSign), - nextStageValue!=0? - attr.ShowAsDecimal()?std::format("{:<4.2f}{}",nextStageValue,percentageSign):std::format("{}{}",nextStageValue,percentageSign) - :"MAX"), + window.DrawShadowStringDecal(drawPos+vf2d{maxAttributeLabelSize+4+24,yOffset},std::format("{:<5}",( + (attr.ShowAsDecimal()?std::format("{:>4.2f}{}",value,percentageSign):std::format("{}{}",value,percentageSign)))), WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits::max():rect.size.x,1.0f); }else{ //This item is getting enhanced to the next level. window.DrawShadowStringDecal(drawPos+vf2d{maxAttributeLabelSize+4+24,yOffset},std::format("{:>5} ->#00AA00 {:<5}", attr.ShowAsDecimal()?std::format("{:>4.2f}{}",value,percentageSign):std::format("{}{}",value,percentageSign), - nextStageValue!=0? + nextEnhanceLevel!="Item.Item Max Enhancement Level"_I? attr.ShowAsDecimal()?std::format("{:<4.2f}{}",nextStageValue,percentageSign):std::format("{}{}",nextStageValue,percentageSign) :"MAX"), WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits::max():rect.size.x,1.0f); diff --git a/Adventures in Lestoria/FunctionPriming.h b/Adventures in Lestoria/FunctionPriming.h index ecd653b5..e64c8df2 100644 --- a/Adventures in Lestoria/FunctionPriming.h +++ b/Adventures in Lestoria/FunctionPriming.h @@ -38,7 +38,9 @@ All rights reserved. #pragma once #include "Error.h" #include -using IT=std::string; +#include "IT.h" + +using namespace std::literals; struct FunctionPrimingData{ bool primed=false; @@ -51,7 +53,7 @@ struct FunctionPrimingData{ }; struct MerchantFunctionPrimingData:public FunctionPrimingData{ - IT item=""; + IT item=""s; uint32_t amt=0; inline MerchantFunctionPrimingData(std::string dependentFunction) :FunctionPrimingData(dependentFunction){} @@ -67,7 +69,7 @@ struct MerchantFunctionPrimingData:public FunctionPrimingData{ }; struct ItemEnhancementFunctionPrimingData:public FunctionPrimingData{ - IT item=""; + IT item=""s; uint8_t enhancementLevel=0; uint8_t qty=0; inline ItemEnhancementFunctionPrimingData(std::string dependentFunction) diff --git a/Adventures in Lestoria/IT.cpp b/Adventures in Lestoria/IT.cpp new file mode 100644 index 00000000..728a000d --- /dev/null +++ b/Adventures in Lestoria/IT.cpp @@ -0,0 +1,70 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions or derivations of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions or derivative works in binary form must reproduce the above +copyright notice. This list of conditions and the following disclaimer must be +reproduced in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +Portions of this software are copyright © 2023 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion + +#include "DEFINES.h" +#include "IT.h" +#include "Item.h" + +INCLUDE_ITEM_CONVERSIONS + +IT::IT():itemName(""){} +IT::IT(std::string name) + :itemName(name){ + if(ITEM_CONVERSIONS.count(name)){ + itemName=ITEM_CONVERSIONS.at(name); //Convert the item if it's using an old name. + } +} +IT::operator std::string(){ + return itemName; +} +std::ostream&operator<<(std::ostream&rhs,IT&item){ + rhs<&rhs){ + return itemName==rhs->ActualName(); +} +const bool IT::operator==(const std::weak_ptr&rhs){ + return !rhs.expired()&&itemName==rhs.lock()->ActualName(); +} +const bool operator==(const IT&lhs,const IT&rhs){ + return lhs.itemName==rhs.itemName; +} +const bool operator<(const IT&lhs,const IT&rhs){ + return lhs.itemName +#include +#include + +class Item; + +class IT{ + friend struct std::formatter; + std::string itemName=""; +public: + IT(); + IT(std::string name); + operator std::string(); + const bool operator==(const std::shared_ptr&rhs); + const bool operator==(const std::weak_ptr&rhs); + friend std::ostream&operator<<(std::ostream&rhs,IT&item); + friend const bool operator==(const IT&lhs,const IT&rhs); + friend const bool operator<(const IT&lhs,const IT&rhs); +}; +template <> +struct std::formatter { + constexpr auto parse(std::format_parse_context&ctx) { + return ctx.begin(); + } + + auto format(const IT&item,std::format_context&ctx) const { + return std::format_to(ctx.out(),"{}",item.itemName); + } +}; \ No newline at end of file diff --git a/Adventures in Lestoria/InventoryCreator.cpp b/Adventures in Lestoria/InventoryCreator.cpp index 6c65e452..9564aabf 100644 --- a/Adventures in Lestoria/InventoryCreator.cpp +++ b/Adventures in Lestoria/InventoryCreator.cpp @@ -146,7 +146,11 @@ std::function [](InventoryScrollableWindowComponent&component,ITCategory cat){ std::vector>weapons; std::copy_if(Inventory::get("Equipment").begin(),Inventory::get("Equipment").end(),std::back_inserter(weapons),[](std::shared_ptritem){return item->IsWeapon();}); - std::copy_if(Inventory::blacksmithInventory.begin(),Inventory::blacksmithInventory.end(),std::back_inserter(weapons),[](std::shared_ptritem){return item->IsWeapon();}); + std::copy_if(Inventory::blacksmithInventory.begin(),Inventory::blacksmithInventory.end(),std::back_inserter(weapons),[](std::shared_ptritem){return game->GetCurrentChapter()>=item->GetEnhancementInfo().AvailableChapter()&&item->GetClass()==game->GetPlayer()->GetClassName()&&item->IsWeapon();}); + + std::sort(weapons.begin(),weapons.end(),[](const std::weak_ptr&it1,const std::weak_ptr&it2){ + return ItemSortRules::GetItemSortRanking(it1)(&component); @@ -183,7 +187,11 @@ std::function [](InventoryScrollableWindowComponent&component,ITCategory cat){ std::vector>armor; std::copy_if(Inventory::get("Equipment").begin(),Inventory::get("Equipment").end(),std::back_inserter(armor),[](std::shared_ptritem){return item->IsArmor();}); - std::copy_if(Inventory::blacksmithInventory.begin(),Inventory::blacksmithInventory.end(),std::back_inserter(armor),[](std::shared_ptritem){return item->IsArmor();}); + std::copy_if(Inventory::blacksmithInventory.begin(),Inventory::blacksmithInventory.end(),std::back_inserter(armor),[](std::shared_ptritem){return game->GetCurrentChapter()>=item->GetEnhancementInfo().AvailableChapter()&&item->GetClass()==game->GetPlayer()->GetClassName()&&item->IsArmor();}); + + std::sort(armor.begin(),armor.end(),[](const std::weak_ptr&it1,const std::weak_ptr&it2){ + return ItemSortRules::GetItemSortRanking(it1)(&component); diff --git a/Adventures in Lestoria/Item.cpp b/Adventures in Lestoria/Item.cpp index 8518893e..94001a44 100644 --- a/Adventures in Lestoria/Item.cpp +++ b/Adventures in Lestoria/Item.cpp @@ -69,11 +69,20 @@ int Item::IsBlankStaticCallCounter=0; safemapStats::maxDamageReductionTable; ItemEnhancementFunctionPrimingData Item::enhanceFunctionPrimed("CanEnhanceItem()"); std::vector>ItemInfo::craftableConsumables; +std::vectorItemSortRules::primarySort; +std::vectorItemSortRules::secondarySort; ItemInfo::ItemInfo() :customProps({nullptr,nullptr}),img(nullptr){} void ItemInfo::InitializeItems(){ + for(const std::string&data:DATA.GetProperty("Item.Equipment Sort Order Primary").GetValues()){ + ItemSortRules::primarySort.push_back(data); + } + for(const std::string&data:DATA.GetProperty("Item.Equipment Sort Order Secondary").GetValues()){ + ItemSortRules::secondarySort.push_back(data); + } + for(int i=int(EquipSlot::HELMET);i<=int(EquipSlot::RING2);i<<=1){ Inventory::equipment[EquipSlot(i)]=Item::BLANK; } @@ -171,8 +180,8 @@ void ItemInfo::InitializeItems(){ if(data[key].HasProperty("StatValues[0]")){ //This means this has enhancement levels. EnhancementInfo enhancementStats; + uint8_t availableChapter=1; for(int enhancementLevel=0;enhancementLevel<=10;enhancementLevel++){ - uint8_t availableChapter=1; datafile&dat=data[key]["StatValues["+std::to_string(enhancementLevel)+"]"]; for(int attrIndex=0;ItemAttribute&attr:statValueList){ enhancementStats.SetAttribute(enhancementLevel,attr,dat.GetReal(attrIndex)); @@ -295,6 +304,13 @@ void ItemInfo::InitializeItems(){ if(it.Category()=="Accessories"&&it.IsArmor())ERR(std::format("WARNING! {} is in the Accessories Category, but is considered Armor!",it.Name())) if(it.Category()=="Accessories"&&!it.IsAccessory())ERR(std::format("WARNING! {} is in the Accessories Category, but not considered an Accessory!",it.Name())) #pragma endregion + + #pragma region Equipment Sort Rules Verification Tests + if(category=="Equipment"){ + if(std::find_if(ItemSortRules::primarySort.begin(),ItemSortRules::primarySort.end(),[&](const std::string&sort){return key.find(sort)!=std::string::npos;})==ItemSortRules::primarySort.end())ERR(std::format("WARNING! Item {} does not have valid equipment sorting primary rule! Check items.txt config key: 'Equipment Sort Order Primary'!",key)) + if(std::find_if(ItemSortRules::secondarySort.begin(),ItemSortRules::secondarySort.end(),[&](const std::string&sort){return key.find(sort)!=std::string::npos;})==ItemSortRules::secondarySort.end())ERR(std::format("WARNING! Item {} does not have valid equipment sorting secondary rule! Check items.txt config key: 'Equipment Sort Order Secondary'!",key)) + } + #pragma endregion } }; @@ -408,28 +424,19 @@ Item::Item() :amt(0),it(nullptr),enhancementLevel(0){} Item::Item(uint32_t amt,IT item,uint8_t enhancementLevel) - :amt(amt),enhancementLevel(enhancementLevel){ - if(ITEM_CONVERSIONS.count(item)){ - it=&ITEM_DATA.at(ITEM_CONVERSIONS[item]); //Convert the item if it's using an old name. - }else{ - it=&ITEM_DATA.at(item); - } -} + :amt(amt),enhancementLevel(enhancementLevel),it(&ITEM_DATA.at(item)){} std::weak_ptrInventory::AddItem(IT it,uint32_t amt,bool monsterDrop){ - if(ITEM_CONVERSIONS.count(it)){ - it=ITEM_CONVERSIONS[it]; //Convert the item if it's using an old name. - } - if(!ITEM_DATA.count(it))ERR("Item "<itemPtr; + std::shared_ptrnewItem; if(ITEM_DATA[it].IsEquippable()){ //Do not stack equips! for(uint32_t i=0;inewItem=(*_inventory.insert({it,std::make_shared(1,it)})).second; + newItem=(*_inventory.insert({it,std::make_shared(1,it)})).second; newItem->RandomizeStats(); InsertIntoSortedInv(newItem); - InsertIntoStageInventoryCategory(newItem,monsterDrop); itemPtr=newItem; } goto SkipAddingStackableItem; @@ -437,9 +444,8 @@ std::weak_ptrInventory::AddItem(IT it,uint32_t amt,bool monsterDrop){ else //There are two places to manipulate items in (Both the sorted inventory and the actual inventory) if(!_inventory.count(it)){ - std::shared_ptrnewItem=(*_inventory.insert({it,std::make_shared(amt,it)})).second; + newItem=(*_inventory.insert({it,std::make_shared(amt,it)})).second; InsertIntoSortedInv(newItem); - InsertIntoStageInventoryCategory(newItem,monsterDrop); itemPtr=newItem; }else{ auto inventory=_inventory.equal_range(it); @@ -447,10 +453,12 @@ std::weak_ptrInventory::AddItem(IT it,uint32_t amt,bool monsterDrop){ [&](int counter,std::pair>item){ (*item.second).amt+=amt; itemPtr=item.second; + newItem=std::make_shared(amt,it); return counter+1;})>1)ERR("WARNING! We should not have more than 1 instance of a stackable item!"); } SkipAddingStackableItem: + InsertIntoStageInventoryCategory(newItem,monsterDrop); return itemPtr; } @@ -671,7 +679,10 @@ const std::string Item::Description(CompactText compact)const{ if(compact==CRAFTING_INFO){ description+="\n\nCrafting Requirements:\n---------\n"; if(IsCraftable()){ - const EnhancementLevelInfo&info=GetEnhancementInfo()[EnhancementLevel()+1]; + size_t enhanceIndex=EnhancementLevel()+1; + if(IsEquippable()&&Inventory::GetItemCount(ActualName())==0)enhanceIndex=0; + + const EnhancementLevelInfo&info=GetEnhancementInfo()[enhanceIndex]; for(const auto&[name,amt]:info.craftingRequirement.GetItems()){ description+=std::format("{}{} x{} ({})\n", Inventory::GetItemCount(name)(item)))ERR("Item "<(item)<<" does not exist in the item database!"); + return ITEM_DATA[const_cast(item)]; } const uint32_t ItemInfo::GetBuyValue()const{ @@ -1069,7 +1080,7 @@ const bool Item::CanEnhanceItem(uint8_t qty)const{ if(!GetEnhancementInfo().CanBeEnhanced())return false; if(GetEnhancementInfo().AvailableChapter()GetCurrentChapter())return false; size_t enhanceIndex=EnhancementLevel()+1; - if(Inventory::GetItemCount(ActualName())==0)enhanceIndex=0; + if(IsEquippable()&&Inventory::GetItemCount(ActualName())==0)enhanceIndex=0;//Equipment we don't have we need to first craft. const EnhancementLevelInfo&enhanceInfo=GetEnhancementInfo()[enhanceIndex]; if(GetEnhancementInfo().size()>2){ //If the item has exactly 2 enhancement levels, then it's an item that can only simply be crafted. Therefore, don't do the max enhancement level check. if(EnhancementLevel()>="Item.Item Max Enhancement Level"_I)return false; @@ -1181,7 +1192,7 @@ const std::vector>Inventory::GetInventory(){ } const std::string&ItemInfo::GetClass()const{ - return equippableClass; + return equippableClass.length()==0?game->GetPlayer()->GetClassName():equippableClass; } const std::string&Item::GetClass()const{ @@ -1203,4 +1214,27 @@ void Inventory::UpdateBlacksmithInventoryLists(){ InventoryCreator::RowPlayerWeapons_InventorySlotsUpdate(*DYNAMIC_POINTER_CAST(weaponsList),"Equipment"); InventoryCreator::RowPlayerArmor_InventorySlotsUpdate(*DYNAMIC_POINTER_CAST(armorList),"Equipment"); +} + +uint16_t ItemSortRules::GetItemSortRanking(const std::weak_ptr&it){ + uint16_t sortRank=0; + auto secondaryFind=std::find_if(secondarySort.begin(),secondarySort.end(),[&](const std::string&sort){ + if(it.lock()->DisplayName().find(sort)!=std::string::npos){ + return true; + } + return false; + }); + sortRank+=std::distance(secondarySort.begin(),secondaryFind); + auto primaryFind=std::find_if(primarySort.begin(),primarySort.end(),[&](const std::string&sort){ + if(it.lock()->DisplayName().find(sort)!=std::string::npos){ + return true; + } + return false; + }); + sortRank+=std::distance(primarySort.begin(),primaryFind)*(secondarySort.size()+1); + return sortRank; +} + +uint16_t ItemSortRules::MaxSortRanking(){ + return primarySort.size()*(secondarySort.size()+1)+secondarySort.size(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Item.h b/Adventures in Lestoria/Item.h index 926b7d9f..dd66fb4e 100644 --- a/Adventures in Lestoria/Item.h +++ b/Adventures in Lestoria/Item.h @@ -46,12 +46,12 @@ All rights reserved. #include "Merchant.h" #include "CraftingRequirement.h" #include "FunctionPriming.h" +#include "IT.h" class AiL; class ItemInfo; class ItemProps; -using IT=std::string; using ITCategory=std::string; using EventName=std::string; @@ -132,6 +132,16 @@ public: const size_t size()const; }; +class ItemSortRules{ + friend class ItemInfo; +public: + static std::vectorprimarySort; + static std::vectorsecondarySort; + //Returns a number based on what the equipment type of an item is. The lower the number, the earlier it should appear in the list. + static uint16_t GetItemSortRanking(const std::weak_ptr&it); + static uint16_t MaxSortRanking(); +}; + //You cannot create instances of this class, access sets from ItemSet::sets and add the appropriate set bonuses. class ItemSet{ friend class ItemInfo; @@ -219,9 +229,9 @@ public: //Use ISBLANK macro instead!! This should not be called directly!! static bool IsBlank(std::weak_ptritem); 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()==rhs;}; + friend const bool operator==(std::shared_ptrlhs,const IT&rhs){return lhs->ActualName()==const_cast(rhs);}; friend const bool operator==(std::weak_ptrlhs,std::weak_ptrrhs){return !lhs.expired()&&!rhs.expired()&&lhs.lock()->it==rhs.lock()->it&&lhs.lock()->randomizedStats==rhs.lock()->randomizedStats;}; - friend const bool operator==(std::weak_ptrlhs,const IT&rhs){return !lhs.expired()&&lhs.lock()->ActualName()==rhs;}; + friend const bool operator==(std::weak_ptrlhs,const IT&rhs){return !lhs.expired()&&lhs.lock()->ActualName()==const_cast(rhs);}; friend const bool operator==(const IT&lhs,std::weak_ptrrhs){return operator==(rhs,lhs);}; friend const bool operator==(const IT&lhs,std::shared_ptrrhs){return operator==(rhs,lhs);}; }; diff --git a/Adventures in Lestoria/LevelCompleteWindow.cpp b/Adventures in Lestoria/LevelCompleteWindow.cpp index 6dbb2e36..295b7111 100644 --- a/Adventures in Lestoria/LevelCompleteWindow.cpp +++ b/Adventures in Lestoria/LevelCompleteWindow.cpp @@ -65,7 +65,6 @@ void Menu::InitializeLevelCompleteWindow(){ auto nextButtonAction=[](MenuFuncData data){ Unlock::UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map); - game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName()); Merchant::RandomizeTravelingMerchant(); GameState::ChangeState(States::GAME_HUB,0.25f); return true; diff --git a/Adventures in Lestoria/Merchant.h b/Adventures in Lestoria/Merchant.h index c87effd8..7ecb5992 100644 --- a/Adventures in Lestoria/Merchant.h +++ b/Adventures in Lestoria/Merchant.h @@ -40,7 +40,6 @@ All rights reserved. class Item; using Chapter=int; -using IT=std::string; using ITCategory=std::string; class Merchant{ diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index 4ee071a0..daa86038 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -189,7 +189,7 @@ public: virtual Class GetClass()=0; virtual bool AutoAttack()=0; virtual void OnUpdate(float fElapsedTime)=0; - virtual std::string GetClassName()=0; + virtual const std::string&GetClassName()=0; virtual Ability&GetRightClickAbility()=0; virtual Ability&GetAbility1()=0; virtual Ability&GetAbility2()=0; @@ -354,7 +354,7 @@ struct Warrior:Player{ //Include only WARRIOR-specific implementations! void OnUpdate(float fElapsedTime)override; static void InitializeClassAbilities(); - std::string GetClassName()override; + const std::string&GetClassName()override; Ability&GetRightClickAbility()override; Ability&GetAbility1()override; Ability&GetAbility2()override; @@ -385,7 +385,7 @@ struct Thief:Player{ //Include only THIEF-specific implementations! void OnUpdate(float fElapsedTime)override; static void InitializeClassAbilities(); - std::string GetClassName()override; + const std::string&GetClassName()override; Ability&GetRightClickAbility()override; Ability&GetAbility1()override; Ability&GetAbility2()override; @@ -416,7 +416,7 @@ struct Ranger:Player{ //Include only RANGER-specific implementations! void OnUpdate(float fElapsedTime)override; static void InitializeClassAbilities(); - std::string GetClassName()override; + const std::string&GetClassName()override; Ability&GetRightClickAbility()override; Ability&GetAbility1()override; Ability&GetAbility2()override; @@ -447,7 +447,7 @@ struct Trapper:Player{ //Include only TRAPPER-specific implementations! void OnUpdate(float fElapsedTime)override; static void InitializeClassAbilities(); - std::string GetClassName()override; + const std::string&GetClassName()override; Ability&GetRightClickAbility()override; Ability&GetAbility1()override; Ability&GetAbility2()override; @@ -478,7 +478,7 @@ struct Wizard:Player{ //Include only WIZARD-specific implementations! void OnUpdate(float fElapsedTime)override; static void InitializeClassAbilities(); - std::string GetClassName()override; + const std::string&GetClassName()override; Ability&GetRightClickAbility()override; Ability&GetAbility1()override; Ability&GetAbility2()override; @@ -509,7 +509,7 @@ struct Witch:Player{ //Include only WITCHs-specific implementations! void OnUpdate(float fElapsedTime)override; static void InitializeClassAbilities(); - std::string GetClassName()override; + const std::string&GetClassName()override; Ability&GetRightClickAbility()override; Ability&GetAbility1()override; Ability&GetAbility2()override; diff --git a/Adventures in Lestoria/RequiredMaterialsList.h b/Adventures in Lestoria/RequiredMaterialsList.h index fecbe09b..71699be2 100644 --- a/Adventures in Lestoria/RequiredMaterialsList.h +++ b/Adventures in Lestoria/RequiredMaterialsList.h @@ -71,9 +71,7 @@ protected: if(itemRef.lock()->EnhancementIsPossible()){ size_t enhancementIndex=itemRef.lock()->EnhancementLevel()+1; - if(Inventory::GetItemCount(itemRef.lock()->ActualName())==0){ //If we don't have the item, use the initial crafting list instead. - enhancementIndex=0; - } + if(itemRef.lock()->IsEquippable()&&Inventory::GetItemCount(itemRef.lock()->ActualName())==0)enhancementIndex=0;//If we don't have the item, use the initial crafting list instead. But only for equipment! float drawWidth=rect.size.x/3; int index=0; for(const auto&[name,amt]:itemRef.lock()->GetEnhancementInfo()[enhancementIndex].craftingRequirement.GetItems()){ diff --git a/Adventures in Lestoria/State_GameHub.cpp b/Adventures in Lestoria/State_GameHub.cpp index 98e93938..a992748b 100644 --- a/Adventures in Lestoria/State_GameHub.cpp +++ b/Adventures in Lestoria/State_GameHub.cpp @@ -43,6 +43,7 @@ All rights reserved. #include "VisualNovel.h" #include "State_OverworldMap.h" #include "GameEvent.h" +#include "SaveFile.h" INCLUDE_MONSTER_LIST INCLUDE_game @@ -51,9 +52,12 @@ void State_GameHub::OnStateChange(GameState*prevState){ if(Menu::IsMenuOpen()){ Menu::CloseAllMenus(); } + SaveFile::SaveGame(); + game->GetPlayer()->SetState(State::NORMAL); game->LoadLevel("HUB"); + game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName()); } void State_GameHub::OnUserUpdate(AiL*game){ State_GameRun::OnUserUpdate(game); diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index 5e1a87a7..3b2b562c 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -4,6 +4,7 @@ Settings Menu - Any settings should be saved to the save file! - Volume Controls - Play Sound in Background + - Keyboard aim assist (When playing w/keyboard, have the game auto fire for players that don't want to use mouse or cannot) - Key Configuration -Upon pressing a key, check if the key is bound to another option, if so, remove that bind from the list. Up to two keys may be binded per action. diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 3c71e7d2..4f9cd8a1 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 3 #define VERSION_PATCH 0 -#define VERSION_BUILD 6616 +#define VERSION_BUILD 6677 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/items/Weapons.txt b/Adventures in Lestoria/assets/config/items/Weapons.txt index ec1bba19..09e94707 100644 --- a/Adventures in Lestoria/assets/config/items/Weapons.txt +++ b/Adventures in Lestoria/assets/config/items/Weapons.txt @@ -1383,7 +1383,7 @@ Equipment Crafting { # When this crafting recipe is available. - AvailableChapter = 1 + AvailableChapter = 4 Item[0] = Wolf Skin,1 Gold = 5 diff --git a/Adventures in Lestoria/assets/config/items/items.txt b/Adventures in Lestoria/assets/config/items/items.txt index 9df79b19..5bf6e1e3 100644 --- a/Adventures in Lestoria/assets/config/items/items.txt +++ b/Adventures in Lestoria/assets/config/items/items.txt @@ -27,6 +27,11 @@ Item Missing Upgradeable Item Text = Missing Materials # Color of the text that displays when items can be upgraded in the Blacksmith but the player doesn't have enough material. Missing Upgradeable Item Text Color = 192,0,0,255 + + # The names of items to be sorted for equipment lists. + Equipment Sort Order Primary = Wooden, Leather, Steel, Copper, Shell, Bone, Laser, Plasma, Unknown + # The types of the items to be sorted for equipment lists if they have the same primary type. + Equipment Sort Order Secondary = Helmet, Armor, Pants, Gloves, Shoes, Sword, Bow, Staff } ItemDrop { diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 220fc908..622d3117 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ