diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index d196ca1a..e1ce0284 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -355,6 +355,10 @@ + + + + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index c62eaad3..39994c4f 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -462,6 +462,9 @@ Header Files + + Header Files + diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 0d9da714..491ae899 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -287,6 +287,24 @@ bool AiL::OnUserCreate(){ TitleScreen::Initialize(); Stats::InitializeDamageReductionTable(); + + #ifdef __EMSCRIPTEN__ + emscripten_idb_async_load("/assets",("save_file_path"_S+"system.conf").c_str(),0,[](void*arg,void*data,int length){ + std::cout<<"Loaded System Save File successfully!"<B(A::IS_KEYBOARD)){ //We are requesting a brand new input. - using A=Attribute; - if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){ - InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->SetNewPrimaryKeybind(Input{KEY,key}); - Menu::alreadyClicked=true; - for(auto&[menuType,menu]:Menu::menus){ - menu->helpDisplay.Initialize(menu->inputGroups); + if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]){ + + if(Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){//We are requesting a brand new input. + using A=Attribute; + if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){ + InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->SetNewPrimaryKeybind(Input{KEY,key}); + Menu::alreadyClicked=true; + for(auto&[menuType,menu]:Menu::menus){ + menu->helpDisplay.Initialize(menu->inputGroups); + } + Menu::CloseMenu(); } + }else{ Menu::CloseMenu(); } } @@ -3217,35 +3241,40 @@ void AiL::GetAnyKeyPress(Key key){ void AiL::GetAnyMouseRelease(int32_t mouseButton){ #pragma region New mouse input binding listener using A=Attribute; - if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]&&Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){ //We are requesting a brand new input. - using A=Attribute; - const std::vector*inputGroup=&InputGroup::menuInputGroups; //First we detect which input group this mouse binding is for. Each group can individually have one key bound to each mouse button, that's why we first detect which group we actually care about. - for(const std::string&groupName:InputGroup::gameplayInputGroups){ - if(groupName==Menu::menus[NEW_INPUT]->S(A::KEYBIND)){ - inputGroup=&InputGroup::gameplayInputGroups; + if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]){ + + if(Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){//We are requesting a brand new input. + using A=Attribute; + const std::vector*inputGroup=&InputGroup::menuInputGroups; //First we detect which input group this mouse binding is for. Each group can individually have one key bound to each mouse button, that's why we first detect which group we actually care about. + for(const std::string&groupName:InputGroup::gameplayInputGroups){ + if(groupName==Menu::menus[NEW_INPUT]->S(A::KEYBIND)){ + inputGroup=&InputGroup::gameplayInputGroups; + } } - } - //Next we need to iterate through that group and check for any already-bound buttons for the mouse button we are about to apply. Get rid of the keybinds from there. - for(const std::string&menuItem:*inputGroup){ - InputGroup&group=*InputGroup::menuNamesToInputGroups[menuItem]; - std::vectorkeybindsToRemove; - for(Input&input:group.keyOrder){ - if(input.GetType()==MOUSE&&input.GetKeyCode()==mouseButton){ - keybindsToRemove.push_back(input); + //Next we need to iterate through that group and check for any already-bound buttons for the mouse button we are about to apply. Get rid of the keybinds from there. + for(const std::string&menuItem:*inputGroup){ + InputGroup&group=*InputGroup::menuNamesToInputGroups[menuItem]; + std::vectorkeybindsToRemove; + for(Input&input:group.keyOrder){ + if(input.GetType()==MOUSE&&input.GetKeyCode()==mouseButton){ + keybindsToRemove.push_back(input); + } + } + for(Input&input:keybindsToRemove){ + group.RemoveKeybind(input); } } - for(Input&input:keybindsToRemove){ - group.RemoveKeybind(input); - } - } - if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){ - InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->AddKeybind(Input{MOUSE,mouseButton}); - Menu::alreadyClicked=true; - for(auto&[menuType,menu]:Menu::menus){ - menu->helpDisplay.Initialize(menu->inputGroups); + if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){ + InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->AddKeybind(Input{MOUSE,mouseButton}); + Menu::alreadyClicked=true; + for(auto&[menuType,menu]:Menu::menus){ + menu->helpDisplay.Initialize(menu->inputGroups); + } + Menu::CloseMenu(); } + }else{ Menu::CloseMenu(); } } diff --git a/Adventures in Lestoria/Audio.cpp b/Adventures in Lestoria/Audio.cpp index 034a2a83..e72dc844 100644 --- a/Adventures in Lestoria/Audio.cpp +++ b/Adventures in Lestoria/Audio.cpp @@ -46,6 +46,7 @@ INCLUDE_DATA float Audio::defaultFadeTime=0.f; float Audio::sfxVol=1.f; float Audio::bgmVol=1.f; +bool Audio::muted=false; void Audio::Initialize(){ Engine().SetBackgroundPlay(true); @@ -298,7 +299,7 @@ void Audio::SetBGMVolume(float vol){ BGM&track=Self().bgm[Self().playParams.sound]; for(int channelListIndex=0;int trackID:track.GetChannelIDs()){ float channelVol=track.GetVolume(Self().currentAudioEvent,channelListIndex); - Engine().SetVolume(trackID,channelVol*GetBGMVolume()); + Engine().SetVolume(trackID,channelVol*GetBGMVolume()*GetMuteMult()); } } void Audio::SetSFXVolume(float vol){ @@ -309,4 +310,8 @@ float&Audio::GetBGMVolume(){ } float&Audio::GetSFXVolume(){ return sfxVol; +} +float Audio::GetMuteMult(){ + if(muted)return 0.f; + return 1.f; } \ No newline at end of file diff --git a/Adventures in Lestoria/Audio.h b/Adventures in Lestoria/Audio.h index cd3bf2c9..d5f019e1 100644 --- a/Adventures in Lestoria/Audio.h +++ b/Adventures in Lestoria/Audio.h @@ -71,6 +71,7 @@ public: static void SetSFXVolume(float vol); static float&GetBGMVolume(); static float&GetSFXVolume(); + static float GetMuteMult(); private: struct BGMPlayParams{ std::string sound; @@ -122,6 +123,7 @@ private: bool fullyLoaded=true; float playBGMWaitTime=0.0f; BGMPlayParams playParams; + static bool muted; }; std::string operator""_SFX(const char*key,size_t length); \ No newline at end of file diff --git a/Adventures in Lestoria/BlacksmithCraftingWindow.cpp b/Adventures in Lestoria/BlacksmithCraftingWindow.cpp index ebff5cc1..aa653d04 100644 --- a/Adventures in Lestoria/BlacksmithCraftingWindow.cpp +++ b/Adventures in Lestoria/BlacksmithCraftingWindow.cpp @@ -84,7 +84,9 @@ void Menu::InitializeBlacksmithCraftingWindow(){ }else{ data.menu.SetSelection(std::weak_ptr(Component(data.menu.GetType(),"Leave Button"))); } - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } return true; })END; weaponTab->selected=true; @@ -100,7 +102,9 @@ void Menu::InitializeBlacksmithCraftingWindow(){ }else{ data.menu.SetSelection(std::weak_ptr(Component(data.menu.GetType(),"Leave Button"))); } - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } return true; })END; armorTab->selectionType=SelectionType::HIGHLIGHT; diff --git a/Adventures in Lestoria/CharacterMenuWindow.cpp b/Adventures in Lestoria/CharacterMenuWindow.cpp index d2742276..ef93c1b4 100644 --- a/Adventures in Lestoria/CharacterMenuWindow.cpp +++ b/Adventures in Lestoria/CharacterMenuWindow.cpp @@ -157,7 +157,9 @@ void Menu::InitializeCharacterMenuWindow(){ if(!comp.expired()){ if(OppositeRingSlotDoesNotMatchCurrentEquip(comp.lock())){ //If we find that the opposite ring slot is equipped to us, this would be an item swap or the exact same ring, therefore no stat calculations apply. Inventory::EquipItem(comp.lock()->GetItem(),EquipSlot(comp.lock()->I(Attribute::EQUIP_TYPE))); - SoundEffect::PlaySFX(comp.lock()->GetItem().lock()->UseSound(),SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX(comp.lock()->GetItem().lock()->UseSound(),SoundEffect::CENTERED); + } for(std::weak_ptrbutton:DYNAMIC_POINTER_CAST(data.parentComponent.lock())->GetComponents()){ std::weak_ptrcomp=DYNAMIC_POINTER_CAST(button.lock()); comp.lock()->SetSelected(false); diff --git a/Adventures in Lestoria/Checkbox.h b/Adventures in Lestoria/Checkbox.h index 0eca8147..9fe4a7e2 100644 --- a/Adventures in Lestoria/Checkbox.h +++ b/Adventures in Lestoria/Checkbox.h @@ -66,10 +66,12 @@ public: inline void SetChecked(bool checked){ this->checked=checked; - if(checked){ - SoundEffect::PlaySFX("Toggle On",SoundEffect::CENTERED); - }else{ - SoundEffect::PlaySFX("Toggle Off",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(parentMenu)){ + if(checked){ + SoundEffect::PlaySFX("Toggle On",SoundEffect::CENTERED); + }else{ + SoundEffect::PlaySFX("Toggle Off",SoundEffect::CENTERED); + } } } diff --git a/Adventures in Lestoria/GameSettings.cpp b/Adventures in Lestoria/GameSettings.cpp index 4dc1b2b0..cae58f06 100644 --- a/Adventures in Lestoria/GameSettings.cpp +++ b/Adventures in Lestoria/GameSettings.cpp @@ -37,12 +37,20 @@ All rights reserved. #pragma endregion #include "GameSettings.h" +#include "olcUTIL_DataFile.h" +#include "config.h" +#include "Checkbox.h" +#include "MenuIconButton.h" +#include "InputDisplayComponent.h" + +INCLUDE_DATA bool GameSettings::screenShake=true; bool GameSettings::rumble=true; bool GameSettings::terrainCollisionBoxes=true; bool GameSettings::keyboardAutoAim=false; vi2d GameSettings::windowPos{30,30}; +IconType GameSettings::iconType=IconType::XB; const bool GameSettings::ScreenShakeEnabled(){ return screenShake; @@ -59,6 +67,9 @@ const bool GameSettings::KeyboardAutoAimEnabled(){ const vi2d GameSettings::GetWindowPos(){ return windowPos; } +const IconType GameSettings::GetIconType(){ + return iconType; +} void GameSettings::SetScreenShake(bool screenShakeEnabled){ screenShake=screenShakeEnabled; @@ -74,4 +85,66 @@ void GameSettings::SetKeyboardAutoAim(bool autoAimEnabled){ } void GameSettings::SetWindowPos(vi2d windowPos){ GameSettings::windowPos=windowPos; +} +void GameSettings::SetIconType(IconType type){ + iconType=type; +} + +void GameSettings::Initialize(){ + utils::datafile loadSystemFile; + + std::string loadSystemFilename="save_file_path"_S+"system.conf"; + + utils::datafile::Read(loadSystemFile,loadSystemFilename); + + if(loadSystemFile.HasProperty("Screen Shake")){ + GameSettings::SetScreenShake(loadSystemFile["Screen Shake"].GetBool()); + Component(SETTINGS,"Screen Shake Checkbox")->SetChecked(loadSystemFile["Screen Shake"].GetBool()); + } + if(loadSystemFile.HasProperty("Controller Rumble")){ + GameSettings::SetRumble(loadSystemFile["Controller Rumble"].GetBool()); + Component(SETTINGS,"Controller Rumble Checkbox")->SetChecked(loadSystemFile["Controller Rumble"].GetBool()); + } + if(loadSystemFile.HasProperty("Terrain Collision Boxes")){ + GameSettings::SetTerrainCollisionBoxes(loadSystemFile["Terrain Collision Boxes"].GetBool()); + Component(SETTINGS,"Terrain Collision Boxes Checkbox")->SetChecked(loadSystemFile["Terrain Collision Boxes"].GetBool()); + } + if(loadSystemFile.HasProperty("Keyboard Auto-Aim")){ + GameSettings::SetKeyboardAutoAim(loadSystemFile["Keyboard Auto-Aim"].GetBool()); + Component(SETTINGS,"Keyboard Play Auto-Aim Checkbox")->SetChecked(loadSystemFile["Keyboard Auto-Aim"].GetBool()); + } + if(loadSystemFile.HasProperty("Controller Icons")){ + const int maxIterations=10; + int iterationCount=0; + IconType targetIconType=IconType(loadSystemFile["Controller Icons"].GetInt()); + while(iterationCount(SETTINGS,"Button Set Toggle Box")->Click(); + iterationCount++; + } + if(iterationCount>=maxIterations)ERR("WARNING! Reached the max iteration count while cycling through controller icons! Failed to reach target icon set. THIS SHOULD NOT BE HAPPENING!") + } + + if(loadSystemFile.HasProperty("BGM Level"))Audio::SetBGMVolume(loadSystemFile["BGM Level"].GetReal()); + if(loadSystemFile.HasProperty("SFX Level"))Audio::SetSFXVolume(loadSystemFile["SFX Level"].GetReal()); + + #pragma region Load up Menu Keybinds + const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1; + const int menuColCount=2; + for(int row=0;row(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput(); + group.SetNewPrimaryKeybind({KEY,loadSystemFile[keyName].GetInt()}); + } + keyName="Menu Controller Input_"+"Inputs.Menu Input Names"_s[inputID]; + if(loadSystemFile.HasProperty(keyName)){ + InputGroup&group=Component(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput(); + group.SetNewPrimaryKeybind({CONTROLLER,loadSystemFile[keyName].GetInt()}); + } + } + } + #pragma endregion } \ No newline at end of file diff --git a/Adventures in Lestoria/GameSettings.h b/Adventures in Lestoria/GameSettings.h index 9902861a..d995c2f4 100644 --- a/Adventures in Lestoria/GameSettings.h +++ b/Adventures in Lestoria/GameSettings.h @@ -38,6 +38,7 @@ All rights reserved. #pragma once #include "olcUTIL_Geometry2D.h" +#include "IconType.h" class GameSettings{ static bool screenShake; @@ -45,15 +46,19 @@ class GameSettings{ static bool terrainCollisionBoxes; static bool keyboardAutoAim; static vi2d windowPos; + static IconType iconType; public: static const bool ScreenShakeEnabled(); static const bool RumbleEnabled(); static const bool TerrainCollisionBoxesEnabled(); static const bool KeyboardAutoAimEnabled(); static const vi2d GetWindowPos(); + static const IconType GetIconType(); static void SetScreenShake(bool screenShakeEnabled); static void SetRumble(bool rumbleEnabled); static void SetTerrainCollisionBoxes(bool terrainCollisionBoxesEnabled); static void SetKeyboardAutoAim(bool autoAimEnabled); static void SetWindowPos(vi2d windowPos); + static void SetIconType(IconType type); + static void Initialize(); }; \ No newline at end of file diff --git a/Adventures in Lestoria/IconType.h b/Adventures in Lestoria/IconType.h new file mode 100644 index 00000000..feae4fb2 --- /dev/null +++ b/Adventures in Lestoria/IconType.h @@ -0,0 +1,44 @@ +#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 © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once + +enum class IconType{ + XB, + PS, + XB_REVERSED, +}; \ No newline at end of file diff --git a/Adventures in Lestoria/InputHelper.cpp b/Adventures in Lestoria/InputHelper.cpp index ef495764..d78e9ae1 100644 --- a/Adventures in Lestoria/InputHelper.cpp +++ b/Adventures in Lestoria/InputHelper.cpp @@ -39,6 +39,7 @@ All rights reserved. #include "AdventuresInLestoria.h" #include "Menu.h" #include "MenuComponent.h" +#include "GameSettings.h" INCLUDE_game INCLUDE_GFX @@ -79,7 +80,6 @@ void InputHelper::Draw(){ std::vectorbuttonDescriptions; #pragma region Populate all buttons to display for(auto&[group,display]:inputGroups){ - size_t groupedInputCount=1; std::vectorinputGroupsToCheck; if(std::holds_alternative(display)&&groupedInputs.count(std::get(display))){ @@ -108,6 +108,10 @@ void InputHelper::Draw(){ auto&primaryKey=group.GetPrimaryKey(mode); if(displayName.length()>0&&primaryKey.has_value()){ + if(primaryKey.value().HasExtendedIcons()){//This means it follows the specialized icon controller schemes, now pick based on these icons. + buttonImgWidth+=primaryKey.value().GetIcon(GameSettings::GetIconType()).Sprite()->width+"Interface.InputHelperSpacing"_I; + iconList.push_back(primaryKey.value().GetIcon(GameSettings::GetIconType()).Decal()); + }else if(primaryKey.value().HasIcon()){ buttonImgWidth+=primaryKey.value().GetIcon().Sprite()->width+"Interface.InputHelperSpacing"_I; iconList.push_back(primaryKey.value().GetIcon().Decal()); diff --git a/Adventures in Lestoria/InputKeyboardWindow.cpp b/Adventures in Lestoria/InputKeyboardWindow.cpp index a431c151..22fb7bed 100644 --- a/Adventures in Lestoria/InputKeyboardWindow.cpp +++ b/Adventures in Lestoria/InputKeyboardWindow.cpp @@ -57,7 +57,7 @@ void Menu::InitializeKeyboardInputWindow(){ inputKeyboardWindow->ADD("Keyboard Mapping Label",MenuLabel)(geom2d::rect{{4,0},{menuSize.x-8.f,24.f}},"Keyboard Mappings",2.f,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; - inputKeyboardWindow->ADD("Menu Inputs Background",MenuLabel)(geom2d::rect{{4,32},{menuSize.x-8,56.f}},"",1.f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; + inputKeyboardWindow->ADD("Menu Inputs Background",MenuLabel)(geom2d::rect{{4,32},{menuSize.x-8,65.f}},"",1.f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1; const int menuColCount=2; @@ -91,7 +91,7 @@ void Menu::InitializeKeyboardInputWindow(){ } } - inputKeyboardWindow->ADD("Controller Inputs Background",MenuLabel)(geom2d::rect{{4,100},{menuSize.x-8,68.f}},"",1.f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; + inputKeyboardWindow->ADD("Controller Inputs Background",MenuLabel)(geom2d::rect{{4,100},{menuSize.x-8,65.f}},"",1.f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1; const int ingameControlsColCount=2; @@ -126,4 +126,19 @@ void Menu::InitializeKeyboardInputWindow(){ Menu::CloseMenu(); return true; })END; + + inputKeyboardWindow->SetupKeyboardNavigation( + [](MenuType type,Data&returnData){ //On Open + returnData="Input_0_0 Input Displayer"; + }, + { //Button Key + {game->KEY_SCROLL,{"Navigate",[](MenuType type){}}}, + {game->KEY_BACK,{"Back",[](MenuType type){ + Menu::CloseMenu(); + }}}, + {game->KEY_CONFIRM,{"Select",[](MenuType type){}}}, + } + ,{ //Button Navigation Rules + + }); } \ No newline at end of file diff --git a/Adventures in Lestoria/InventoryConsumableWindow.cpp b/Adventures in Lestoria/InventoryConsumableWindow.cpp index ddd5dce6..5efb0f45 100644 --- a/Adventures in Lestoria/InventoryConsumableWindow.cpp +++ b/Adventures in Lestoria/InventoryConsumableWindow.cpp @@ -121,6 +121,12 @@ void Menu::InitializeConsumableInventoryWindow(){ {game->KEY_BACK,{"Back",[](MenuType type){ Menu::CloseMenu(); }}}, + {game->KEY_START,{"Set Loadout Item",[](MenuType type){ + if(!Menu::menus[type]->GetSelection().expired()&& + !Menu::menus[type]->GetSelection().lock()->parentComponent.expired()){ + Menu::menus[type]->GetSelection().lock()->Click(); + } + }}}, {game->KEY_CONFIRM,{"Set Loadout Item",[](MenuType type){}}}, } ,{ //Button Navigation Rules diff --git a/Adventures in Lestoria/InventoryWindow.cpp b/Adventures in Lestoria/InventoryWindow.cpp index bee58797..fde8599c 100644 --- a/Adventures in Lestoria/InventoryWindow.cpp +++ b/Adventures in Lestoria/InventoryWindow.cpp @@ -97,7 +97,9 @@ void Menu::InitializeInventoryWindow(){ if(data.menu.I(A::ITEM_SLOT)>=0){ data.menu.SetSelection(Component(data.menu.GetType(),"Inventory Display - "+data.component.lock()->S(A::CATEGORY_NAME))->GetComponents()[0],true); } - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } return true; },vf2d{textScaling,1.f})END; button->SetSelectionType(HIGHLIGHT); diff --git a/Adventures in Lestoria/ItemLoadoutWindow.cpp b/Adventures in Lestoria/ItemLoadoutWindow.cpp index 3bb6401a..548802bd 100644 --- a/Adventures in Lestoria/ItemLoadoutWindow.cpp +++ b/Adventures in Lestoria/ItemLoadoutWindow.cpp @@ -64,7 +64,8 @@ void Menu::InitializeItemLoadoutWindow(){ Component(ITEM_LOADOUT,"Item Name Label")->SetLabel(""); Component(ITEM_LOADOUT,"Item Description")->SetLabel(""); return true; - },"Item Name Label","Item Description")END; + },"Item Name Label","Item Description")END + ->SetIconScale({2.f,2.f}); itemLoadoutWindow->ADD("Loadout Item 2",MenuItemItemButton)(geom2d::rect{{itemLoadoutWindowWidth/2-24,84},{48,48}},game->GetLoadoutItem(1),[](MenuFuncData data){ Menu::menus.at(INVENTORY_CONSUMABLES)->I(A::LOADOUT_SLOT)=1; Menu::OpenMenu(INVENTORY_CONSUMABLES); @@ -75,7 +76,8 @@ void Menu::InitializeItemLoadoutWindow(){ Component(ITEM_LOADOUT,"Item Name Label")->SetLabel(""); Component(ITEM_LOADOUT,"Item Description")->SetLabel(""); return true; - },"Item Name Label","Item Description")END; + },"Item Name Label","Item Description")END + ->SetIconScale({2.f,2.f}); itemLoadoutWindow->ADD("Loadout Item 3",MenuItemItemButton)(geom2d::rect{{itemLoadoutWindowWidth-48-64,84},{48,48}},game->GetLoadoutItem(2),[](MenuFuncData data){ Menu::menus.at(INVENTORY_CONSUMABLES)->I(A::LOADOUT_SLOT)=2; Menu::OpenMenu(INVENTORY_CONSUMABLES); @@ -86,7 +88,8 @@ void Menu::InitializeItemLoadoutWindow(){ Component(ITEM_LOADOUT,"Item Name Label")->SetLabel(""); Component(ITEM_LOADOUT,"Item Description")->SetLabel(""); return true; - },"Item Name Label","Item Description")END; + },"Item Name Label","Item Description")END + ->SetIconScale({2.f,2.f}); itemLoadoutWindow->ADD("Item Name Label",MenuLabel)(geom2d::rect{{0,146},{itemLoadoutWindowWidth,12}},"",1,ComponentAttr::SHADOW)END; itemLoadoutWindow->ADD("Item Description",MenuLabel)(geom2d::rect{{0,158},{itemLoadoutWindowWidth,24}},"",1,ComponentAttr::SHADOW)END; diff --git a/Adventures in Lestoria/Key.cpp b/Adventures in Lestoria/Key.cpp index b7edd338..c84f1548 100644 --- a/Adventures in Lestoria/Key.cpp +++ b/Adventures in Lestoria/Key.cpp @@ -400,9 +400,27 @@ void InputGroup::DrawInput(const std::variant0; } +const bool Input::HasExtendedIcons()const{ + return GenericKey::keyLiteral.at({type,key}).iconName.length()>0&&GenericKey::keyLiteral.at({type,key}).iconName2.length()>0&&GenericKey::keyLiteral.at({type,key}).iconName3.length()>0; +} const Renderable&Input::GetIcon()const{ return GFX.at(GenericKey::keyLiteral.at({type,key}).iconName); } +const Renderable&Input::GetIcon(IconType type)const{ + switch(type){ + case IconType::XB:{ + return GFX.at(GenericKey::keyLiteral.at({this->type,key}).iconName); + }break; + case IconType::PS:{ + return GFX.at(GenericKey::keyLiteral.at({this->type,key}).iconName2); + }break; + case IconType::XB_REVERSED:{ + return GFX.at(GenericKey::keyLiteral.at({this->type,key}).iconName3); + }break; + } + ERR("WARNING! Did not handle a valid controller icon type. THIS SHOULD NOT BE HAPPENING!"); + return GFX.at("themes/button_d_xb.png"); +} #undef END @@ -510,10 +528,10 @@ std::map,GenericKey::KeyInfo> GenericKey::keyLiteral={ {{MOUSE, Mouse::LEFT},{"L.MOUSE","themes/lmb.png"}}, {{MOUSE, Mouse::RIGHT},{"R.MOUSE","themes/rmb.png"}}, {{MOUSE, Mouse::MIDDLE},{"M.MOUSE","themes/mmb.png"}}, - {{CONTROLLER, static_cast(GPButtons::FACE_D)},{"A/X","themes/button_d.png"}}, - {{CONTROLLER, static_cast(GPButtons::FACE_L)},{"X/Square","themes/button_l.png"}}, - {{CONTROLLER, static_cast(GPButtons::FACE_R)},{"B/Circle","themes/button_r.png"}}, - {{CONTROLLER, static_cast(GPButtons::FACE_U)},{"Y/Triangle","themes/button_u.png"}}, + {{CONTROLLER, static_cast(GPButtons::FACE_D)},{"A/X","themes/button_d_xb.png","themes/button_d_ps.png","themes/button_r_xb.png"}}, + {{CONTROLLER, static_cast(GPButtons::FACE_L)},{"X/Square","themes/button_l_xb.png","themes/button_l_ps.png","themes/button_u_xb.png"}}, + {{CONTROLLER, static_cast(GPButtons::FACE_R)},{"B/Circle","themes/button_r_xb.png","themes/button_r_ps.png","themes/button_d_xb.png"}}, + {{CONTROLLER, static_cast(GPButtons::FACE_U)},{"Y/Triangle","themes/button_u_xb.png","themes/button_u_ps.png","themes/button_l_xb.png"}}, {{CONTROLLER, static_cast(GPButtons::L1)},{"L1","themes/button_l1.png"}}, {{CONTROLLER, static_cast(GPButtons::L2)},{"L2","themes/button_l2.png"}}, {{CONTROLLER, static_cast(GPButtons::L3)},{"L3"}}, @@ -648,23 +666,28 @@ void InputGroup::SetNewPrimaryKeybind(Input key){ void InputListener::Update(){ #pragma region New controller input binding listener using A=Attribute; - if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]&&!Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){ //We are requesting a brand new controller input. - if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){ - for(GamePad*gamepad:GamePad::getGamepads()){ - for(size_t button=0;bool hasButton:gamepad->availableButtons){ - GPButtons releasedButton=olc::GPButtons(button); - if(gamepad->getButton(releasedButton).bReleased){ - InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->SetNewPrimaryKeybind(Input{CONTROLLER,int(button)}); - for(auto&[menuType,menu]:Menu::menus){ - menu->helpDisplay.Initialize(menu->inputGroups); + if(Menu::IsMenuOpen()&&Menu::stack.back()==Menu::menus[NEW_INPUT]){ + if(!Menu::menus[NEW_INPUT]->B(A::IS_KEYBOARD)){//We are requesting a brand new controller input. + if(InputGroup::menuNamesToInputGroups.count(Menu::menus[NEW_INPUT]->S(A::KEYBIND))){ + for(GamePad*gamepad:GamePad::getGamepads()){ + for(size_t button=0;bool hasButton:gamepad->availableButtons){ + GPButtons releasedButton=olc::GPButtons(button); + if(gamepad->getButton(releasedButton).bReleased){ + InputGroup::menuNamesToInputGroups[Menu::menus[NEW_INPUT]->S(A::KEYBIND)]->SetNewPrimaryKeybind(Input{CONTROLLER,int(button)}); + for(auto&[menuType,menu]:Menu::menus){ + menu->helpDisplay.Initialize(menu->inputGroups); + } + Menu::alreadyClicked=true; + Menu::CloseMenu(); + return; } - Menu::alreadyClicked=true; - Menu::CloseMenu(); - return; + button++; } - button++; } } + }else{ + Menu::alreadyClicked=true; + Menu::CloseMenu(); } } #pragma endregion diff --git a/Adventures in Lestoria/Key.h b/Adventures in Lestoria/Key.h index d1918de8..489c7333 100644 --- a/Adventures in Lestoria/Key.h +++ b/Adventures in Lestoria/Key.h @@ -43,6 +43,7 @@ All rights reserved. #include "safemap.h" #include "olcPGEX_TransformedView.h" #include +#include "IconType.h" class AiL; @@ -80,7 +81,9 @@ public: const InputType GetType()const; const std::string str()const; const bool HasIcon()const; + const bool HasExtendedIcons()const; //Whether or not this input has extended icons for all the button sets (See IconType.h) const Renderable&GetIcon()const; + const Renderable&GetIcon(IconType type)const; const int GetKeyCode()const; friend const bool operator==(const Input&input1,const Input&input2); }; @@ -147,7 +150,9 @@ public: class GenericKey{ struct KeyInfo{ std::string displayName; - std::string iconName; + std::string iconName=""; + std::string iconName2=""; + std::string iconName3=""; }; public: static std::map,KeyInfo>keyLiteral; //The displayed text for a given key for a given input type. diff --git a/Adventures in Lestoria/LoadGameWindow.cpp b/Adventures in Lestoria/LoadGameWindow.cpp index 51c64414..09088549 100644 --- a/Adventures in Lestoria/LoadGameWindow.cpp +++ b/Adventures in Lestoria/LoadGameWindow.cpp @@ -56,7 +56,9 @@ void Menu::InitializeLoadGameWindow(){ Component(data.menu.GetType(),"Online Game Files List")->Disable(); Component(data.menu.GetType(),"Online Character Tab")->SetSelected(false); data.component.lock()->SetSelected(true); - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } SaveFile::SetOnlineMode(false); if(Component(data.menu.GetType(),"Game Files List")->GetComponents().size()>0){ data.menu.SetSelection(Component(data.menu.GetType(),"Game Files List")->GetComponents()[0],true); @@ -69,7 +71,9 @@ void Menu::InitializeLoadGameWindow(){ Component(data.menu.GetType(),"Game Files List")->Disable(); Component(data.menu.GetType(),"Online Game Files List")->Enable(); Component(data.menu.GetType(),"Offline Character Tab")->SetSelected(false); - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } data.component.lock()->SetSelected(true); if(!SaveFile::IsOnline()){ if(SaveFile::GetUserID().length()==0){ @@ -137,10 +141,16 @@ void Menu::InitializeLoadGameWindow(){ {{game->KEY_SHOULDER,Pressed},{"Scroll",[](MenuType type){}}}, {{game->KEY_FASTSCROLLDOWN,PressedDAS,InputEngageGroup::NOT_VISIBLE},{"Scroll",[](MenuType type){ auto gameFilesList=Component(type,"Game Files List"); + if(!Component(type,"Offline Character Tab")->selected){ + gameFilesList=Component(type,"Online Game Files List"); + } gameFilesList->IncreaseSelectionIndex(3.f); }}}, {{game->KEY_FASTSCROLLUP,PressedDAS,InputEngageGroup::NOT_VISIBLE},{"Scroll",[](MenuType type){ auto gameFilesList=Component(type,"Game Files List"); + if(!Component(type,"Offline Character Tab")->selected){ + gameFilesList=Component(type,"Online Game Files List"); + } gameFilesList->IncreaseSelectionIndex(-3.f); }}}, } diff --git a/Adventures in Lestoria/Menu.cpp b/Adventures in Lestoria/Menu.cpp index efd109db..a00ff3a2 100644 --- a/Adventures in Lestoria/Menu.cpp +++ b/Adventures in Lestoria/Menu.cpp @@ -374,17 +374,6 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){ if(navigationGroups.count(selectionButtonName)){ Navigation nav=navigationGroups[selectionButtonName]; - if(selection.lock()->IsGreyedOut()||selection.lock()->IsDisabled()){ - // If the button is greyed out or disabled, this is an invalid selection. We will try to reset to a default, but we need to break out of this loop. - if(onOpenFunc){ - Data returnData; - onOpenFunc(GetType(),returnData); - defaultButton=returnData; - if(std::holds_alternative(returnData)&&std::get(returnData).length()>0||std::holds_alternative>(returnData))SetSelection(returnData,true); - } - break; - } - if(game->KEY_UP.PressedDAS()||game->KEY_SCROLLUP.AnalogDAS(0.5f)<-0.5f){ SoundEffect::PlaySFX("Menu Navigate",SoundEffect::CENTERED); SetMouseNavigation(false); @@ -441,7 +430,18 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){ break; //There's no reason to be doing anything here if we navigate with the mouse. } 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!"); + if(iterationCount==MAX_ITERATIONS){ + if(selection.lock()->IsGreyedOut()||selection.lock()->IsDisabled()){ + // If the button is greyed out or disabled, this is an invalid selection. We will try to reset to a default, but we need to break out of this loop. + if(onOpenFunc){ + Data returnData; + onOpenFunc(GetType(),returnData); + defaultButton=returnData; + if(std::holds_alternative(returnData)&&std::get(returnData).length()>0||std::holds_alternative>(returnData))SetSelection(returnData,true); + } + break; + } + } }while(iterationCountgrayedOut||selection.lock()->disable)); } @@ -770,4 +770,9 @@ void Menu::SetSelection(Data button,const bool reset){ void Menu::IgnoreNextMouseNavigationAttempt(){ nextMouseNavigationIsIgnored=true; +} + +bool Menu::IsCurrentlyActive(MenuType type){ + if(Menu::stack.size()==0)return false; + return Menu::stack.back()->GetType()==type; } \ No newline at end of file diff --git a/Adventures in Lestoria/Menu.h b/Adventures in Lestoria/Menu.h index f47103c4..f5e35f46 100644 --- a/Adventures in Lestoria/Menu.h +++ b/Adventures in Lestoria/Menu.h @@ -198,6 +198,8 @@ public: const std::weak_ptrGetSelection()const; const std::weak_ptrGetKeySelection()const; static void IgnoreNextMouseNavigationAttempt(); + //Returns whether or not this menu type is currently in the foreground of the game, and thus being interacted with by the user. + static bool IsCurrentlyActive(MenuType type); private: Menu(vf2d pos,vf2d size); static MenuType lastMenuTypeCreated; diff --git a/Adventures in Lestoria/MenuComponent.cpp b/Adventures in Lestoria/MenuComponent.cpp index 76754909..80faaa26 100644 --- a/Adventures in Lestoria/MenuComponent.cpp +++ b/Adventures in Lestoria/MenuComponent.cpp @@ -259,7 +259,11 @@ void MenuComponent::OnChapterUpdate(uint8_t newChapter){} void MenuComponent::Click(){ if(grayedOut||disable||disableOutsideWindow)return; - onClick(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name]}); + std::weak_ptrparent; + if(!Menu::menus[parentMenu]->components[name]->parentComponent.expired()){//HACK ALERT! We assume every parent is a scrollable window component. + parent=Menu::menus[parentMenu]->components[name]->parentComponent; + } + onClick(MenuFuncData{*Menu::menus[parentMenu],game,Menu::menus[parentMenu]->components[name],parent}); } void MenuComponent::SetLabel(std::string newLabel){ label=newLabel; diff --git a/Adventures in Lestoria/MenuIconButton.h b/Adventures in Lestoria/MenuIconButton.h index aff4a178..62a62566 100644 --- a/Adventures in Lestoria/MenuIconButton.h +++ b/Adventures in Lestoria/MenuIconButton.h @@ -53,6 +53,7 @@ enum class IconButtonAttr{ class MenuIconButton:public MenuComponent{ protected: Decal*icon; + vf2d iconScale{1,1}; Pixel tint=WHITE; public: inline MenuIconButton(geom2d::rectrect,Decal*icon,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) @@ -60,6 +61,12 @@ public: border=!(attributes&IconButtonAttr::NO_OUTLINE); background=!(attributes&IconButtonAttr::NO_BACKGROUND); } + virtual inline void SetIcon(Decal*newIcon){ + icon=newIcon; + } + virtual inline void SetIconScale(vf2d iconScale){ + this->iconScale=iconScale; + } protected: virtual inline void Update(AiL*game)override{ MenuComponent::Update(game); @@ -67,8 +74,7 @@ protected: virtual inline void DrawDecal(ViewPort&window,bool focused)override{ MenuComponent::DrawDecal(window,focused); if(icon!=nullptr){ - vf2d iconScale=rect.size/24.f; - window.DrawDecal(rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale,tint); + window.DrawRotatedDecal(rect.middle(),icon,0.f,icon->sprite->Size()/2,iconScale,tint); } } }; diff --git a/Adventures in Lestoria/MenuType.h b/Adventures in Lestoria/MenuType.h index 62ef6213..181bfa8d 100644 --- a/Adventures in Lestoria/MenuType.h +++ b/Adventures in Lestoria/MenuType.h @@ -65,7 +65,7 @@ enum MenuType{ SETTINGS, //100% Controller Compatibility SHERMAN, //100% Controller Compatibility INPUT_KEY_DISPLAY, //25% Controller Compatibility - NEW_INPUT, //100% Controller Compatibility + NEW_INPUT, //75% Controller Compatibility PAUSE, //0% Controller Compatibility /////////////////////////////////////////////////////////// /*DO NOT REMOVE!!*/ENUM_END//////////////////////////////// diff --git a/Adventures in Lestoria/MerchantWindow.cpp b/Adventures in Lestoria/MerchantWindow.cpp index 15856164..713fa2a7 100644 --- a/Adventures in Lestoria/MerchantWindow.cpp +++ b/Adventures in Lestoria/MerchantWindow.cpp @@ -78,7 +78,9 @@ void Menu::InitializeMerchantWindow(){ Component(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Disable(); Component(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->Disable(); data.component.lock()->selected=true; - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } return true; })END; buyTab->selected=true; @@ -95,7 +97,9 @@ void Menu::InitializeMerchantWindow(){ Component(data.menu.GetType(),"Inventory Display - "+data.menu.S(A::LAST_INVENTORY_TYPE_OPENED))->Enable(); Component(data.menu.GetType(),data.menu.S(A::LAST_INVENTORY_TYPE_OPENED)+" Inventory Tab")->Enable(); data.component.lock()->selected=true; - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } return true; })END; sellTab->selectionType=SelectionType::HIGHLIGHT; @@ -162,7 +166,9 @@ void Menu::InitializeMerchantWindow(){ if(data.menu.I(A::ITEM_SLOT)>=0){ data.menu.SetSelection(Component(data.menu.GetType(),"Inventory Display - "+data.component.lock()->S(A::CATEGORY_NAME))->GetComponents()[0],true); } - SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + if(Menu::IsCurrentlyActive(data.menu.GetType())){ + SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED); + } return true; },vf2d{textScaling,1.f})END; button->SetSelectionType(HIGHLIGHT); diff --git a/Adventures in Lestoria/SaveFile.cpp b/Adventures in Lestoria/SaveFile.cpp index 6c6a54ed..70c7fcb9 100644 --- a/Adventures in Lestoria/SaveFile.cpp +++ b/Adventures in Lestoria/SaveFile.cpp @@ -125,21 +125,17 @@ const void SaveFile::SaveGame(){ saveFile["Game Time"].SetReal(game->GetRuntime()); saveFile["TravelingMerchant"].SetString(std::string(Merchant::GetCurrentTravelingMerchant().GetKeyName())); - saveFile["Screen Shake"].SetBool(GameSettings::ScreenShakeEnabled()); - saveFile["Controller Rumble"].SetBool(GameSettings::RumbleEnabled()); - saveFile["Terrain Collision Boxes"].SetBool(GameSettings::TerrainCollisionBoxesEnabled()); - saveFile["Keyboard Auto-Aim"].SetBool(GameSettings::KeyboardAutoAimEnabled()); - #pragma region Save Keyboard/Controller mappings //NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well! + //ALSO NOTE: The menu inputs are saved to the system file while gameplay inputs are per-character and saved to the character settings file! const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1; const int menuColCount=2; for(int row=0;row(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(KEY).value().GetKeyCode()); - saveFile["Menu Controller Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(CONTROLLER).value().GetKeyCode()); + saveSystemFile["Menu Keyboard Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(KEY).value().GetKeyCode()); + saveSystemFile["Menu Controller Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(CONTROLLER).value().GetKeyCode()); } } const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1; @@ -155,7 +151,14 @@ const void SaveFile::SaveGame(){ #pragma endregion #pragma region Save System Settings - //HACK ALERT! It's possible that on X11 the actual reported window position is offset later when we set it. We will set it now to see if it moves or adjusts, and use that new position instead as the position we save. + saveSystemFile["BGM Level"].SetReal(Audio::GetBGMVolume()); + saveSystemFile["SFX Level"].SetReal(Audio::GetSFXVolume()); + saveSystemFile["Screen Shake"].SetBool(GameSettings::ScreenShakeEnabled()); + saveSystemFile["Controller Rumble"].SetBool(GameSettings::RumbleEnabled()); + saveSystemFile["Terrain Collision Boxes"].SetBool(GameSettings::TerrainCollisionBoxesEnabled()); + saveSystemFile["Keyboard Auto-Aim"].SetBool(GameSettings::KeyboardAutoAimEnabled()); + saveSystemFile["Controller Icons"].SetInt(int(GameSettings::GetIconType())); + saveSystemFile["Window Pos"].SetInt(game->GetActualWindowPos().x,0); saveSystemFile["Window Pos"].SetInt(game->GetActualWindowPos().y,1); saveSystemFile["Window Size"].SetInt(game->GetWindowSize().x,0); @@ -238,6 +241,22 @@ const void SaveFile::SaveGame(){ metafile.close(); } + std::stringstream systemFileContents; + std::ifstream systemfile("save_file_path"_S+"system.conf"); + while(systemfile.good()){ + int val=systemfile.get(); + if(val!=-1){ + systemFileContents<GetPlayer()->RecalculateEquipStats(); if(loadFile.HasProperty("TravelingMerchant"))Merchant::SetTravelingMerchant(loadFile["TravelingMerchant"].GetString()); - if(loadFile.HasProperty("Screen Shake"))GameSettings::SetScreenShake(loadFile["Screen Shake"].GetBool()); - if(loadFile.HasProperty("Controller Rumble"))GameSettings::SetRumble(loadFile["Controller Rumble"].GetBool()); - if(loadFile.HasProperty("Terrain Collision Boxes"))GameSettings::SetTerrainCollisionBoxes(loadFile["Terrain Collision Boxes"].GetBool()); - if(loadFile.HasProperty("Keyboard Auto-Aim"))GameSettings::SetKeyboardAutoAim(loadFile["Keyboard Auto-Aim"].GetBool()); - #pragma region Load Keyboard/Controller mappings //NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well! - const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1; - const int menuColCount=2; - for(int row=0;row(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput(); - group.SetNewPrimaryKeybind({KEY,loadFile[keyName].GetInt()}); - } - keyName="Menu Controller Input_"+"Inputs.Menu Input Names"_s[inputID]; - if(loadFile.HasProperty(keyName)){ - InputGroup&group=Component(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput(); - group.SetNewPrimaryKeybind({CONTROLLER,loadFile[keyName].GetInt()}); - } - } - } const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1; const int ingameControlsColCount=2; for(int row=0;rowADD("Unlock All Button",MenuComponent)(geom2d::rect{{4,windowSize.y-12},{72,12}},"Unlock All",[](MenuFuncData data){ - for(auto&cp:State_OverworldMap::connections){ - Unlock::UnlockArea(cp.map); + settingsWindow->ADD("Unlock All Button",MenuComponent)(geom2d::rect{{4,windowSize.y-20},{72,12}},"Unlock All",[](MenuFuncData data){ + if(Menu::IsCurrentlyActive(SETTINGS)){ + for(auto&cp:State_OverworldMap::connections){ + Unlock::UnlockArea(cp.map); + } + SoundEffect::PlaySFX("Buy Item",SoundEffect::CENTERED); } - SoundEffect::PlaySFX("Buy Item",SoundEffect::CENTERED); return true; })END; @@ -74,16 +77,20 @@ void Menu::InitializeSettingsWindow(){ settingsWindow->F(A::LAST_SFX_VOLUME)=1.f; settingsWindow->ADD("BGM Slider",Slider)(geom2d::rect{vf2d{windowSize.x/2-64,32},{172,16}},"BGM Volume:",Audio::GetBGMVolume(),[](float val){ - if(abs(Menu::menus[SETTINGS]->F(A::LAST_BGM_VOLUME)-val)>=0.04f){ - SoundEffect::PlaySFX("Change Volume",SoundEffect::CENTERED); - Menu::menus[SETTINGS]->F(A::LAST_BGM_VOLUME)=val; + if(Menu::IsCurrentlyActive(SETTINGS)){ + if(abs(Menu::menus[SETTINGS]->F(A::LAST_BGM_VOLUME)-val)>=0.04f){ + SoundEffect::PlaySFX("Change Volume",SoundEffect::CENTERED); + Menu::menus[SETTINGS]->F(A::LAST_BGM_VOLUME)=val; + } + Audio::SetBGMVolume(val); } - Audio::SetBGMVolume(val); })END; settingsWindow->ADD("SFX Slider",Slider)(geom2d::rect{vf2d{windowSize.x/2-64,52},{172,16}},"SFX Volume:",Audio::GetSFXVolume(),[](float val){ - if(abs(Menu::menus[SETTINGS]->F(A::LAST_SFX_VOLUME)-val)>=0.04f){ - SoundEffect::PlaySFX("Change Volume",SoundEffect::CENTERED); - Menu::menus[SETTINGS]->F(A::LAST_SFX_VOLUME)=val; + if(Menu::IsCurrentlyActive(SETTINGS)){ + if(abs(Menu::menus[SETTINGS]->F(A::LAST_SFX_VOLUME)-val)>=0.04f){ + SoundEffect::PlaySFX("Change Volume",SoundEffect::CENTERED); + Menu::menus[SETTINGS]->F(A::LAST_SFX_VOLUME)=val; + } } })END; settingsWindow->ADD("Screen Shake Checkbox",Checkbox)(geom2d::rect{{4.f,72},{16.f,16.f}},[](ToggleFuncData data){ @@ -92,12 +99,14 @@ void Menu::InitializeSettingsWindow(){ },true)END; settingsWindow->ADD("Screen Shake Label",MenuLabel)(geom2d::rect{{22.f,72},{windowSize.x/2-24.f,16.f}},"Screen Shake",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; settingsWindow->ADD("Controller Rumble Checkbox",Checkbox)(geom2d::rect{{4.f,92},{16.f,16.f}},[](ToggleFuncData data){ - GameSettings::SetRumble(data.checked); - if(GameSettings::RumbleEnabled()){ - Input::StartVibration(); - data.component.lock()->F(A::RUMBLE_TIMER)=0.3f; - }else{ - Input::StopVibration(); + if(Menu::IsCurrentlyActive(SETTINGS)){ + GameSettings::SetRumble(data.checked); + if(GameSettings::RumbleEnabled()){ + Input::StartVibration(); + data.component.lock()->F(A::RUMBLE_TIMER)=0.3f; + }else{ + Input::StopVibration(); + } } return true; },true)END; @@ -129,6 +138,27 @@ void Menu::InitializeSettingsWindow(){ fullscreenToggle->Disable(); fullscreenToggleLabel->Disable(); #endif + + settingsWindow->ADD("Button Set Toggle Box",MenuIconButton)(geom2d::rect{{windowSize.x/8.f,112},{windowSize.x/4.f,16.f}},GFX["themes/xb.png"].Decal(),[](MenuFuncData data){ + switch(GameSettings::GetIconType()){ + case IconType::XB:{ + GameSettings::SetIconType(IconType::PS); + DYNAMIC_POINTER_CAST(data.component)->SetIcon(GFX["themes/ps.png"].Decal()); + }break; + case IconType::PS:{ + GameSettings::SetIconType(IconType::XB_REVERSED); + DYNAMIC_POINTER_CAST(data.component)->SetIcon(GFX["themes/xb_reversed.png"].Decal()); + }break; + case IconType::XB_REVERSED:{ + GameSettings::SetIconType(IconType::XB); + DYNAMIC_POINTER_CAST(data.component)->SetIcon(GFX["themes/xb.png"].Decal()); + }break; + default:{ + ERR(std::format("WARNING! Unhandled icon type {}!",int(GameSettings::GetIconType()))); + } + } + return true; + })END; #pragma region Setup all input displays as keyboard controls. //NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well! @@ -165,7 +195,7 @@ void Menu::InitializeSettingsWindow(){ return true; },vf2d{1.5f,2.f})END; - settingsWindow->ADD("Go Back",MenuComponent)(geom2d::rect{vf2d{windowSize.x/2.f,windowSize.y-12}-vf2d{36,4},{72,12}},"Go Back",[](MenuFuncData data){ + settingsWindow->ADD("Go Back",MenuComponent)(geom2d::rect{vf2d{windowSize.x/2.f,windowSize.y-12}-vf2d{36,8},{72,12}},"Go Back",[](MenuFuncData data){ Menu::CloseMenu(); return true; })END; @@ -205,16 +235,25 @@ void Menu::InitializeSettingsWindow(){ .right="Terrain Collision Boxes Checkbox",}}, {"Controller Rumble Checkbox",{ .up="Screen Shake Checkbox", - .down="Fullscreen Toggle Checkbox", + .down="Button Set Toggle Box", .left="Keyboard Play Auto-Aim Checkbox", .right="Keyboard Play Auto-Aim Checkbox",}}, + {"Button Set Toggle Box",{ + .up="Controller Rumble Checkbox", + .down="Keyboard Bindings Button", + .left="Fullscreen Toggle Checkbox", + .right="Fullscreen Toggle Checkbox",}}, {"Fullscreen Toggle Checkbox",{ .up="Keyboard Play Auto-Aim Checkbox", .down="Keyboard Bindings Button", - .left="Controller Rumble Checkbox", - .right="Controller Rumble Checkbox",}}, + .left="Button Set Toggle Box", + .right="Button Set Toggle Box",}}, {"Keyboard Bindings Button",{ - .up="Fullscreen Toggle Checkbox", + #ifdef __EMSCRIPTEN__ + .up="Button Set Toggle Box", + #else + .up="Fullscreen Toggle Checkbox", + #endif .down="Controller Bindings Button",}}, {"Controller Bindings Button",{ .up="Keyboard Bindings Button", diff --git a/Adventures in Lestoria/SoundEffect.cpp b/Adventures in Lestoria/SoundEffect.cpp index 514a01c8..a5e673c8 100644 --- a/Adventures in Lestoria/SoundEffect.cpp +++ b/Adventures in Lestoria/SoundEffect.cpp @@ -88,7 +88,7 @@ void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){ float pitch=util::random(pitchDiff)+sfx.minPitch; if(pos==CENTERED){ - Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),sfx.vol*Audio::GetSFXVolume(),0.0f,pitch); + Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),sfx.vol*Audio::GetSFXVolume()*Audio::GetMuteMult(),0.0f,pitch); }else{ const float soundActivationRange="Audio.Environmental Audio Activation Range"_F; @@ -97,7 +97,7 @@ void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){ float distRatio=1-distanceFromPlayer/soundActivationRange; //0-1 where 1 is full volume. float xDistRatio=(pos.x-game->GetPlayer()->GetX())/soundActivationRange; //0-1 where 1 is full volume. - float vol=distRatio*sfx.vol*Audio::GetSFXVolume(); + float vol=distRatio*sfx.vol*Audio::GetSFXVolume()*Audio::GetMuteMult(); float pan=xDistRatio; Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),vol,pan,pitch); } diff --git a/Adventures in Lestoria/State_MainMenu.cpp b/Adventures in Lestoria/State_MainMenu.cpp index fcbc367f..b6d2e7ee 100644 --- a/Adventures in Lestoria/State_MainMenu.cpp +++ b/Adventures in Lestoria/State_MainMenu.cpp @@ -53,8 +53,6 @@ void State_MainMenu::OnUserUpdate(AiL*game){ if(AiL::KEY_CONFIRM.Released()){ TitleScreen::Skip(); } - if(game->GetKey(W).bPressed)game->SetWindowPos({5200,60}); - if(game->GetKey(S).bPressed)game->SetWindowSize({400,400}); }; void State_MainMenu::Draw(AiL*game){ TitleScreen::Draw(); diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index 3d109d9b..2248f7a8 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -8,7 +8,7 @@ January 1st - Track items used during a stage, on death, restore the loadout item quantities used. - Toggle between Playstation / Xbox controller gamepad displays -- Rebind FACELEFT/FACERIGHT menu keys (as they are used constantly throughout menus and would need to be rebinded if the player wants). (Or make confirm/back not rebindable) +- Rebind FACELEFT/FACERIGHT menu keys Open window to the correct position/size at the beginning of the game if possible. @@ -31,6 +31,4 @@ January 31st - Auto aim causes retreat-type moves to aim away from the auto target, and prefer the direction the player's moving in. -- Condense stage track (loading times) - -- If you enter the keyboard config menu and press a controller button, it cancels the request. If you enter the controller config menu and press a keyboard/mouse button, it also cancels the request. \ No newline at end of file +- Condense stage track (loading times) \ No newline at end of file diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 82ec4dac..d89cb9d3 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 7393 +#define VERSION_BUILD 7420 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/gfx/gfx.txt b/Adventures in Lestoria/assets/config/gfx/gfx.txt index ebccaba3..9fb5573f 100644 --- a/Adventures in Lestoria/assets/config/gfx/gfx.txt +++ b/Adventures in Lestoria/assets/config/gfx/gfx.txt @@ -52,14 +52,21 @@ Images GFX_AimingLine = aiming_line.png GFX_Button_AnalogStick_Horz = themes/button_analogstick_horz.png GFX_Button_AnalogStick_Vert = themes/button_analogstick_vert.png - GFX_Button_Face_Down = themes/button_d.png - GFX_Button_Face_Left = themes/button_l.png - GFX_Button_Face_Right = themes/button_r.png - GFX_Button_Face_Up = themes/button_u.png + GFX_Button_Face_Down = themes/button_d_xb.png + GFX_Button_Face_Left = themes/button_l_xb.png + GFX_Button_Face_Right = themes/button_r_xb.png + GFX_Button_Face_Up = themes/button_u_xb.png + GFX_Button_Face_Down2 = themes/button_d_ps.png + GFX_Button_Face_Left2 = themes/button_l_ps.png + GFX_Button_Face_Right2 = themes/button_r_ps.png + GFX_Button_Face_Up2 = themes/button_u_ps.png GFX_Button_Face_L1 = themes/button_l1.png GFX_Button_Face_L2 = themes/button_l2.png GFX_Button_Face_R1 = themes/button_r1.png GFX_Button_Face_R2 = themes/button_r2.png + GFX_Button_SetXB = themes/xb.png + GFX_Button_SetPS = themes/ps.png + GFX_Button_SetXB_Reversed = themes/xb_reversed.png GFX_LMB = themes/lmb.png GFX_RMB = themes/rmb.png GFX_MMB = themes/mmb.png diff --git a/Adventures in Lestoria/assets/config/settings/input.txt b/Adventures in Lestoria/assets/config/settings/input.txt index f63bb5a7..d69b1461 100644 --- a/Adventures in Lestoria/assets/config/settings/input.txt +++ b/Adventures in Lestoria/assets/config/settings/input.txt @@ -1,8 +1,8 @@ Inputs { - Menu Input Names = Confirm, Back, Menu, Up, Right, Down, Left + Menu Input Names = Confirm, Back, Function 1, Function 2, Menu, Up, Right, Down, Left - Gameplay Input Names = Basic Attack, Ability 1, Ability 2, Ability 3, Ability 4, Defensive, Item 1, Item 2, Item 3 + Gameplay Input Names = Basic Attack, Defensive, Ability 1, Ability 2, Ability 3, Ability 4, Item 1, Item 2, Item 3 KEY_CONFIRM = Confirm @@ -14,6 +14,8 @@ Inputs KEY_DOWN=Down KEY_MENU=Menu KEY_BACK=Back + KEY_FACELEFT=Function 2 + KEY_FACEUP=Function 1 Player::KEY_ABILITY1=Ability 1 Player::KEY_ABILITY2=Ability 2 Player::KEY_ABILITY3=Ability 3 diff --git a/Adventures in Lestoria/assets/themes/button_d_ps.png b/Adventures in Lestoria/assets/themes/button_d_ps.png new file mode 100644 index 00000000..84b4f54c Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_d_ps.png differ diff --git a/Adventures in Lestoria/assets/themes/button_d_xb.png b/Adventures in Lestoria/assets/themes/button_d_xb.png new file mode 100644 index 00000000..dfb40ad6 Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_d_xb.png differ diff --git a/Adventures in Lestoria/assets/themes/button_l_ps.png b/Adventures in Lestoria/assets/themes/button_l_ps.png new file mode 100644 index 00000000..afbfbdce Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_l_ps.png differ diff --git a/Adventures in Lestoria/assets/themes/button_l_xb.png b/Adventures in Lestoria/assets/themes/button_l_xb.png new file mode 100644 index 00000000..3aaef539 Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_l_xb.png differ diff --git a/Adventures in Lestoria/assets/themes/button_r_ps.png b/Adventures in Lestoria/assets/themes/button_r_ps.png new file mode 100644 index 00000000..64e33cf0 Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_r_ps.png differ diff --git a/Adventures in Lestoria/assets/themes/button_r_xb.png b/Adventures in Lestoria/assets/themes/button_r_xb.png new file mode 100644 index 00000000..30920b9d Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_r_xb.png differ diff --git a/Adventures in Lestoria/assets/themes/button_u_ps.png b/Adventures in Lestoria/assets/themes/button_u_ps.png new file mode 100644 index 00000000..1fe01e56 Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_u_ps.png differ diff --git a/Adventures in Lestoria/assets/themes/button_u_xb.png b/Adventures in Lestoria/assets/themes/button_u_xb.png new file mode 100644 index 00000000..1f2c1ce0 Binary files /dev/null and b/Adventures in Lestoria/assets/themes/button_u_xb.png differ diff --git a/Adventures in Lestoria/assets/themes/ps.png b/Adventures in Lestoria/assets/themes/ps.png new file mode 100644 index 00000000..672258bc Binary files /dev/null and b/Adventures in Lestoria/assets/themes/ps.png differ diff --git a/Adventures in Lestoria/assets/themes/xb.png b/Adventures in Lestoria/assets/themes/xb.png new file mode 100644 index 00000000..a6ab577f Binary files /dev/null and b/Adventures in Lestoria/assets/themes/xb.png differ diff --git a/Adventures in Lestoria/assets/themes/xb_reversed.png b/Adventures in Lestoria/assets/themes/xb_reversed.png new file mode 100644 index 00000000..0f80f993 Binary files /dev/null and b/Adventures in Lestoria/assets/themes/xb_reversed.png differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index f604c861..e0ee391d 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ