Added XP bar animations and steady increasing progress bar. Added level up animation text on stage completion screen. Refactor enable and disable functions for menu components. Differentiated between disabling due to being outside the window, and manual enable/disabling of components. Fix infinite loop bug with components outside of a scrollable window component not being iterated over. Fix bug with hovering over non-navigational components causing the default component for a menu to be selected while in mouse navigation mode. Release Build 7095.

pull/35/head
sigonasr2 12 months ago
parent 22b1557c05
commit 8afd66632a
  1. 3
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 10
      Adventures in Lestoria/BlacksmithCraftingWindow.cpp
  3. 44
      Adventures in Lestoria/CharacterMenuWindow.cpp
  4. 4
      Adventures in Lestoria/ClassSelectionWindow.cpp
  5. 6
      Adventures in Lestoria/DynamicCounter.cpp
  6. 4
      Adventures in Lestoria/GameState.cpp
  7. 1
      Adventures in Lestoria/GameState.h
  8. 8
      Adventures in Lestoria/InventoryWindow.cpp
  9. 12
      Adventures in Lestoria/LevelCompleteWindow.cpp
  10. 4
      Adventures in Lestoria/LoadGameWindow.cpp
  11. 23
      Adventures in Lestoria/Menu.cpp
  12. 36
      Adventures in Lestoria/MenuComponent.cpp
  13. 12
      Adventures in Lestoria/MenuComponent.h
  14. 8
      Adventures in Lestoria/MenuItemButton.h
  15. 8
      Adventures in Lestoria/MenuItemItemButton.h
  16. 28
      Adventures in Lestoria/MerchantWindow.cpp
  17. 2
      Adventures in Lestoria/Player.cpp
  18. 8
      Adventures in Lestoria/RowItemDisplay.h
  19. 50
      Adventures in Lestoria/ScrollableWindowComponent.h
  20. 2
      Adventures in Lestoria/Slider.h
  21. 37
      Adventures in Lestoria/State_LevelComplete.cpp
  22. 5
      Adventures in Lestoria/State_LevelComplete.h
  23. 18
      Adventures in Lestoria/State_OverworldMap.cpp
  24. 2
      Adventures in Lestoria/Version.h
  25. 2
      Adventures in Lestoria/assets/Campaigns/1_B1.tmx
  26. 6
      Adventures in Lestoria/assets/config/Interface.txt
  27. 5
      Adventures in Lestoria/assets/config/audio/events.txt
  28. BIN
      Adventures in Lestoria/assets/sounds/levelup.ogg
  29. BIN
      x64/Release/Adventures in Lestoria.exe

@ -304,6 +304,7 @@ bool AiL::OnUserUpdate(float fElapsedTime){
RenderWorld(GetElapsedTime()); RenderWorld(GetElapsedTime());
GameState::STATE->Draw(this); GameState::STATE->Draw(this);
RenderMenu(); RenderMenu();
GameState::STATE->DrawOverlay(this);
RenderFadeout(); RenderFadeout();
RenderVersionInfo(); RenderVersionInfo();
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
@ -3053,7 +3054,7 @@ void AiL::UpdateDiscordStatus(std::string levelName,std::string className){
if(levelName!="Main Menu"){ if(levelName!="Main Menu"){
newActivity.SetState(std::format("Level {} {}",player->Level(),className).c_str()); newActivity.SetState(std::format("Level {} {}",player->Level(),className).c_str());
assets.SetSmallText(std::format("Level {} {}",player->Level(),className).c_str()); assets.SetSmallText(std::format("{} the {}",SaveFile::GetSaveFileName(),className).c_str());
std::for_each(className.begin(),className.end(),[](char&c){c=std::tolower(c);}); std::for_each(className.begin(),className.end(),[](char&c){c=std::tolower(c);});
assets.SetSmallImage(("nico-"+className+"_512").c_str()); assets.SetSmallImage(("nico-"+className+"_512").c_str());
} }

@ -74,8 +74,8 @@ void Menu::InitializeBlacksmithCraftingWindow(){
auto weaponTab=blacksmithWindow->ADD("Weapon Tab",MenuComponent)(geom2d::rect<float>{{2,0},{blacksmithWindow->size.x/2-4,24}},"Weapon",[](MenuFuncData data){ auto weaponTab=blacksmithWindow->ADD("Weapon Tab",MenuComponent)(geom2d::rect<float>{{2,0},{blacksmithWindow->size.x/2-4,24}},"Weapon",[](MenuFuncData data){
Component<MenuComponent>(BLACKSMITH,"Armor Tab")->selected=false; Component<MenuComponent>(BLACKSMITH,"Armor Tab")->selected=false;
Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Weapon Inventory Display")->Enable(true); Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Weapon Inventory Display")->Enable();
Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Armor Inventory Display")->Enable(false); Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Armor Inventory Display")->Disable();
data.component.lock()->selected=true; data.component.lock()->selected=true;
return true; return true;
})END; })END;
@ -83,8 +83,8 @@ void Menu::InitializeBlacksmithCraftingWindow(){
weaponTab->selectionType=SelectionType::HIGHLIGHT; weaponTab->selectionType=SelectionType::HIGHLIGHT;
auto armorTab=blacksmithWindow->ADD("Armor Tab",MenuComponent)(geom2d::rect<float>{{blacksmithWindow->size.x/2+2,0},{blacksmithWindow->size.x/2-4,24}},"Armor",[](MenuFuncData data){ auto armorTab=blacksmithWindow->ADD("Armor Tab",MenuComponent)(geom2d::rect<float>{{blacksmithWindow->size.x/2+2,0},{blacksmithWindow->size.x/2-4,24}},"Armor",[](MenuFuncData data){
Component<MenuComponent>(BLACKSMITH,"Weapon Tab")->selected=false; Component<MenuComponent>(BLACKSMITH,"Weapon Tab")->selected=false;
Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Weapon Inventory Display")->Enable(false); Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Weapon Inventory Display")->Disable();
Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Armor Inventory Display")->Enable(true); Component<RowInventoryScrollableWindowComponent>(BLACKSMITH,"Armor Inventory Display")->Enable();
data.component.lock()->selected=true; data.component.lock()->selected=true;
return true; return true;
})END; })END;
@ -175,7 +175,7 @@ void Menu::InitializeBlacksmithCraftingWindow(){
InventoryCreator::RowPlayerArmor_InventoryUpdate, InventoryCreator::RowPlayerArmor_InventoryUpdate,
InventoryWindowOptions{.padding=1,.size={207,28}} InventoryWindowOptions{.padding=1,.size={207,28}}
)END; )END;
armorDisplay->Enable(false); armorDisplay->Disable();
armorDisplay->SetCompactDescriptions(CRAFTING_INFO); armorDisplay->SetCompactDescriptions(CRAFTING_INFO);
#pragma endregion #pragma endregion

@ -78,18 +78,18 @@ void Menu::InitializeCharacterMenuWindow(){
characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)(geom2d::rect<float>{{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)(geom2d::rect<float>{{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
->Enable(false); ->Disable();
characterMenuWindow->ADD("Equip List",ScrollableWindowComponent)(geom2d::rect<float>{{123,28},{120,windowSize.y-37-24}})DEPTH -1 END characterMenuWindow->ADD("Equip List",ScrollableWindowComponent)(geom2d::rect<float>{{123,28},{120,windowSize.y-37-24}})DEPTH -1 END
->Enable(false); ->Disable();
characterMenuWindow->ADD("Equip Selection Bottom Outline",MenuComponent)(geom2d::rect<float>{{123,28+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END characterMenuWindow->ADD("Equip Selection Bottom Outline",MenuComponent)(geom2d::rect<float>{{123,28+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
->Enable(false); ->Disable();
auto equipSelectionSelectButton=characterMenuWindow->ADD("Equip Selection Select Button",MenuComponent)(geom2d::rect<float>{{123+12,28+(windowSize.y-37-24)+6},{96,12}},"Select", auto equipSelectionSelectButton=characterMenuWindow->ADD("Equip Selection Select Button",MenuComponent)(geom2d::rect<float>{{123+12,28+(windowSize.y-37-24)+6},{96,12}},"Select",
[](MenuFuncData data){ [](MenuFuncData data){
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Outline")->Enable(false); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Outline")->Disable();
Component<ScrollableWindowComponent>(data.component.lock()->parentMenu,"Equip List")->Enable(false); Component<ScrollableWindowComponent>(data.component.lock()->parentMenu,"Equip List")->Disable();
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Bottom Outline")->Enable(false); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Bottom Outline")->Disable();
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Select Button")->Enable(false); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Select Button")->Disable();
Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Enable(true); Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Enable();
for(int counter=0;const std::string&attribute:displayAttrs){ for(int counter=0;const std::string&attribute:displayAttrs){
std::weak_ptr<StatLabel>statDisplayLabel=Component<StatLabel>(CHARACTER_MENU,"Attribute "+std::string(ItemAttribute::Get(attribute).Name())+" Label"); std::weak_ptr<StatLabel>statDisplayLabel=Component<StatLabel>(CHARACTER_MENU,"Attribute "+std::string(ItemAttribute::Get(attribute).Name())+" Label");
statDisplayLabel.lock()->SetStatChangeAmt(0); statDisplayLabel.lock()->SetStatChangeAmt(0);
@ -98,7 +98,7 @@ void Menu::InitializeCharacterMenuWindow(){
return true; return true;
})DEPTH 0 END; })DEPTH 0 END;
equipSelectionSelectButton->Enable(false); equipSelectionSelectButton->Disable();
const static auto GetLabelText=[](ItemAttribute attribute){ const static auto GetLabelText=[](ItemAttribute attribute){
std::string attrStr=std::string(attribute.Name())+":\n "; std::string attrStr=std::string(attribute.Name())+":\n ";
@ -233,26 +233,26 @@ void Menu::InitializeCharacterMenuWindow(){
counter++; counter++;
} }
equipList->I(Attribute::INDEXED_THEME)=data.component.lock()->I(Attribute::INDEXED_THEME); equipList->I(Attribute::INDEXED_THEME)=data.component.lock()->I(Attribute::INDEXED_THEME);
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Outline")->Enable(true); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Outline")->Enable();
equipList->Enable(true); equipList->Enable();
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Bottom Outline")->Enable(true); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Bottom Outline")->Enable();
Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Select Button")->Enable(true); Component<MenuComponent>(data.component.lock()->parentMenu,"Equip Selection Select Button")->Enable();
Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Enable(false); Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Disable();
equipmentWindowOpened=true; equipmentWindowOpened=true;
return true; return true;
},[](MenuFuncData data){//On Mouse Hover },[](MenuFuncData data){//On Mouse Hover
EquipSlot slot=DYNAMIC_POINTER_CAST<EquipSlotButton>(data.component.lock())->GetSlot(); EquipSlot slot=DYNAMIC_POINTER_CAST<EquipSlotButton>(data.component.lock())->GetSlot();
const std::weak_ptr<Item>equip=Inventory::GetEquip(slot); const std::weak_ptr<Item>equip=Inventory::GetEquip(slot);
if(!ISBLANK(equip)){ if(!ISBLANK(equip)){
Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Enable(false); Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Disable();
} }
return true; return true;
},[](MenuFuncData data){//On Mouse Out },[](MenuFuncData data){//On Mouse Out
if(!equipmentWindowOpened){ if(!equipmentWindowOpened){
Component<MenuLabel>(data.component.lock()->parentMenu,"Item Equip Description")->SetLabel(""); Component<MenuLabel>(data.component.lock()->parentMenu,"Item Equip Description")->SetLabel("");
Component<MenuLabel>(data.component.lock()->parentMenu,"Item Equip Name")->Enable(false); Component<MenuLabel>(data.component.lock()->parentMenu,"Item Equip Name")->Disable();
Component<MenuLabel>(data.component.lock()->parentMenu,"Item Equip Description")->Enable(false); Component<MenuLabel>(data.component.lock()->parentMenu,"Item Equip Description")->Disable();
Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Enable(true); Component<CharacterRotatingDisplay>(data.component.lock()->parentMenu,"Character Rotating Display")->Enable();
} }
return true; return true;
},"Item Equip Name","Item Equip Description")END; },"Item Equip Name","Item Equip Description")END;
@ -283,8 +283,8 @@ void Menu::InitializeCharacterMenuWindow(){
auto itemEquipNameDisplay=characterMenuWindow->ADD("Item Equip Name",MenuLabel)(geom2d::rect<float>{{123,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::FIT_TO_LABEL)END; auto itemEquipNameDisplay=characterMenuWindow->ADD("Item Equip Name",MenuLabel)(geom2d::rect<float>{{123,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::FIT_TO_LABEL)END;
auto itemEquipDescriptionDisplay=characterMenuWindow->ADD("Item Equip Description",MenuLabel)(geom2d::rect<float>{{123,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END; auto itemEquipDescriptionDisplay=characterMenuWindow->ADD("Item Equip Description",MenuLabel)(geom2d::rect<float>{{123,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
itemNameDisplay->Enable(false); itemNameDisplay->Disable();
itemDescriptionDisplay->Enable(false); itemDescriptionDisplay->Disable();
itemEquipNameDisplay->Enable(false); itemEquipNameDisplay->Disable();
itemEquipDescriptionDisplay->Enable(false); itemEquipDescriptionDisplay->Disable();
} }

@ -92,7 +92,7 @@ void Menu::InitializeClassSelectionWindow(){
#endif #endif
return true; return true;
})END })END
->disabled=true; ->Disable();
vf2d buttonPadding={2,2}; vf2d buttonPadding={2,2};
vf2d buttonSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/9-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug. vf2d buttonSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/9-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug.
@ -146,7 +146,7 @@ void Menu::InitializeClassSelectionWindow(){
classSelectionWindow->ADD(className+" Label",MenuLabel)(geom2d::rect<float>{backgroundOffsetPos,buttonSize},className,1,ComponentAttr::SHADOW)END; classSelectionWindow->ADD(className+" Label",MenuLabel)(geom2d::rect<float>{backgroundOffsetPos,buttonSize},className,1,ComponentAttr::SHADOW)END;
auto classSprite=classSelectionWindow->ADD(className+" Icon",MenuAnimatedIconToggleButton)(geom2d::rect<float>{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){ auto classSprite=classSelectionWindow->ADD(className+" Icon",MenuAnimatedIconToggleButton)(geom2d::rect<float>{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){
data.menu.components["Confirm"]->Enable(true); data.menu.components["Confirm"]->Enable();
data.menu.components["Confirm"]->S(A::CLASS_SELECTION)=data.component.lock()->S(A::CLASS_SELECTION); data.menu.components["Confirm"]->S(A::CLASS_SELECTION)=data.component.lock()->S(A::CLASS_SELECTION);
return true; return true;
})END; })END;

@ -66,14 +66,16 @@ void DynamicCounter::Update(){
tickTimer-=tickRate; tickTimer-=tickRate;
if(displayNumber!=int(*targetNumber)){ if(displayNumber!=int(*targetNumber)){
if(displayNumber>int(*targetNumber)){ if(displayNumber>int(*targetNumber)){
displayNumber--; int incrementAmt=int(abs(*targetNumber-displayNumber)/(1/tickRate))+1;
displayNumber=std::max(displayNumber-incrementAmt,*targetNumber);
if(targetNumberChanged){ if(targetNumberChanged){
adjustedCol=decreaseCol; adjustedCol=decreaseCol;
targetChangedTimer=colorChangeTime; targetChangedTimer=colorChangeTime;
} }
}else{ }else{
displayNumber++; int incrementAmt=int(abs(*targetNumber-displayNumber)/(1/tickRate))+1;
displayNumber=std::min(displayNumber+incrementAmt,*targetNumber);
if(targetNumberChanged){ if(targetNumberChanged){
adjustedCol=increaseCol; adjustedCol=increaseCol;

@ -82,4 +82,6 @@ GameState::~GameState(){}
void GameState::GetAnyKeyPress(Key k){} void GameState::GetAnyKeyPress(Key k){}
void GameState::GetAnyKeyRelease(Key k){} void GameState::GetAnyKeyRelease(Key k){}
void GameState::GetAnyMousePress(int32_t mouseButton){} void GameState::GetAnyMousePress(int32_t mouseButton){}
void GameState::GetAnyMouseRelease(int32_t mouseButton){} void GameState::GetAnyMouseRelease(int32_t mouseButton){}
void GameState::DrawOverlay(AiL*game){};

@ -67,6 +67,7 @@ public:
virtual void OnStateChange(GameState*prevState)=0; virtual void OnStateChange(GameState*prevState)=0;
virtual void OnUserUpdate(AiL*game)=0; virtual void OnUserUpdate(AiL*game)=0;
virtual void Draw(AiL*game)=0; virtual void Draw(AiL*game)=0;
virtual void DrawOverlay(AiL*game);
virtual void GetAnyKeyPress(Key k); virtual void GetAnyKeyPress(Key k);
virtual void GetAnyKeyRelease(Key k); virtual void GetAnyKeyRelease(Key k);
virtual void GetAnyMousePress(int32_t mouseButton); virtual void GetAnyMousePress(int32_t mouseButton);

@ -78,9 +78,9 @@ void Menu::InitializeInventoryWindow(){
auto button=inventoryWindow->ADD(category+" Inventory Tab",MenuComponent)(geom2d::rect<float>{{2,30+yOffset},{68,16}},category,MenuType::ENUM_END, auto button=inventoryWindow->ADD(category+" Inventory Tab",MenuComponent)(geom2d::rect<float>{{2,30+yOffset},{68,16}},category,MenuType::ENUM_END,
[&](MenuFuncData data){ [&](MenuFuncData data){
//Close the old inventory window and show the proper one. //Close the old inventory window and show the proper one.
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Enable(false); Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Disable();
Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->SetSelected(false); Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->SetSelected(false);
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.component.lock()->S(A::CATEGORY_NAME))->Enable(true); Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.component.lock()->S(A::CATEGORY_NAME))->Enable();
Component<MenuComponent>(data.menu.GetType(),data.component.lock()->S(A::CATEGORY_NAME)+" Inventory Tab")->SetSelected(true); Component<MenuComponent>(data.menu.GetType(),data.component.lock()->S(A::CATEGORY_NAME)+" Inventory Tab")->SetSelected(true);
data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)=data.component.lock()->S(A::CATEGORY_NAME); data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)=data.component.lock()->S(A::CATEGORY_NAME);
return true; return true;
@ -103,10 +103,12 @@ void Menu::InitializeInventoryWindow(){
if(first){ if(first){
inventoryWindow->S(A::LAST_INVENTORY_TYPE_OPENED)=category; inventoryWindow->S(A::LAST_INVENTORY_TYPE_OPENED)=category;
button->onClick(MenuFuncData{*inventoryWindow,game,button}); //Simulate a click of this button if it's the top one for an initial inventory display. button->onClick(MenuFuncData{*inventoryWindow,game,button}); //Simulate a click of this button if it's the top one for an initial inventory display.
inventoryDisplay->Enable();
}else{
inventoryDisplay->Disable();
} }
Menu::AddInventoryListener(inventoryDisplay,category); Menu::AddInventoryListener(inventoryDisplay,category);
inventoryDisplay->Enable(first);
inventoryDisplay->SetCompactDescriptions(NON_COMPACT); inventoryDisplay->SetCompactDescriptions(NON_COMPACT);
yOffset+=20; yOffset+=20;

@ -115,7 +115,9 @@ void Menu::InitializeLevelCompleteWindow(){
} }
}}}, }}},
{game->KEY_SCROLL,{"View Items",[](MenuType type){}}}, {game->KEY_SCROLL,{"View Items",[](MenuType type){}}},
{game->KEY_START,{"Continue",[](MenuType type){}}}, {game->KEY_START,{"Continue",[](MenuType type){
Component<MenuComponent>(type,"Next Button")->Click();
}}},
} }
,{ //Button Navigation Rules ,{ //Button Navigation Rules
{"Monster Loot Window",{ {"Monster Loot Window",{
@ -152,7 +154,7 @@ void Menu::InitializeLevelCompleteWindow(){
DetectInventory(InventoryScrollableWindowComponent,type,"Monster Loot Window") DetectInventory(InventoryScrollableWindowComponent,type,"Monster Loot Window")
{ //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory. { //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory.
//By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping. //By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping.
int colIndex=(newRowIndex+invWidth)%invWidth; //Negative index, so we have to loop around. int colIndex=selectedButton.lock()->inventoryIndex; //Negative index, so we have to loop around.
//Get the base row index of the new inventory. //Get the base row index of the new inventory.
auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Stage Loot Window"); auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Stage Loot Window");
if(stageLootWindow->GetComponents().size()>0){ if(stageLootWindow->GetComponents().size()>0){
@ -205,7 +207,7 @@ void Menu::InitializeLevelCompleteWindow(){
DetectInventory(InventoryScrollableWindowComponent,type,"Monster Loot Window") DetectInventory(InventoryScrollableWindowComponent,type,"Monster Loot Window")
{ //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory. { //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory.
//By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping. //By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping.
int colIndex=newRowIndex%invWidth; int colIndex=selectedButton.lock()->inventoryIndex;
//Get the base row index of the new inventory. //Get the base row index of the new inventory.
auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Stage Loot Window"); auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Stage Loot Window");
if(stageLootWindow->GetComponents().size()>0){ if(stageLootWindow->GetComponents().size()>0){
@ -336,7 +338,7 @@ void Menu::InitializeLevelCompleteWindow(){
DetectInventory(InventoryScrollableWindowComponent,type,"Stage Loot Window") DetectInventory(InventoryScrollableWindowComponent,type,"Stage Loot Window")
{ //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory. { //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory.
//By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping. //By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping.
int colIndex=(newRowIndex+invWidth)%invWidth; int colIndex=selectedButton.lock()->inventoryIndex;
//Get the base row index of the new inventory. //Get the base row index of the new inventory.
auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Monster Loot Window"); auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Monster Loot Window");
if(stageLootWindow->GetComponents().size()>0){ if(stageLootWindow->GetComponents().size()>0){
@ -389,7 +391,7 @@ void Menu::InitializeLevelCompleteWindow(){
DetectInventory(InventoryScrollableWindowComponent,type,"Stage Loot Window") DetectInventory(InventoryScrollableWindowComponent,type,"Stage Loot Window")
{ //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory. { //This means we have to wrap around. We have access to itemsList if we needed to point to a specific item in the inventory.
//By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping. //By returning here, you are processing returnData yourself. Otherwise manipulate newRowIndex to point to an item in the itemsList when wrapping.
int colIndex=newRowIndex%invWidth; int colIndex=selectedButton.lock()->inventoryIndex;
//Get the base row index of the new inventory. //Get the base row index of the new inventory.
auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Monster Loot Window"); auto stageLootWindow=Component<InventoryScrollableWindowComponent>(type,"Monster Loot Window");
if(stageLootWindow->GetComponents().size()>0){ if(stageLootWindow->GetComponents().size()>0){

@ -46,9 +46,9 @@ void Menu::InitializeLoadGameWindow(){
loadGameWindow->ADD("Game Files Label",MenuLabel)(geom2d::rect<float>{{-8,-12},{208,12}},"Load Game",1.0f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; loadGameWindow->ADD("Game Files Label",MenuLabel)(geom2d::rect<float>{{-8,-12},{208,12}},"Load Game",1.0f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
loadGameWindow->ADD("Game Files List",ScrollableWindowComponent)(geom2d::rect<float>{{40,24},{112,116}})END loadGameWindow->ADD("Game Files List",ScrollableWindowComponent)(geom2d::rect<float>{{40,24},{112,116}})END
->Enable(true); ->Enable();
loadGameWindow->ADD("Online Game Files List",ScrollableWindowComponent)(geom2d::rect<float>{{40,24},{112,116}})END loadGameWindow->ADD("Online Game Files List",ScrollableWindowComponent)(geom2d::rect<float>{{40,24},{112,116}})END
->Enable(false); ->Disable();
loadGameWindow->ADD("Go Back Button",MenuComponent)(geom2d::rect<float>{{72,148},{48,12}},"Back",[](MenuFuncData menu){Menu::CloseMenu();return true;})END; loadGameWindow->ADD("Go Back Button",MenuComponent)(geom2d::rect<float>{{72,148},{48,12}},"Back",[](MenuFuncData menu){Menu::CloseMenu();return true;})END;
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
auto offlineCharacterTab = loadGameWindow->ADD("Offline Character Tab",MenuComponent)(geom2d::rect<float>{{-8,4},{102,16}},"Offline Characters",[](MenuFuncData data){ auto offlineCharacterTab = loadGameWindow->ADD("Offline Character Tab",MenuComponent)(geom2d::rect<float>{{-8,4},{102,16}},"Offline Characters",[](MenuFuncData data){

@ -132,7 +132,7 @@ void Menu::CheckClickAndPerformMenuSelect(AiL*game){
} }
void Menu::HoverMenuSelect(AiL*game){ void Menu::HoverMenuSelect(AiL*game){
if(!game->IsFocused()||selection.expired()||selection.lock()->disabled||selection.lock()->grayedOut||Menu::alreadyClicked||Menu::scrolling)return; if(!game->IsFocused()||selection.expired()||selection.lock()->disable||selection.lock()->disableOutsideWindow||selection.lock()->grayedOut||Menu::alreadyClicked||Menu::scrolling)return;
if(selection.lock()->draggable){ if(selection.lock()->draggable){
if(buttonHoldTime<"ThemeGlobal.MenuHoldTime"_F){ if(buttonHoldTime<"ThemeGlobal.MenuHoldTime"_F){
@ -147,7 +147,7 @@ void Menu::HoverMenuSelect(AiL*game){
} }
void Menu::MenuSelect(AiL*game){ void Menu::MenuSelect(AiL*game){
if(!game->IsFocused()||selection.expired()||selection.lock()->disabled||selection.lock()->grayedOut)return; if(!game->IsFocused()||selection.expired()||selection.lock()->disable||selection.lock()->disableOutsideWindow||selection.lock()->grayedOut)return;
bool buttonStillValid=selection.lock()->onClick(MenuFuncData{*this,game,selection,dynamic_pointer_cast<ScrollableWindowComponent>(selection.lock()->parentComponent.lock())}); bool buttonStillValid=selection.lock()->onClick(MenuFuncData{*this,game,selection,dynamic_pointer_cast<ScrollableWindowComponent>(selection.lock()->parentComponent.lock())});
if(buttonStillValid){ if(buttonStillValid){
if(selection.lock()->menuDest!=MenuType::ENUM_END){ if(selection.lock()->menuDest!=MenuType::ENUM_END){
@ -170,7 +170,7 @@ void Menu::Update(AiL*game){
} }
for(auto&[key,button]:components){ for(auto&[key,button]:components){
if(!button->disabled){ if(!button->disable||!button->disableOutsideWindow){
button->hovered=false; button->hovered=false;
} }
} }
@ -186,7 +186,7 @@ void Menu::Update(AiL*game){
selection={}; selection={};
for(auto&[key,component]:components){ for(auto&[key,component]:components){
if(component->selectable){ if(component->selectable){
if(!component->disabled&&!component->grayedOut){ if(!component->disable&&!component->disableOutsideWindow&&!component->grayedOut){
if(component->GetHoverState(game)){ if(component->GetHoverState(game)){
component->hovered=true; component->hovered=true;
itemHovered=true; itemHovered=true;
@ -338,6 +338,8 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
} }
} }
if(!selection.expired()){ if(!selection.expired()){
const int MAX_ITERATIONS=10; //Skip a maximum amount of items in case everything gets disabled somehow, prevents an infinite loop.
int iterationCount=0;
do{ do{
if(navigationGroups.size()==0)break; //We don't do anything here when there are no navigation groups. if(navigationGroups.size()==0)break; //We don't do anything here when there are no navigation groups.
std::string selectionButtonName=selection.lock()->GetName(); std::string selectionButtonName=selection.lock()->GetName();
@ -386,10 +388,15 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
SetSelection(returnData); SetSelection(returnData);
} }
} }
}else{ }else
if(!Menu::UsingMouseNavigation()){
if(std::holds_alternative<ButtonName>(defaultButton)&&std::get<ButtonName>(defaultButton).length()>0||std::holds_alternative<std::weak_ptr<MenuComponent>>(defaultButton))SetSelection(defaultButton,true); if(std::holds_alternative<ButtonName>(defaultButton)&&std::get<ButtonName>(defaultButton).length()>0||std::holds_alternative<std::weak_ptr<MenuComponent>>(defaultButton))SetSelection(defaultButton,true);
}else{
break; //There's no reason to be doing anything here if we navigate with the mouse.
} }
}while(selection.lock()->disabled||selection.lock()->grayedOut); iterationCount++;
if(iterationCount==MAX_ITERATIONS)ERR("WARNING! We've entered the max iteration count of automatic Menu navigation! THIS LIKELY MEANS WE'VE DONE SOMETHING TERRIBLY WRONG!");
}while(iterationCount<MAX_ITERATIONS&&(selection.lock()->grayedOut||selection.lock()->disable));
} }
if(game->KEY_UP.Released()||game->KEY_RIGHT.Released()||game->KEY_LEFT.Released()||game->KEY_DOWN.Released()|| if(game->KEY_UP.Released()||game->KEY_RIGHT.Released()||game->KEY_LEFT.Released()||game->KEY_DOWN.Released()||
@ -399,7 +406,7 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
buttonHoldTime=0; buttonHoldTime=0;
} }
if(&*prevSelection.lock()!=&*selection.lock()){ if(&*prevSelection.lock()!=&*selection.lock()){
if(!selection.expired()&&(selection.lock()->disabled||selection.lock()->grayedOut)){ if(!selection.expired()&&selection.lock()->disableOutsideWindow){
bool handled=false; bool handled=false;
if(!UsingMouseNavigation()){ if(!UsingMouseNavigation()){
//Let's transfer some information about our selection being off the screen. Our intention with keyboard controls is that the screen will scroll to the correct location instead. //Let's transfer some information about our selection being off the screen. Our intention with keyboard controls is that the screen will scroll to the correct location instead.
@ -500,7 +507,7 @@ Pixel Menu::GetRenderColor(){
} }
bool Menu::HandleOutsideDisabledButtonSelection(std::weak_ptr<MenuComponent>disabledButton){ bool Menu::HandleOutsideDisabledButtonSelection(std::weak_ptr<MenuComponent>disabledButton){
if(!disabledButton.expired()){ if(!disabledButton.expired()&&!disabledButton.lock()->parentComponent.expired()){
return disabledButton.lock()->parentComponent.lock()->HandleOutsideDisabledButtonSelection(disabledButton); return disabledButton.lock()->parentComponent.lock()->HandleOutsideDisabledButtonSelection(disabledButton);
}else{ }else{
return false; return false;

@ -80,7 +80,7 @@ void MenuComponent::Update(AiL*game){
} }
void MenuComponent::_Update(AiL*game){ void MenuComponent::_Update(AiL*game){
if(!disabled){ if(!disable&&!disableOutsideWindow){
_OnHover(); _OnHover();
Update(game); Update(game);
} }
@ -130,7 +130,7 @@ void MenuComponent::DrawDecal(ViewPort&window,bool focused){
} }
void MenuComponent::_DrawDecal(ViewPort&window,bool focused){ void MenuComponent::_DrawDecal(ViewPort&window,bool focused){
if(!disabled){ if(!disable&&!disableOutsideWindow){
DrawDecal(window,focused); DrawDecal(window,focused);
} }
} }
@ -188,8 +188,20 @@ const std::string&MenuComponent::GetLabel()const{
return label; return label;
} }
void MenuComponent::Enable(bool enabled){ void MenuComponent::Enable(){
disabled=!enabled; disable=false;
};
void MenuComponent::Disable(){
disable=true;
};
void MenuComponent::EnableOutsideWindow(){
disableOutsideWindow=false;
};
void MenuComponent::DisableOutsideWindow(){
disableOutsideWindow=true;
}; };
void MenuComponent::Cleanup(){} void MenuComponent::Cleanup(){}
@ -248,7 +260,7 @@ void MenuComponent::OnPlayerMoneyUpdate(uint32_t newMoney){}
void MenuComponent::OnChapterUpdate(uint8_t newChapter){} void MenuComponent::OnChapterUpdate(uint8_t newChapter){}
void MenuComponent::Click(){ void MenuComponent::Click(){
if(grayedOut||disabled)return; if(grayedOut||disable||disableOutsideWindow)return;
bool buttonStillValid=onClick(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name]}); bool buttonStillValid=onClick(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name]});
if(buttonStillValid){ if(buttonStillValid){
if(menuDest!=MenuType::ENUM_END){ if(menuDest!=MenuType::ENUM_END){
@ -263,4 +275,18 @@ void MenuComponent::Click(){
} }
void MenuComponent::SetLabel(std::string newLabel){ void MenuComponent::SetLabel(std::string newLabel){
label=newLabel; label=newLabel;
}
const bool MenuComponent::IsEnabled()const{
return !IsDisabled();
}
const bool MenuComponent::IsDisabled()const{
return disable;
}
const bool MenuComponent::IsEnabledOutsideWindow()const{
return !IsDisabledOutsideWindow();
}
const bool MenuComponent::IsDisabledOutsideWindow()const{
return disableOutsideWindow;
} }

@ -94,6 +94,8 @@ private:
void _OnMouseOut(); void _OnMouseOut();
void _OnHover(); void _OnHover();
SelectionType selectionType=CROSSHAIR; SelectionType selectionType=CROSSHAIR;
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.
protected: protected:
int depth=0; int depth=0;
float hoverEffect=0; float hoverEffect=0;
@ -110,7 +112,6 @@ protected:
bool selectable=true; bool selectable=true;
bool selectableViaKeyboard=true; bool selectableViaKeyboard=true;
bool selected=false; bool selected=false;
bool disabled=false; //If set to true, this component will not be rendered or updated.
bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop. bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop.
bool valid=true; //If set to false, this would cause the component to be removed. bool valid=true; //If set to false, this would cause the component to be removed.
bool fitToLabel=false; //Will shrink text horizontally to fit the size of the label if the display text is too large. bool fitToLabel=false; //Will shrink text horizontally to fit the size of the label if the display text is too large.
@ -128,6 +129,10 @@ protected:
virtual bool PointWithinParent(MenuComponent*child,geom2d::rect<float> drawRect); virtual bool PointWithinParent(MenuComponent*child,geom2d::rect<float> drawRect);
virtual void OnMouseOut(); virtual void OnMouseOut();
virtual void OnHover(); virtual void OnHover();
virtual void EnableOutsideWindow();
virtual void DisableOutsideWindow();
const bool IsEnabledOutsideWindow()const;
const bool IsDisabledOutsideWindow()const;
public: public:
MenuType parentMenu=MenuType::ENUM_END; MenuType parentMenu=MenuType::ENUM_END;
std::weak_ptr<ScrollableWindowComponent>parentComponent{}; std::weak_ptr<ScrollableWindowComponent>parentComponent{};
@ -150,7 +155,10 @@ public:
std::string GetName(); std::string GetName();
virtual void SetSelected(bool selected)final; virtual void SetSelected(bool selected)final;
virtual void SetSelectionType(SelectionType selectionType)final; virtual void SetSelectionType(SelectionType selectionType)final;
virtual void Enable(bool enabled); virtual void Enable();
virtual void Disable();
const bool IsEnabled()const;
const bool IsDisabled()const;
virtual void Cleanup(); virtual void Cleanup();
virtual void SetHoverFunc(std::function<bool(MenuFuncData)>func); virtual void SetHoverFunc(std::function<bool(MenuFuncData)>func);
virtual void SetMouseOutFunc(std::function<bool(MenuFuncData)>func); virtual void SetMouseOutFunc(std::function<bool(MenuFuncData)>func);

@ -97,10 +97,10 @@ public:
protected: protected:
virtual inline void OnMouseOut()override{ virtual inline void OnMouseOut()override{
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(false); Component<MenuLabel>(parentMenu,itemNameLabelName)->Disable();
} }
if(itemDescriptionLabelName!=""){ if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(false); Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Disable();
} }
} }
void UpdateLabel(){ void UpdateLabel(){
@ -118,11 +118,11 @@ protected:
} }
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText; Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText;
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable();
} }
if(itemDescriptionLabelName!=""){ if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText; Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText;
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable();
} }
} }
virtual inline void OnHover()override{ virtual inline void OnHover()override{

@ -106,10 +106,10 @@ public:
protected: protected:
virtual inline void OnMouseOut()override{ virtual inline void OnMouseOut()override{
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(false); Component<MenuLabel>(parentMenu,itemNameLabelName)->Disable();
} }
if(itemDescriptionLabelName!=""){ if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(false); Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Disable();
} }
} }
virtual inline void OnHover()override{ virtual inline void OnHover()override{
@ -135,11 +135,11 @@ protected:
} }
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText; Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText;
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable();
} }
if(itemDescriptionLabelName!=""){ if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText; Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText;
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable();
} }
} }
virtual inline void Update(AiL*game)override{ virtual inline void Update(AiL*game)override{

@ -62,15 +62,15 @@ void Menu::InitializeMerchantWindow(){
std::sort(categories.begin(),categories.end(),[](std::pair<std::string,int>&cat1,std::pair<std::string,int>&cat2){return cat1.second<cat2.second;}); std::sort(categories.begin(),categories.end(),[](std::pair<std::string,int>&cat1,std::pair<std::string,int>&cat2){return cat1.second<cat2.second;});
auto buyTab=merchantWindow->ADD("Buy Tab",MenuComponent)(geom2d::rect<float>{{2,0},{merchantWindow->size.x/2-4,24}},"Buy",[](MenuFuncData data){ auto buyTab=merchantWindow->ADD("Buy Tab",MenuComponent)(geom2d::rect<float>{{2,0},{merchantWindow->size.x/2-4,24}},"Buy",[](MenuFuncData data){
Component<RowInventoryScrollableWindowComponent>(MERCHANT,"Merchant Inventory Display")->Enable(true); Component<RowInventoryScrollableWindowComponent>(MERCHANT,"Merchant Inventory Display")->Enable();
Component<MenuComponent>(MERCHANT,"Sell Tab")->selected=false; Component<MenuComponent>(MERCHANT,"Sell Tab")->selected=false;
Component<MenuComponent>(MERCHANT,"Inventory Tabs Outline")->Enable(false); Component<MenuComponent>(MERCHANT,"Inventory Tabs Outline")->Disable();
for(auto&[category,items]:ITEM_CATEGORIES){ for(auto&[category,items]:ITEM_CATEGORIES){
if(DATA["ItemCategory"][category].GetString(0)=="!HIDE")continue; //This category is meant to be hidden! if(DATA["ItemCategory"][category].GetString(0)=="!HIDE")continue; //This category is meant to be hidden!
Component<MenuComponent>(MERCHANT,category+" Inventory Tab")->Enable(false); Component<MenuComponent>(MERCHANT,category+" Inventory Tab")->Disable();
} }
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Enable(false); Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Disable();
Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->Enable(false); Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->Disable();
data.component.lock()->selected=true; data.component.lock()->selected=true;
return true; return true;
})END; })END;
@ -78,15 +78,15 @@ void Menu::InitializeMerchantWindow(){
buyTab->selectionType=SelectionType::HIGHLIGHT; buyTab->selectionType=SelectionType::HIGHLIGHT;
auto sellTab=merchantWindow->ADD("Sell Tab",MenuComponent)(geom2d::rect<float>{{merchantWindow->size.x/2+2,0},{merchantWindow->size.x/2-4,24}},"Sell",[](MenuFuncData data){ auto sellTab=merchantWindow->ADD("Sell Tab",MenuComponent)(geom2d::rect<float>{{merchantWindow->size.x/2+2,0},{merchantWindow->size.x/2-4,24}},"Sell",[](MenuFuncData data){
Component<RowInventoryScrollableWindowComponent>(MERCHANT,"Merchant Inventory Display")->Enable(false); Component<RowInventoryScrollableWindowComponent>(MERCHANT,"Merchant Inventory Display")->Disable();
Component<MenuComponent>(MERCHANT,"Buy Tab")->selected=false; Component<MenuComponent>(MERCHANT,"Buy Tab")->selected=false;
Component<MenuComponent>(MERCHANT,"Inventory Tabs Outline")->Enable(true); Component<MenuComponent>(MERCHANT,"Inventory Tabs Outline")->Enable();
for(auto&[category,items]:ITEM_CATEGORIES){ for(auto&[category,items]:ITEM_CATEGORIES){
if(DATA["ItemCategory"][category].GetString(0)=="!HIDE")continue; //This category is meant to be hidden! if(DATA["ItemCategory"][category].GetString(0)=="!HIDE")continue; //This category is meant to be hidden!
Component<MenuComponent>(MERCHANT,category+" Inventory Tab")->Enable(true); Component<MenuComponent>(MERCHANT,category+" Inventory Tab")->Enable();
} }
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Enable(true); Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Enable();
Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->Enable(true); Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->Enable();
data.component.lock()->selected=true; data.component.lock()->selected=true;
return true; return true;
})END; })END;
@ -140,9 +140,9 @@ void Menu::InitializeMerchantWindow(){
auto button=merchantWindow->ADD(category+" Inventory Tab",MenuComponent)(geom2d::rect<float>{{2,30+yOffset},{68,16}},category,MenuType::ENUM_END, auto button=merchantWindow->ADD(category+" Inventory Tab",MenuComponent)(geom2d::rect<float>{{2,30+yOffset},{68,16}},category,MenuType::ENUM_END,
[&](MenuFuncData data){ [&](MenuFuncData data){
//Close the old inventory window and show the proper one. //Close the old inventory window and show the proper one.
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Enable(false); Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Disable();
Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->SetSelected(false); Component<MenuComponent>(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->SetSelected(false);
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.component.lock()->S(A::CATEGORY_NAME))->Enable(true); Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.component.lock()->S(A::CATEGORY_NAME))->Enable();
Component<MenuComponent>(data.menu.GetType(),data.component.lock()->S(A::CATEGORY_NAME)+" Inventory Tab")->SetSelected(true); Component<MenuComponent>(data.menu.GetType(),data.component.lock()->S(A::CATEGORY_NAME)+" Inventory Tab")->SetSelected(true);
data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)=data.component.lock()->S(A::CATEGORY_NAME); data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)=data.component.lock()->S(A::CATEGORY_NAME);
return true; return true;
@ -185,10 +185,12 @@ void Menu::InitializeMerchantWindow(){
if(first){ if(first){
merchantWindow->S(A::LAST_INVENTORY_TYPE_OPENED)=category; merchantWindow->S(A::LAST_INVENTORY_TYPE_OPENED)=category;
button->onClick(MenuFuncData{*merchantWindow,game,button}); //Simulate a click of this button if it's the top one for an initial inventory display. button->onClick(MenuFuncData{*merchantWindow,game,button}); //Simulate a click of this button if it's the top one for an initial inventory display.
inventoryDisplay->Enable();
}else{
inventoryDisplay->Disable();
} }
Menu::AddInventoryListener(inventoryDisplay,category); Menu::AddInventoryListener(inventoryDisplay,category);
inventoryDisplay->Enable(first);
inventoryDisplay->SetCompactDescriptions(NON_COMPACT); inventoryDisplay->SetCompactDescriptions(NON_COMPACT);
yOffset+=20; yOffset+=20;

@ -1211,7 +1211,7 @@ void Player::AddXP(const uint32_t xpGain){
uint32_t nextLevelXP=NextLevelXPRequired(); uint32_t nextLevelXP=NextLevelXPRequired();
while(currentLevelXP>nextLevelXP){ while(currentLevelXP>nextLevelXP){
currentLevelXP-=nextLevelXP; currentLevelXP-=nextLevelXP;
level++; SetLevel(Level()+1);
OnLevelUp(); OnLevelUp();
} }
} }

@ -188,10 +188,10 @@ public:
} }
virtual inline void OnMouseOut()override{ virtual inline void OnMouseOut()override{
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(false); Component<MenuLabel>(parentMenu,itemNameLabelName)->Disable();
} }
if(itemDescriptionLabelName!=""){ if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(false); Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Disable();
} }
} }
virtual inline void SetShowQuantity(bool showQuantity){ virtual inline void SetShowQuantity(bool showQuantity){
@ -220,11 +220,11 @@ public:
} }
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText; Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText;
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable();
} }
if(itemDescriptionLabelName!=""){ if(itemDescriptionLabelName!=""){
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText; Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->label=labelDescriptionText;
Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemDescriptionLabelName)->Enable();
} }
} }
virtual inline void OnHover()override{ virtual inline void OnHover()override{

@ -119,8 +119,20 @@ protected:
upButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+vf2d{rect.size.x-12,0}).str()+"_"+vf2d(12,12).str(),MenuComponent)(geom2d::rect<float>{rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){SetScrollAmount(GetScrollAmount()+vf2d{0,"ThemeGlobal.MenuButtonScrollSpeed"_F});return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH depth-1 END; upButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+vf2d{rect.size.x-12,0}).str()+"_"+vf2d(12,12).str(),MenuComponent)(geom2d::rect<float>{rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){SetScrollAmount(GetScrollAmount()+vf2d{0,"ThemeGlobal.MenuButtonScrollSpeed"_F});return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH depth-1 END;
downButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+rect.size-vf2d{12,12}).str()+"_"+vf2d(12,12).str(),MenuComponent)(geom2d::rect<float>{rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){SetScrollAmount(GetScrollAmount()-vf2d{0,"ThemeGlobal.MenuButtonScrollSpeed"_F});return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH depth-1 END; downButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+rect.size-vf2d{12,12}).str()+"_"+vf2d(12,12).str(),MenuComponent)(geom2d::rect<float>{rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){SetScrollAmount(GetScrollAmount()-vf2d{0,"ThemeGlobal.MenuButtonScrollSpeed"_F});return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH depth-1 END;
subWindow=ViewPort::rectViewPort({},rect.size,Menu::menus[parentMenu]->pos+rect.pos); subWindow=ViewPort::rectViewPort({},rect.size,Menu::menus[parentMenu]->pos+rect.pos);
if(!upButton.expired()){upButton.lock()->Enable(!disabled);} if(!upButton.expired()){
if(!downButton.expired()){downButton.lock()->Enable(!disabled);} if(IsEnabled()){
upButton.lock()->Enable();
}else{
upButton.lock()->Disable();
}
}
if(!downButton.expired()){
if(IsEnabled()){
downButton.lock()->Enable();
}else{
downButton.lock()->Disable();
}
}
} }
virtual inline void BeforeUpdate(AiL*game)override{ virtual inline void BeforeUpdate(AiL*game)override{
MenuComponent::BeforeUpdate(game); MenuComponent::BeforeUpdate(game);
@ -184,15 +196,19 @@ protected:
std::sort(components.begin(),components.end(),[](std::weak_ptr<MenuComponent>c1,std::weak_ptr<MenuComponent>c2){return c1.lock()->depth>c2.lock()->depth;}); std::sort(components.begin(),components.end(),[](std::weak_ptr<MenuComponent>c1,std::weak_ptr<MenuComponent>c2){return c1.lock()->depth>c2.lock()->depth;});
for(std::weak_ptr<MenuComponent>component:components){ for(std::weak_ptr<MenuComponent>component:components){
component.lock()->disabled=!OnScreen(component.lock()); if(OnScreen(component.lock())){
component.lock()->EnableOutsideWindow();
}else{
component.lock()->DisableOutsideWindow();
}
component.lock()->_Update(game); component.lock()->_Update(game);
} }
upButton.lock()->disabled=false; upButton.lock()->disable=false;
downButton.lock()->disabled=false; downButton.lock()->disable=false;
if(geom2d::contains(rect,bounds)){//This means we have no reason to show a scrollbar. if(geom2d::contains(rect,bounds)){//This means we have no reason to show a scrollbar.
upButton.lock()->disabled=true; upButton.lock()->disable=true;
downButton.lock()->disabled=true; downButton.lock()->disable=true;
} }
#pragma region Move scroll offset towards target offset #pragma region Move scroll offset towards target offset
@ -285,7 +301,7 @@ public:
components.push_back(button); components.push_back(button);
button->renderInMain=false; //Now we are in control! button->renderInMain=false; //Now we are in control!
button->parentComponent=DYNAMIC_POINTER_CAST<ScrollableWindowComponent>(Menu::menus[parentMenu]->components[this->GetName()]); button->parentComponent=DYNAMIC_POINTER_CAST<ScrollableWindowComponent>(Menu::menus[parentMenu]->components[this->GetName()]);
button->disabled=disabled; button->disable=disable;
CalculateBounds(); CalculateBounds();
@ -307,12 +323,20 @@ public:
inline std::vector<std::weak_ptr<MenuComponent>>&GetComponents(){ inline std::vector<std::weak_ptr<MenuComponent>>&GetComponents(){
return components; return components;
} }
virtual inline void Enable(bool enabled)override final{ virtual inline void Enable()override final{
disabled=!enabled; MenuComponent::Enable();
for(std::weak_ptr<MenuComponent>component:components){
component.lock()->Enable();
}
if(upButton.lock()){upButton.lock()->Enable();}
if(downButton.lock()){downButton.lock()->Enable();}
};
virtual inline void Disable()override final{
MenuComponent::Disable();
for(std::weak_ptr<MenuComponent>component:components){ for(std::weak_ptr<MenuComponent>component:components){
component.lock()->Enable(enabled); component.lock()->Disable();
} }
if(upButton.lock()){upButton.lock()->Enable(enabled);} if(upButton.lock()){upButton.lock()->Disable();}
if(downButton.lock()){downButton.lock()->Enable(enabled);} if(downButton.lock()){downButton.lock()->Disable();}
}; };
}; };

@ -77,7 +77,7 @@ public:
inline virtual void Update(AiL*game)override final{ inline virtual void Update(AiL*game)override final{
MenuComponent::Update(game); MenuComponent::Update(game);
if(disabled)return; if(IsDisabled()||IsDisabledOutsideWindow())return;
if(hovered&&(game->KEY_CONFIRM.Pressed()||game->GetMouse(Mouse::LEFT).bPressed)){ if(hovered&&(game->KEY_CONFIRM.Pressed()||game->GetMouse(Mouse::LEFT).bPressed)){
dragging=true; dragging=true;

@ -42,6 +42,7 @@ All rights reserved.
#include "MenuLabel.h" #include "MenuLabel.h"
#include "SaveFile.h" #include "SaveFile.h"
#include "ProgressBar.h" #include "ProgressBar.h"
#include "SoundEffect.h"
INCLUDE_MONSTER_LIST INCLUDE_MONSTER_LIST
INCLUDE_game INCLUDE_game
@ -50,8 +51,10 @@ void State_LevelComplete::OnStateChange(GameState*prevState){
if(Menu::IsMenuOpen()){ if(Menu::IsMenuOpen()){
Menu::CloseAllMenus(); Menu::CloseAllMenus();
} }
levelUpTextPos={-100.f,-100.f};
Component<MenuLabel>(MenuType::LEVEL_COMPLETE,"Level EXP Gain Outline")->SetLabel(std::format("+{} Exp",game->GetPlayer()->GetAccumulatedXP())); Component<MenuLabel>(MenuType::LEVEL_COMPLETE,"Level EXP Gain Outline")->SetLabel(std::format("+{} Exp",game->GetPlayer()->GetAccumulatedXP()));
Component<ProgressBar>(MenuType::LEVEL_COMPLETE,"XP Bar")->ResetProgressBar(game->GetPlayer()->CurrentXP(),game->GetPlayer()->NextLevelXPRequired()); Component<ProgressBar>(MenuType::LEVEL_COMPLETE,"XP Bar")->ResetProgressBar(game->GetPlayer()->CurrentXP(),game->GetPlayer()->NextLevelXPRequired());
accumulatedXP=game->GetPlayer()->GetAccumulatedXP();
game->GetPlayer()->AddXP(game->GetPlayer()->GetAccumulatedXP()); game->GetPlayer()->AddXP(game->GetPlayer()->GetAccumulatedXP());
for(const ItemMapData&data:game->GetCurrentMap().GetStageLoot()){ for(const ItemMapData&data:game->GetCurrentMap().GetStageLoot()){
uint8_t amountDiff=data.maxAmt-data.minAmt; uint8_t amountDiff=data.maxAmt-data.minAmt;
@ -69,7 +72,39 @@ void State_LevelComplete::OnStateChange(GameState*prevState){
Menu::OpenMenu(LEVEL_COMPLETE); Menu::OpenMenu(LEVEL_COMPLETE);
}; };
void State_LevelComplete::OnUserUpdate(AiL*game){ void State_LevelComplete::OnUserUpdate(AiL*game){
if(levelUpTimer>0.f){
levelUpTimer=std::max(0.f,levelUpTimer-game->GetElapsedTime());
levelUpTextPos.y-=(16/"Interface.HUD Level Up Timer"_F)*game->GetElapsedTime();
if(levelUpTimer<0.f){
levelUpTimer=0.f;
levelUpTextPos=Menu::menus[LEVEL_COMPLETE]->pos.x+Component<MenuLabel>(LEVEL_COMPLETE,"Level Display")->GetPos()+Component<MenuLabel>(LEVEL_COMPLETE,"Level Display")->GetSize()-vf2d{0.f,16.f};
}
}
if(accumulatedXP>0){
lastXPChangeTimer-=game->GetElapsedTime();
while(lastXPChangeTimer<=0.f){
int incrementAmt=int(accumulatedXP/(1/"Interface.HUD XP Bar Tick Rate"_F))+1;
accumulatedXP-=incrementAmt;
auto progressBar=Component<ProgressBar>(MenuType::LEVEL_COMPLETE,"XP Bar");
progressBar->UpdateProgressBar(progressBar->GetCurrentProgress()+incrementAmt);
if(progressBar->GetCurrentProgress()>=progressBar->GetFinalProgress()){
levelUpTextPos=Menu::menus[LEVEL_COMPLETE]->pos+Component<MenuLabel>(LEVEL_COMPLETE,"Level Display")->GetPos()+Component<MenuLabel>(LEVEL_COMPLETE,"Level Display")->GetSize();
levelUpTimer="Interface.HUD Level Up Timer"_F;
progressBar->ResetProgressBar(progressBar->GetCurrentProgress()-progressBar->GetFinalProgress(),game->GetPlayer()->NextLevelXPRequired());
SoundEffect::PlaySFX("Level Up",SoundEffect::CENTERED);
}
lastXPChangeTimer+="Interface.HUD XP Bar Tick Rate"_F;
}
}
}; };
void State_LevelComplete::Draw(AiL*game){ void State_LevelComplete::Draw(AiL*game){
game->RenderHud(); game->RenderHud();
}; };
void State_LevelComplete::DrawOverlay(AiL*game){
game->DrawShadowStringPropDecal(levelUpTextPos+vf2d{8.f,0.f},"Level Up!",YELLOW);
game->DrawRotatedDecal(levelUpTextPos+vf2d{2.f,1.f},GFX["overworld_arrow.png"].Decal(),-PI/2,GFX["overworld_arrow.png"].Sprite()->Size(),{1.f,1.f},BLACK);
game->DrawRotatedDecal(levelUpTextPos+vf2d{2.f,0.f},GFX["overworld_arrow.png"].Decal(),-PI/2,GFX["overworld_arrow.png"].Sprite()->Size(),{1.f,1.f},YELLOW);
}

@ -39,7 +39,12 @@ All rights reserved.
#include "GameState.h" #include "GameState.h"
class State_LevelComplete:public GameState{ class State_LevelComplete:public GameState{
int accumulatedXP=0;
float lastXPChangeTimer=0.f;
vf2d levelUpTextPos={-100.f,-100.f};
float levelUpTimer=0.f;
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void DrawOverlay(AiL*game)override final;
}; };

@ -74,7 +74,11 @@ void State_OverworldMap::OnStateChange(GameState*prevState){
Component<MenuLabel>(OVERWORLD_LEVEL_SELECT,"Chapter Label")->SetLabel("Chapter "+std::to_string(game->GetCurrentChapter())); Component<MenuLabel>(OVERWORLD_LEVEL_SELECT,"Chapter Label")->SetLabel("Chapter "+std::to_string(game->GetCurrentChapter()));
Component<MenuLabel>(OVERWORLD_LEVEL_SELECT,"Stage Label")->SetLabel(currentConnectionPoint->name); Component<MenuLabel>(OVERWORLD_LEVEL_SELECT,"Stage Label")->SetLabel(currentConnectionPoint->name);
Component<EncountersSpawnListScrollableWindowComponent>(OVERWORLD_LEVEL_SELECT,"Spawns List")->UpdateSpawns(currentConnectionPoint->spawns); Component<EncountersSpawnListScrollableWindowComponent>(OVERWORLD_LEVEL_SELECT,"Spawns List")->UpdateSpawns(currentConnectionPoint->spawns);
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Enable(currentConnectionPoint->levelDataExists); if(currentConnectionPoint->levelDataExists){
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Enable();
}else{
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Disable();
}
Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false); Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false);
game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName()); game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName());
}; };
@ -243,8 +247,16 @@ void State_OverworldMap::UpdateCurrentConnectionPoint(const ConnectionPoint&conn
currentConnectionPoint=const_cast<ConnectionPoint*>(&connection); currentConnectionPoint=const_cast<ConnectionPoint*>(&connection);
Component<MenuLabel>(OVERWORLD_LEVEL_SELECT,"Stage Label")->SetLabel(currentConnectionPoint->name); Component<MenuLabel>(OVERWORLD_LEVEL_SELECT,"Stage Label")->SetLabel(currentConnectionPoint->name);
Component<EncountersSpawnListScrollableWindowComponent>(OVERWORLD_LEVEL_SELECT,"Spawns List")->UpdateSpawns(currentConnectionPoint->spawns); Component<EncountersSpawnListScrollableWindowComponent>(OVERWORLD_LEVEL_SELECT,"Spawns List")->UpdateSpawns(currentConnectionPoint->spawns);
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Enable(currentConnectionPoint->levelDataExists); if(currentConnectionPoint->levelDataExists){
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Change Loadout Button")->Enable(currentConnectionPoint->levelDataExists&&!(currentConnectionPoint->type=="STORY"||currentConnectionPoint->type=="SHOP")); Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Enable();
}else{
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Enter Button")->Disable();
}
if(currentConnectionPoint->levelDataExists&&!(currentConnectionPoint->type=="STORY"||currentConnectionPoint->type=="SHOP")){
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Change Loadout Button")->Enable();
}else{
Component<MenuComponent>(OVERWORLD_LEVEL_SELECT,"Change Loadout Button")->Disable();
}
} }
std::optional<ConnectionPoint*>State_OverworldMap::ConnectionPointFromString(std::string_view mapName){ std::optional<ConnectionPoint*>State_OverworldMap::ConnectionPointFromString(std::string_view mapName){

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 7041 #define VERSION_BUILD 7095
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -415,7 +415,7 @@
</layer> </layer>
<objectgroup id="5" name="Spawn Zones"> <objectgroup id="5" name="Spawn Zones">
<object id="1" name="Player Spawn" type="PlayerSpawnLocation" x="96" y="360" width="24" height="24"/> <object id="1" name="Player Spawn" type="PlayerSpawnLocation" x="96" y="360" width="24" height="24"/>
<object id="2" name="End Zone" type="EndZone" x="77.8813" y="303.88" width="120" height="120"/> <object id="2" name="End Zone" type="EndZone" x="3191" y="1507" width="120" height="120"/>
<object id="3" name="Spawn Group 1" type="SpawnGroup" x="670" y="157" width="506" height="492"> <object id="3" name="Spawn Group 1" type="SpawnGroup" x="670" y="157" width="506" height="492">
<ellipse/> <ellipse/>
</object> </object>

@ -50,4 +50,10 @@ Interface
# How long between each reduction/addition of health. # How long between each reduction/addition of health.
HUD Mana Tick Rate = 0.01s HUD Mana Tick Rate = 0.01s
# How long between each addition to the XP bar on the level complete screen.
HUD XP Bar Tick Rate = 0.005s
# How long the timer text rises up
HUD Level Up Timer = 0.2s
} }

@ -88,6 +88,11 @@ Events
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = item_collect.ogg, 40% File[0] = item_collect.ogg, 40%
} }
Level Up
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = levelup.ogg, 100%
}
Monster Hurt Monster Hurt
{ {
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)

Loading…
Cancel
Save