Implemented locking of accessories in the inventory and merchant window to prevent immediate selling of an item. Fixed a bug that prevented custom menu actions to be performed on the menu select button when a button was clicked. Release Build 7966. Patch Version 0.4.5.

mac-build
sigonasr2 9 months ago
parent 7ce1e37549
commit 2c81cf15f2
  1. 37
      Adventures in Lestoria/AccessoryRowItemDisplay.h
  2. 40
      Adventures in Lestoria/InventoryWindow.cpp
  3. 11
      Adventures in Lestoria/Item.cpp
  4. 4
      Adventures in Lestoria/Item.h
  5. 4
      Adventures in Lestoria/Menu.cpp
  6. 4
      Adventures in Lestoria/MenuComponent.cpp
  7. 3
      Adventures in Lestoria/MenuComponent.h
  8. 25
      Adventures in Lestoria/MerchantWindow.cpp
  9. 8
      Adventures in Lestoria/SaveFile.cpp
  10. 5
      Adventures in Lestoria/ScrollableWindowComponent.h
  11. 2
      Adventures in Lestoria/TODO.txt
  12. 4
      Adventures in Lestoria/Version.h
  13. 10
      Adventures in Lestoria/assets/config/audio/events.txt
  14. 2
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  15. BIN
      Adventures in Lestoria/assets/gamepack.pak
  16. BIN
      Adventures in Lestoria/assets/lock.png
  17. BIN
      Adventures in Lestoria/assets/unlock.png
  18. BIN
      x64/Release/Adventures in Lestoria.exe

@ -37,12 +37,14 @@ All rights reserved.
#pragma endregion
#pragma once
#include "RowItemDisplay.h"
#include "SoundEffect.h"
#include "MenuIconButton.h"
INCLUDE_game
INCLUDE_GFX
class AccessoryRowItemDisplay:public RowItemDisplay{
std::weak_ptr<MenuComponent>lockButton;
std::weak_ptr<MenuIconButton>lockButton;
public:
inline AccessoryRowItemDisplay(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName,ButtonAttr attributes=ButtonAttr::NONE)
:RowItemDisplay(rect,itemRef,onClick,itemNameLabelName,itemDescriptionLabelName,attributes){}
@ -54,9 +56,38 @@ public:
lockButton.reset();
}
}
virtual inline void AfterCreate()override final{
lockButton=parentComponent.lock()->ADDSUB(std::format("{}_lock",name),MenuComponent)(geom2d::rect<float>{rect.pos,vf2d{16.f,8.f}},"Lock",[](MenuFuncData data){
inline void AfterCreate()override final{
lockButton=parentComponent.lock()->ADDSUB(std::format("{}_lock",name),MenuIconButton)(geom2d::rect<float>{rect.pos+vf2d{rect.size.x-10.f,rect.size.y-10.f},vf2d{10.f,10.f}},GFX["unlock.png"].Decal(),[](MenuFuncData data){
std::weak_ptr<AccessoryRowItemDisplay>accessoryParent=DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.component.lock()->GetSubcomponentParent());
accessoryParent.lock()->SetLocked(!accessoryParent.lock()->IsLocked());
if(accessoryParent.lock()->IsLocked()){
SoundEffect::PlaySFX("Lock Accessory",SoundEffect::CENTERED);
}else{
SoundEffect::PlaySFX("Unlock Accessory",SoundEffect::CENTERED);
}
std::weak_ptr<MenuIconButton>lockButton=DYNAMIC_POINTER_CAST<MenuIconButton>(data.component.lock());
return true;
})END;
}
inline void Update(AiL*game)override final{
MenuComponent::Update(game);
if(itemRef.lock()->IsLocked()){
lockButton.lock()->SetIcon(GFX["lock.png"].Decal());
}else{
lockButton.lock()->SetIcon(GFX["unlock.png"].Decal());
}
}
inline const bool IsLocked()const{
return itemRef.lock()->IsLocked();
}
inline void SetLocked(const bool locked){
if(locked){
itemRef.lock()->Lock();
}else{
itemRef.lock()->Unlock();
}
}
inline const std::weak_ptr<MenuIconButton>GetLockButton()const{
return lockButton;
}
};

@ -46,6 +46,7 @@ All rights reserved.
#include "RowItemDisplay.h"
#include "PlayerMoneyLabel.h"
#include "SoundEffect.h"
#include "AccessoryRowItemDisplay.h"
INCLUDE_game
INCLUDE_ITEM_CATEGORIES
@ -202,7 +203,44 @@ void Menu::InitializeInventoryWindow(){
}
}}},
{{game->KEY_SCROLL,Pressed},{"Navigate",[](MenuType type){}}},
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
{game->KEY_CONFIRM,{[](MenuFuncData data){
if(!data.menu.GetSelection().expired()&&
!data.menu.GetSelection().lock()->parentComponent.expired()&&
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"){
if(DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.menu.GetSelection().lock())->GetItem().lock()->IsLocked()){
return "Unlock";
}else{
return "Lock";
}
}
return "Select";
},[](MenuType type){
if(!Menu::menus[type]->GetSelection().expired()&&
!Menu::menus[type]->GetSelection().lock()->parentComponent.expired()&&
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"
&&Menu::menus[type]->GetSelection().lock()->GetSubcomponentParent().expired()){
DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(Menu::menus[type]->GetSelection().lock())->GetLockButton().lock()->Click();
}
}}},
{game->KEY_SELECT,{[](MenuFuncData data){
if(!data.menu.GetSelection().expired()&&
!data.menu.GetSelection().lock()->parentComponent.expired()&&
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"){
if(DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.menu.GetSelection().lock())->GetItem().lock()->IsLocked()){
return "Unlock";
}else{
return "Lock";
}
}
return "";
},[](MenuType type){
if(!Menu::menus[type]->GetSelection().expired()&&
!Menu::menus[type]->GetSelection().lock()->parentComponent.expired()&&
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"
&&Menu::menus[type]->GetSelection().lock()->GetSubcomponentParent().expired()){
DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(Menu::menus[type]->GetSelection().lock())->GetLockButton().lock()->Click();
}
}}},
}
,{ //Button Navigation Rules
{"Back Button",{

@ -1263,3 +1263,14 @@ void Inventory::GivePlayerLoadoutItemsUsed(){
}
ResetLoadoutItemsUsed();
}
const bool Item::IsLocked()const{
return locked;
}
void Item::Lock(){
locked=true;
}
void Item::Unlock(){
locked=false;
}

@ -174,6 +174,7 @@ private:
uint8_t enhancementLevel;
ItemInfo*it;
Stats randomizedStats;
bool locked=false;
void SetAmt(uint32_t newAmt);
static ItemEnhancementFunctionPrimingData enhanceFunctionPrimed;
@ -227,6 +228,9 @@ public:
static bool IsBlank(std::shared_ptr<Item>item);
//Use ISBLANK macro instead!! This should not be called directly!!
static bool IsBlank(std::weak_ptr<Item>item);
const bool IsLocked()const;
void Lock();
void Unlock();
friend const bool operator==(std::shared_ptr<Item>lhs,std::shared_ptr<Item>rhs){return lhs->it==rhs->it&&lhs->randomizedStats==rhs->randomizedStats;};
friend const bool operator==(std::shared_ptr<Item>lhs,const IT&rhs){return lhs->ActualName()==const_cast<IT&>(rhs);};
friend const bool operator==(std::weak_ptr<Item>lhs,std::weak_ptr<Item>rhs){return !lhs.expired()&&!rhs.expired()&&lhs.lock()->it==rhs.lock()->it&&lhs.lock()->randomizedStats==rhs.lock()->randomizedStats;};

@ -140,8 +140,10 @@ Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){
void Menu::CheckClickAndPerformMenuSelect(AiL*game){
if(game->KEY_CONFIRM.Released()&&!Menu::alreadyClicked&&(MOUSE_NAVIGATION||(!MOUSE_NAVIGATION&&!game->GetMouse(Mouse::LEFT).bReleased&&!game->GetMouse(Mouse::RIGHT).bReleased&&!game->GetMouse(Mouse::MIDDLE).bReleased))){
if(!GetSelection().expired()){ //If we are on controller/gamepad it's possible we haven't highlighted a button yet, so don't click this button right away.
Menu*prevMenu=Menu::IsMenuOpen()?Menu::stack.back():nullptr;
MenuSelect(game);
Menu::alreadyClicked=true;
Menu*currentMenu=Menu::IsMenuOpen()?Menu::stack.back():nullptr;
if(prevMenu!=currentMenu)Menu::alreadyClicked=true; //The logic here is that only when we navigate between menus do we care about setting the already clicked flag to prevent further clicks going into the new screen. If we're still on the same menu, then we will proceed with regular inputs.
}
}
}

@ -282,3 +282,7 @@ const bool MenuComponent::IsEnabledOutsideWindow()const{
const bool MenuComponent::IsDisabledOutsideWindow()const{
return disableOutsideWindow;
}
const std::weak_ptr<MenuComponent>MenuComponent::GetSubcomponentParent()const{
return subcomponentParent;
}

@ -98,6 +98,8 @@ private:
bool disableOutsideWindow=false; //If set to true, this component was automatically set to not be renderable outside the window.
bool disable=false; //If set to true, this component will not be rendered or updated.
std::string label="";
std::weak_ptr<MenuComponent>subcomponentParent; //For subcomponents, this value provides the actual component this subcomponent was spawned from.
protected:
int depth=0;
float hoverEffect=0;
@ -168,4 +170,5 @@ public:
virtual void OnChapterUpdate(uint8_t newChapter);
virtual void Click();
virtual void SetLabel(std::string newLabel);
const std::weak_ptr<MenuComponent>GetSubcomponentParent()const;
};

@ -38,6 +38,7 @@ All rights reserved.
#include "Menu.h"
#include "AdventuresInLestoria.h"
#include "AccessoryRowItemDisplay.h"
#include "RowInventoryScrollableWindowComponent.h"
#include "MenuItemItemButton.h"
#include "MenuComponent.h"
@ -177,6 +178,10 @@ void Menu::InitializeMerchantWindow(){
auto inventoryDisplay=merchantWindow->ADD("Inventory Display - "+category,RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{72,28},{150,merchantWindow->size.y-44}},"Item Name Label","Item Description Label",
[](MenuFuncData data){
std::weak_ptr<RowItemDisplay>item=DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component.lock());
if(item.lock()->GetItem().lock()->IsLocked()){
SoundEffect::PlaySFX("Locked Item",SoundEffect::CENTERED);
return true;
}
if(item.lock()->GetItem().lock()->CanBeSold()){
Component<ItemMenuLabel>(SELL_ITEM,"Item Sell Header")->SetItem(item.lock()->GetItem());
Component<MenuLabel>(SELL_ITEM,"Price per item Amount Label")->SetLabel(std::to_string(item.lock()->GetItem().lock()->SellValue()));
@ -330,6 +335,26 @@ void Menu::InitializeMerchantWindow(){
}}},
{{game->KEY_SCROLL,Pressed},{"Navigate",[](MenuType type){}}},
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
{game->KEY_SELECT,{[](MenuFuncData data){
/* //Too wordy, let's leave it out for now.
if(!data.menu.GetSelection().expired()&&
!data.menu.GetSelection().lock()->parentComponent.expired()&&
data.menu.GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"){
if(DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(data.menu.GetSelection().lock())->GetItem().lock()->IsLocked()){
return "Unlock";
}else{
return "Lock";
}
}*/
return "";
},[](MenuType type){
if(!Menu::menus[type]->GetSelection().expired()&&
!Menu::menus[type]->GetSelection().lock()->parentComponent.expired()&&
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->GetName()=="Inventory Display - Accessories"
&&Menu::menus[type]->GetSelection().lock()->GetSubcomponentParent().expired()){
DYNAMIC_POINTER_CAST<AccessoryRowItemDisplay>(Menu::menus[type]->GetSelection().lock())->GetLockButton().lock()->Click();
}
}}},
}
,{ //Button Navigation Rules
{"Leave Button",{

@ -92,6 +92,7 @@ const void SaveFile::SaveGame(){
saveFile["Items"][std::format("Item[{}]",itemCount)]["Enhancement Level"].SetInt(item->EnhancementLevel());
saveFile["Items"][std::format("Item[{}]",itemCount)]["Item Name"].SetString(item->ActualName());
saveFile["Items"][std::format("Item[{}]",itemCount)]["Equip Slot"].SetInt(int(Inventory::GetSlotEquippedIn(item)));
saveFile["Items"][std::format("Item[{}]",itemCount)]["Locked"].SetBool(item->IsLocked());
uint8_t loadoutSlotNumber=255;
for(int i=0;i<game->loadout.size();i++){
if(item==game->GetLoadoutItem(i)){loadoutSlotNumber=i;break;}
@ -295,6 +296,13 @@ void SaveFile::LoadFile(){
if(slot!=EquipSlot::NONE){ //This should be equipped somewhere!
Inventory::EquipItem(newItem,slot);
}
if(loadFile.GetProperty(std::format("Items.{}",key)).HasProperty("Locked")){
bool locked=loadFile.GetProperty(std::format("Items.{}",key))["Locked"].GetBool();
if(locked){
newItem.lock()->Lock();
}
}
}
game->ChangePlayerClass(classutils::StringToClass(loadFile["Player"]["Class"].GetString()));
game->GetPlayer()->SetLevel(loadFile["Player"]["Level"].GetInt());

@ -42,7 +42,7 @@ All rights reserved.
using A=Attribute;
#define ADDSUB(key,componentType) _AddSubcomponent<componentType>(key,std::make_shared<componentType>
#define ADDSUB(key,componentType) _AddSubcomponent<componentType>(name,key,std::make_shared<componentType>
INCLUDE_game
@ -364,7 +364,7 @@ public:
}
public:
template<class T>
std::shared_ptr<T> _AddSubcomponent(std::string key,std::shared_ptr<T>button){
std::shared_ptr<T> _AddSubcomponent(std::string parentKey,std::string key,std::shared_ptr<T>button){
if(Menu::menus[parentMenu]->components.count(key)){
ERR("WARNING! Key "<<key<<" for menu"<<parentMenu<<" already exists! Key names must be unique!")
}
@ -377,6 +377,7 @@ public:
CalculateBounds();
Menu::menus[parentMenu]->_AddComponent(key,button);
button->subcomponentParent=Menu::menus[parentMenu]->components.at(parentKey);
return button;
}
template<class T>

@ -8,8 +8,6 @@ Materials for initial craft seems to be wrong? need to recheck
do we need a minimap? (maybe with fog of war?) Maybe polling that once testing with more people.
should gemstones dropp from boss stages aswell? (Maybe lower droprate?)
feature to lock accesoires to protect them from selling would be nice
When opening craft/buy/sell menu, default to the appropriate button.
Pressing back on the Select button of the equip menu causes you to exit the menu.
Funny text colors with text color override on blacksmith menu

@ -38,8 +38,8 @@ All rights reserved.
#pragma once
#define VERSION_MAJOR 0
#define VERSION_MINOR 4
#define VERSION_PATCH 4
#define VERSION_BUILD 7947
#define VERSION_PATCH 5
#define VERSION_BUILD 7966
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -79,6 +79,16 @@ Events
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = item_sell.ogg, 80%
}
Lock Accessory
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = button_click2.ogg, 40%
}
Unlock Accessory
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = button_click2.ogg, 60%, 50%, 60%
}
Locked Item
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)

@ -79,6 +79,8 @@ Images
GFX_Ursule2 = monsters/Ursule Mother of Bears2.png
GFX_Wisp = wisp.png
GFX_XPBar = xpbar.png
GFX_Lock = lock.png
GFX_Unlock = unlock.png
# Ability Icons
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Loading…
Cancel
Save