diff --git a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj index c4629b3c..44b7f380 100644 --- a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj +++ b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj @@ -105,6 +105,10 @@ + + + + diff --git a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters index 801e3a76..a1675d57 100644 --- a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters +++ b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters @@ -72,5 +72,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Adventures in Lestoria Tests/EngineTests.cpp b/Adventures in Lestoria Tests/EngineTests.cpp new file mode 100644 index 00000000..41499a62 --- /dev/null +++ b/Adventures in Lestoria Tests/EngineTests.cpp @@ -0,0 +1,90 @@ +#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 + +#include "CppUnitTest.h" +#include "AdventuresInLestoria.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + + +namespace EngineTests +{ + TEST_CLASS(EngineTest) + { + public: + std::unique_ptrtestGame; + TEST_METHOD_INITIALIZE(PlayerInitialize){ + testGame.reset(new AiL(true)); + } + TEST_METHOD(StripLeadingColorTest){ + std::string noColCode{"Hello World!"}; + Assert::AreEqual("Hello World!"s,testGame->stripLeadingCol(noColCode),L"Function should not strip out any text when there's no color codes."); + std::string leadingColCode{"#FFFFFFHello World!"}; + Assert::AreEqual("Hello World!"s,testGame->stripLeadingCol(leadingColCode),L"Function should strip out color code at beginning of text."); + std::string extraColCodes{"#FFFFFFHello #00FF00World!"}; + Assert::AreEqual("Hello #00FF00World!"s,testGame->stripLeadingCol(extraColCodes),L"Function should only strip out color code at beginning of text."); + std::u32string u32noColCode{noColCode.begin(),noColCode.end()}; + std::u32string u32noColCodeResult{testGame->stripLeadingCol(u32noColCode)}; + Assert::AreEqual("Hello World!"s,std::string{u32noColCodeResult.begin(),u32noColCodeResult.end()},L"Function should not strip out any text when there's no color codes."); + std::u32string u32leadingColCode{noColCode.begin(),noColCode.end()}; + std::u32string u32leadingColCodeResult{testGame->stripLeadingCol(u32leadingColCode)}; + Assert::AreEqual("Hello World!"s,std::string{u32leadingColCodeResult.begin(),u32leadingColCodeResult.end()},L"Function should strip out color code at beginning of text."); + std::u32string u32extraColCodes{extraColCodes.begin(),extraColCodes.end()}; + std::u32string u32extraColCodesResult{testGame->stripLeadingCol(u32extraColCodes)}; + Assert::AreEqual("Hello #00FF00World!"s,std::string{u32extraColCodesResult.begin(),u32extraColCodesResult.end()},L"Function should only strip out color code at beginning of text."); + } + TEST_METHOD(GetFinalRenderColorTest){ + Assert::AreEqual(WHITE.n,testGame->GetFinalRenderColor(WHITE,"Hello World!").n,L"Should use source color as there's no HTML color code."); + Assert::AreEqual(BLUE.n,testGame->GetFinalRenderColor(WHITE,"#0000FFHello World!").n,L"Should use color in string since it has a leading HTML color code."); + Assert::AreEqual(BLUE.n,testGame->GetFinalRenderColor(WHITE,"#0000FFHello #00FF00World!").n,L"Should use color in string since it has a leading HTML color code."); + Assert::AreEqual(WHITE.n,testGame->GetFinalRenderColor(WHITE,"Hello #00FF00World!").n,L"Should use color in string since it has a leading HTML color code."); + std::string testStr{"Hello World!"}; + std::u32string u32testStr{testStr.begin(),testStr.end()}; + Assert::AreEqual(WHITE.n,testGame->GetFinalRenderColor(WHITE,testStr).n,L"Should use source color as there's no HTML color code."); + std::string colorCodeStr{"#0000FFHello World!"}; + std::u32string u32colorCodeStr{colorCodeStr.begin(),colorCodeStr.end()}; + Assert::AreEqual(BLUE.n,testGame->GetFinalRenderColor(WHITE,colorCodeStr).n,L"Should use color in string since it has a leading HTML color code."); + std::string extraColorCodeStr{"#0000FFHello #00FF00World!"}; + std::u32string u32extraColorCodeStr{extraColorCodeStr.begin(),extraColorCodeStr.end()}; + Assert::AreEqual(BLUE.n,testGame->GetFinalRenderColor(WHITE,extraColorCodeStr).n,L"Should use color in string since it has a leading HTML color code."); + std::string middleColorCodeStr{"Hello #00FF00World!"}; + std::u32string u32middleColorCodeStr{middleColorCodeStr.begin(),middleColorCodeStr.end()}; + Assert::AreEqual(WHITE.n,testGame->GetFinalRenderColor(WHITE,middleColorCodeStr).n,L"Should use color in string since it has a leading HTML color code."); + } + }; +} \ No newline at end of file diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index 764129ce..0afd4a59 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -1214,6 +1214,7 @@ + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index 796793ae..f1c98153 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -97,6 +97,9 @@ {aaa148fb-5e34-4c35-a5bf-65ee8f2c0fb1} + + {e565fb16-43e6-4d18-a450-af7474df70b9} + @@ -1388,6 +1391,9 @@ Configurations\Items + + Documentation\Admin + diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 24383308..91c37f3d 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -90,6 +90,7 @@ INCLUDE_FOREDROP_DATA INCLUDE_MONSTER_DATA INCLUDE_PACK_KEY +bool ADMIN_MODE = true; //Enables the Unlock All button and admin console. bool _DEBUG_MAP_LOAD_INFO = false; //360x240 vi2d WINDOW_SIZE={24*15,24*10}; @@ -380,12 +381,75 @@ bool AiL::OnUserCreate(){ return true; } +void AiL::AdminConsole(){ + if(ADMIN_MODE){ + if(GetKey(F12).bPressed)ConsoleShow(F12); + } +} + +bool AiL::OnConsoleCommand(const std::string& sCommand){ + std::vectorargs; + size_t marker{}; + std::string acc{}; + bool inQuotationMark{false}; + while(marker0)args.emplace_back(acc); + + if(args.size()>0){ + try{ + if(args[0]=="/help"){ + std::ifstream helpFile("ConsoleCommands.txt"); + while(helpFile.good())ConsoleOut()< [Amount]"<=3)itemAmt=std::stoi(args[2]); + Inventory::AddItem(args[1],itemAmt); + ConsoleOut()<<"Added x"< [Enchant Name]"<accessory{Inventory::AddItem(args[1])}; + if(args.size()>=3)accessory.lock()->EnchantItem(args[2]); + ConsoleOut()<<"Added "<TestingModeEnabled()){ GameState::STATE->Draw(this); RenderMenu(); @@ -404,6 +468,8 @@ bool AiL::OnUserUpdate(float fElapsedTime){ } #endif } + + skipGameProcess: return !gameEnd; } @@ -3550,7 +3616,7 @@ void AiL::RenderMenu(){ if(Menu::alreadyClicked){ //Do not run a click event for this round. Menu::alreadyClicked=false; }else{ - if(!MenuClicksDeactivated()){ + if(!MenuClicksDeactivated()&&!IsConsoleShowing()){ Menu::stack.back()->Update(this); } } @@ -3765,7 +3831,7 @@ void AiL::RenderVersionInfo(){ } std::string versionStr("v" + std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR) + "." + std::to_string(VERSION_PATCH) + "." + std::to_string(VERSION_BUILD)); - DrawShadowStringDecal(vf2d{ GetScreenSize() } - vf2d{ GetTextSize(versionStr) }*0.4f,versionStr,WHITE,BLACK,{0.4f,0.4f},std::numeric_limits::max(),0.4f); + DrawShadowStringDecal(vf2d{ GetScreenSize() } - vf2d{ GetTextSize(versionStr) }*0.4f,versionStr,ADMIN_MODE?RED:WHITE,BLACK,{0.4f,0.4f},std::numeric_limits::max(),0.4f); } int AiL::GetCurrentChapter(){ diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h index 22f0fd9d..44e90bcd 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.h +++ b/Adventures in Lestoria/AdventuresInLestoria.h @@ -227,6 +227,8 @@ private: float zoomAdjustSpeed{0.1f}; std::vector,StackCount,MarkTime>>lockOnTargets; float lastLockOnTargetTime{}; + void AdminConsole(); + virtual bool OnConsoleCommand(const std::string& sCommand)override final; public: AiL(bool testingMode=false); bool OnUserCreate() override; diff --git a/Adventures in Lestoria/ConsoleCommands.txt b/Adventures in Lestoria/ConsoleCommands.txt new file mode 100644 index 00000000..a5ac2811 --- /dev/null +++ b/Adventures in Lestoria/ConsoleCommands.txt @@ -0,0 +1,10 @@ +To open the admin console, press F12 in-game. The admin console is turned on via the ADMIN_MODE variable located in AdventuresInLestoria.cpp + +Required arguments are in <>. Optional arguments are in []. + +Items with spaces must be surrounded in quotation marks "". + +Valid Commands are: +/help - Shows this help file. +/give [Amount] - Gives an item of type into the player's inventory. Optionally adds [Amount] amount of items to the player's inventory. +/accessory [Enchant Name] - Gives an accessory of type into the player's inventory. Optionally adds an enchant of type [Enchant Name]. \ No newline at end of file diff --git a/Adventures in Lestoria/DEFINES.h b/Adventures in Lestoria/DEFINES.h index 2ecf8ac3..3264f37a 100644 --- a/Adventures in Lestoria/DEFINES.h +++ b/Adventures in Lestoria/DEFINES.h @@ -61,6 +61,7 @@ using MonsterSpawnerID=int; #define DO_NOTHING [](MenuFuncData data){return true;} #define INCLUDE_WINDOW_SIZE extern vi2d WINDOW_SIZE; #define INCLUDE_ITEM_CONVERSIONS extern safemapITEM_CONVERSIONS; +#define INCLUDE_ADMIN_MODE extern bool ADMIN_MODE; #define INCLUDE_PACK_KEY extern std::string PACK_KEY; diff --git a/Adventures in Lestoria/Item.cpp b/Adventures in Lestoria/Item.cpp index 5d4bf94d..382427ca 100644 --- a/Adventures in Lestoria/Item.cpp +++ b/Adventures in Lestoria/Item.cpp @@ -700,7 +700,7 @@ const std::string Item::DisplayName()const{ if(IsEquippable()&&EnhancementLevel()>0){ name+=" [#00FF00+"+std::to_string(EnhancementLevel())+"#FFFFFF]"; } - return name; + return GetDisplayNameColor().toHTMLColorCode()+name; } const bool ItemInfo::IsEquippable()const{ return slot!=EquipSlot::NONE&&(category=="Equipment"||category=="Accessories"); @@ -768,6 +768,9 @@ const std::string Item::Description(CompactText compact)const{ } } } + if(HasEnchant()){ + description+=std::format("\n#D48EFF{}\n#E0E0E0{}#FFFFFF",GetEnchant().value().Name(),GetEnchant().value().Description()); + } return description; } const ITCategory Item::Category()const{ @@ -1071,7 +1074,7 @@ const std::string Stats::GetStatsString(const Stats&maxStats,CompactText compact std::string col=""; if(maxStats.attributes.count(attr)&&int(val)>=int(maxStats.attributes.at(attr))){ Pixel shimmeringCol=PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f)); - col=util::PixelToHTMLColorCode(shimmeringCol); + col=shimmeringCol.toHTMLColorCode(); } description+=col+std::string(attr.Name())+": "+statNumber+(attr.DisplayAsPercent()?"%":"")+"#FFFFFF"; @@ -1453,4 +1456,9 @@ std::optionalItem::GetEnchant()const{ } const bool Item::HasEnchant()const{ return enchant.has_value(); +} +const Pixel Item::GetDisplayNameColor()const{ + Pixel col{WHITE}; + if(HasEnchant())col=0xD8BDFF; + return col; } \ No newline at end of file diff --git a/Adventures in Lestoria/Item.h b/Adventures in Lestoria/Item.h index dfd7a95c..5e7e5de6 100644 --- a/Adventures in Lestoria/Item.h +++ b/Adventures in Lestoria/Item.h @@ -188,6 +188,7 @@ private: Stats randomizedStats; bool locked=false; std::optionalenchant; + Pixel displayNameColor{WHITE}; void SetAmt(uint32_t newAmt); static ItemEnhancementFunctionPrimingData enhanceFunctionPrimed; @@ -258,6 +259,7 @@ public: friend const bool operator==(std::weak_ptrlhs,const IT&rhs){return !lhs.expired()&&lhs.lock()->ActualName()==const_cast(rhs);}; friend const bool operator==(const IT&lhs,std::weak_ptrrhs){return operator==(rhs,lhs);}; friend const bool operator==(const IT&lhs,std::shared_ptrrhs){return operator==(rhs,lhs);}; + const Pixel GetDisplayNameColor()const; }; class Inventory{ diff --git a/Adventures in Lestoria/ItemEnchant.cpp b/Adventures in Lestoria/ItemEnchant.cpp index b39e424b..d86bd604 100644 --- a/Adventures in Lestoria/ItemEnchant.cpp +++ b/Adventures in Lestoria/ItemEnchant.cpp @@ -103,13 +103,6 @@ void ItemEnchantInfo::Initialize(){ if(!affectSlots.count(affectStr))ERR(std::format("WARNING! Could not find translate ability affect slot name {} to a valid slot! Valid slot names are: \"Auto Attack, Right Click Ability, Ability 1, Ability 2, Ability 3\"",affectStr)); newEnchant.abilitySlot=affectSlots.at(affectStr); } - size_t statModifierInd{}; - while(enchant.HasProperty(std::format("Stat Modifier[{}]",statModifierInd))){ - const datafile&stat{enchant[std::format("Stat Modifier[{}]",statModifierInd)]}; - newEnchant.minStatModifiers.A(stat.GetString(0))=stat.GetReal(1); - newEnchant.maxStatModifiers.A(stat.GetString(0))=stat.GetReal(2); - statModifierInd++; - } auto IsRequiredKey=[](const std::string_view key){return key=="Description"||key=="Affects"||key.starts_with("Stat Modifier[");}; @@ -128,6 +121,14 @@ void ItemEnchantInfo::Initialize(){ enchantDescription=enchantDescription.replace(configValInd,wrappedConfigStr.length(),formattedFloat); } + size_t statModifierInd{}; + while(enchant.HasProperty(std::format("Stat Modifier[{}]",statModifierInd))){ + const datafile&stat{enchant[std::format("Stat Modifier[{}]",statModifierInd)]}; + newEnchant.minStatModifiers.A(stat.GetString(0))=stat.GetReal(1); + newEnchant.maxStatModifiers.A(stat.GetString(0))=stat.GetReal(2); + statModifierInd++; + } + newEnchant.description=enchantDescription; return newEnchant; @@ -155,7 +156,7 @@ void ItemEnchantInfo::Initialize(){ } ItemEnchant::ItemEnchant(const std::string_view enchantName) -:enchantName(std::string(enchantName)){ +:enchantName(std::string(enchantName)),description(ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).Description()){ for(const auto&[attr,val]:ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).minStatModifiers){ float minVal=ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).minStatModifiers.A_Read(attr); float maxVal=ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).maxStatModifiers.A_Read(attr); @@ -164,6 +165,12 @@ ItemEnchant::ItemEnchant(const std::string_view enchantName) const auto&randRange{std::ranges::iota_view(int(minVal),int(maxVal))}; A(attr)=randRange[util::random()%randRange.size()]; } + + const std::string wrappedConfigStr{std::vformat("{{{}}}",std::make_format_args(attr.ActualName()))}; + size_t configValInd{description.find(wrappedConfigStr)}; + if(configValInd==std::string::npos)continue; + std::string formattedFloat{std::format("{}",val)}; + description=description.replace(configValInd,wrappedConfigStr.length(),formattedFloat); } } @@ -178,7 +185,7 @@ const std::string ItemEnchantInfo::Name(TextStyle style)const{ return name; }break; case COLOR_CODES:{ - return ENCHANT_CATEGORIES.at(category).displayCol.toHexString()+name; + return ENCHANT_CATEGORIES.at(category).displayCol.toHTMLColorCode()+name; }break; } return{}; @@ -203,7 +210,7 @@ const std::string ItemEnchant::Name(ItemEnchantInfo::TextStyle style)const{ return GetEnchantInfo().Name(style); } const std::string_view ItemEnchant::Description()const{ - return GetEnchantInfo().Description(); + return description; } const ItemEnchantInfo::ItemEnchantCategory&ItemEnchant::Category()const{ return GetEnchantInfo().Category(); diff --git a/Adventures in Lestoria/ItemEnchant.h b/Adventures in Lestoria/ItemEnchant.h index e4f19fb1..42d1155c 100644 --- a/Adventures in Lestoria/ItemEnchant.h +++ b/Adventures in Lestoria/ItemEnchant.h @@ -104,4 +104,5 @@ public: private: const ItemEnchantInfo&GetEnchantInfo()const; std::string enchantName; + std::string description; }; \ No newline at end of file diff --git a/Adventures in Lestoria/Pixel.cpp b/Adventures in Lestoria/Pixel.cpp index a6450653..a59d5331 100644 --- a/Adventures in Lestoria/Pixel.cpp +++ b/Adventures in Lestoria/Pixel.cpp @@ -168,7 +168,7 @@ namespace olc{ return Pixel(nR, nG, nB, a); } - std::string Pixel::toHexString()const{ + std::string Pixel::toHTMLColorCode()const{ return std::format("#{:2X}{:2X}{:2X}",r,g,b); } diff --git a/Adventures in Lestoria/Pixel.h b/Adventures in Lestoria/Pixel.h index dfa990b4..ec3178f8 100644 --- a/Adventures in Lestoria/Pixel.h +++ b/Adventures in Lestoria/Pixel.h @@ -90,7 +90,7 @@ namespace olc{ Pixel& operator *=(const Pixel& p); bool operator < (const Pixel& p)const; Pixel inv() const; - std::string toHexString()const; + std::string toHTMLColorCode()const; }; Pixel PixelF(float red, float green, float blue, float alpha = 1.0f); diff --git a/Adventures in Lestoria/RowItemDisplay.h b/Adventures in Lestoria/RowItemDisplay.h index c22a6a16..c2171a69 100644 --- a/Adventures in Lestoria/RowItemDisplay.h +++ b/Adventures in Lestoria/RowItemDisplay.h @@ -101,14 +101,14 @@ public: vf2d scaledSize={std::min(1.f,(rect.size.x-6-iconSize.x)/game->GetTextSizeProp(itemName).x),1}; bool missingRequirements=!canEnhance&&fadeOutIfMissingRequirements; + - Pixel itemNameTextCol=WHITE; + if(locked&&hideLabelWhileLocked)std::for_each(itemName.begin(),itemName.end(),[](char&c){if(c>='0'&&c<='z'){c='?';}}); + Pixel itemNameTextCol{itemRef.lock()->GetDisplayNameColor()}; if(missingRequirements){ itemNameTextCol=DARK_GREY; } - if(locked&&hideLabelWhileLocked)std::for_each(itemName.begin(),itemName.end(),[](char&c){if(c>='0'&&c<='z'){c='?';}}); - window.DrawShadowStringPropDecal(rect.pos+vf2d{4,4}+vf2d{iconSize.x,iconSize.y/2-4},itemName,itemNameTextCol,BLACK,scaledSize); #pragma endregion diff --git a/Adventures in Lestoria/SaveFile.cpp b/Adventures in Lestoria/SaveFile.cpp index 2cb6049f..c7b1a071 100644 --- a/Adventures in Lestoria/SaveFile.cpp +++ b/Adventures in Lestoria/SaveFile.cpp @@ -51,6 +51,7 @@ All rights reserved. #include "Tutorial.h" INCLUDE_game +INCLUDE_ADMIN_MODE size_t SaveFile::saveFileID=0; std::string SaveFile::saveFileName=""; @@ -104,6 +105,13 @@ const void SaveFile::SaveGame(){ for(const auto&[attr,val]:item->RandomStats()){ saveFile["Items"][std::format("Item[{}]",itemCount)]["Attributes"][std::string(attr.ActualName())].SetReal(val); } + if(item->HasEnchant()){ + saveFile["Items"][std::format("Item[{}]",itemCount)]["Enchant"]["Name"].SetString(item->GetEnchant().value().Name()); + ItemEnchant enchant{item->GetEnchant().value()}; + for(const auto&[attr,val]:enchant){ + saveFile["Items"][std::format("Item[{}]",itemCount)]["Enchant"]["Attributes"][std::string(attr.ActualName())].SetReal(val); + } + } itemCount++; } saveFile["Player"]["Class"].SetString(game->GetPlayer()->GetClassName()); @@ -331,7 +339,7 @@ void SaveFile::LoadFile(){ std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID)); trim(fileHash); //It's possible the expected file hash has a space at the end/beginning that gets stripped out. We want to trim and match that string. - if(expectedFileHash!=fileHash){ + if(!ADMIN_MODE&&expectedFileHash!=fileHash){ LOG(std::format("WARNING! Filehash for file {} was not identified as proper! Will not load this file!","save_file_path"_S+std::format("save.{:04}",saveFileID))); return; } @@ -367,6 +375,15 @@ void SaveFile::LoadFile(){ newItem.lock()->Lock(); } } + + if(data.HasProperty("Enchant")){ + newItem.lock()->enchant=ItemEnchant{data["Enchant"]["Name"].GetString()}; + if(loadFile.GetProperty(std::format("Items.{}.Enchant",key)).HasProperty("Attributes")){ + for(auto&[attr,data]:loadFile.GetProperty(std::format("Items.{}.Enchant.Attributes",key)).GetOrderedKeys()){ + newItem.lock()->enchant.value().A(attr)=data.GetReal(); + } + } + } } game->ChangePlayerClass(classutils::StringToClass(loadFile["Player"]["Class"].GetString())); game->GetPlayer()->SetLevel(loadFile["Player"]["Level"].GetInt()); diff --git a/Adventures in Lestoria/SettingsWindow.cpp b/Adventures in Lestoria/SettingsWindow.cpp index 967239d7..4ff6c798 100644 --- a/Adventures in Lestoria/SettingsWindow.cpp +++ b/Adventures in Lestoria/SettingsWindow.cpp @@ -55,28 +55,26 @@ All rights reserved. INCLUDE_DATA INCLUDE_game INCLUDE_WINDOW_SIZE +INCLUDE_ADMIN_MODE using A=Attribute; -#define UNLOCK_ALL_BUTTON -//#undef UNLOCK_ALL_BUTTON //Comment out to enable unlock all button. - void Menu::InitializeSettingsWindow(){ vf2d windowSize=WINDOW_SIZE-vf2d{28,28}; Menu*settingsWindow=CreateMenu(SETTINGS,CENTERED,windowSize); #pragma region Unlock All Button - #ifdef UNLOCK_ALL_BUTTON - 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); + if(ADMIN_MODE){ + 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; - #endif + return true; + })END; + } #pragma endregion settingsWindow->ADD("Settings Label",MenuLabel)(geom2d::rect{{4,4},vf2d{windowSize.x-8,24}},"Game Settings",2.f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END; diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index e23e2225..620c7276 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -23,6 +23,8 @@ DEMO ==== Add Unit Test for Attack Speed Reduction stat. +Move censoredTextEntry calculation in MenuLabel draw somewhere else perhaps? + PGETinker notes =============== Changing zoom size does not affect the indentation breadcumb immediately (requires scrolling to change the view) diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 41d71bb4..04fd7b7c 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_PATCH 3 -#define VERSION_BUILD 10538 +#define VERSION_BUILD 10604 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/items/ItemEnchants.txt b/Adventures in Lestoria/assets/config/items/ItemEnchants.txt index 9e3b1d4c..cd641b78 100644 --- a/Adventures in Lestoria/assets/config/items/ItemEnchants.txt +++ b/Adventures in Lestoria/assets/config/items/ItemEnchants.txt @@ -8,49 +8,49 @@ Item Enchants Health Boost { - Description = "Increases Maximum Health %." + Description = "Increases Maximum Health by {Health %}%" # Stat, Lowest, Highest Value Stat Modifier[0] = Health %, 3, 5 # Stat Modifier[1] = ... } Attack Boost { - Description = "Increases Attack %." + Description = "Increases Attack {Attack %}%" # Stat, Lowest, Highest Value Stat Modifier[0] = Attack %, 3, 5 # Stat Modifier[1] = ... } Movement Boost { - Description = "Increases Move Spd %." + Description = "Increases Move Spd by {Move Spd %}%" # Stat, Lowest, Highest Value Stat Modifier[0] = Move Spd %, 3, 5 # Stat Modifier[1] = ... } Ability Haste { - Description = "Decreases cooldown time of abilities." + Description = "Decreases cooldown time of abilities by {CDR}%" # Stat, Lowest, Highest Value Stat Modifier[0] = CDR, 3, 5 # Stat Modifier[1] = ... } Crit Rate { - Description = "Increases critical hit rate." + Description = "Increases critical hit rate by {Crit Rate}%" # Stat, Lowest, Highest Value Stat Modifier[0] = Crit Rate, 3, 5 # Stat Modifier[1] = ... } Crit Damage { - Description = "Increases damage from critical hits." + Description = "Increases damage from critical hits by {Crit Dmg}%" # Stat, Lowest, Highest Value Stat Modifier[0] = Crit Dmg, 7, 10 # Stat Modifier[1] = ... } Stoneskin { - Description = "Reduces damage taken." + Description = "Reduces damage taken by {Damage Reduction}%" # Stat, Lowest, Highest Value Stat Modifier[0] = Damage Reduction, 3, 5 # Stat Modifier[1] = ... @@ -58,7 +58,7 @@ Item Enchants Mana Pool { - Description = "Increases maximum mana." + Description = "Increases maximum mana by {Mana}." # Stat, Lowest, Highest Value Stat Modifier[0] = Mana, 7, 12 # Stat Modifier[1] = ... @@ -161,7 +161,7 @@ Item Enchants } Tumble { - Description = "Roll range, invulnerability time, and Movespeed boost are all increased by {BOOST PERCENTAGE}%." + Description = "Roll range, invulnerability time, and Movespeed boost are all increased by {BOOST PERCENTAGE}%" Affects = Right Click Ability BOOST PERCENTAGE = 30% diff --git a/Adventures in Lestoria/olcPGEX_ViewPort.h b/Adventures in Lestoria/olcPGEX_ViewPort.h index e85ce7f4..dc067df5 100644 --- a/Adventures in Lestoria/olcPGEX_ViewPort.h +++ b/Adventures in Lestoria/olcPGEX_ViewPort.h @@ -636,100 +636,113 @@ float olc::ViewPort::directionFromLine(vf2d lineA, vf2d lineB, vf2d point) { void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale, const float width,const bool disableDynamicScaling){ if(sText.length()==0)return; - std::string key{"DSD_"+std::string(pge->stripCol(sText))}; + std::string originalKey{pge->stripCol(sText)}; + std::string renderStr{pge->stripLeadingCol(sText)}; + std::string key{"DSD_"+originalKey}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=pge->GetWrappedTextSize(sText,width,scale); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=renderStr; + const bool ShadowRerenderRequired=pge->garbageCollector.count(key+"_SHADOW")&&pge->garbageCollector[key+"_SHADOW"].originalStr!=renderStr; + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=pge->GetWrappedTextSize(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!pge->garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); pge->garbageCollector[key].decal=newDecal; }else{ newDecal=pge->garbageCollector[key].decal; } - pge->garbageCollector[key].originalStr=sText; + pge->garbageCollector[key].originalStr=originalKey; pge->SetDrawTarget(newDecal->sprite); pge->Clear(BLANK); - pge->DrawString({0,0},sText,WHITE,1U,width/scale.x); + pge->DrawString({0,0},renderStr,WHITE,1U,width/scale.x); pge->SetDrawTarget(nullptr); newDecal->Update(); } pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; - DrawDecal(pos,pge->garbageCollector[key].decal,scale,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){ if(sText.length()==0)return; - std::u32string Ukey=U"DSD_"+font.GetFontName()+U"_"+pge->stripCol(sText); + std::u32string originalKey{pge->stripCol(sText)}; + std::u32string renderStr{pge->stripLeadingCol(sText)}; + std::u32string Ukey=U"DSD_"+font.GetFontName()+U"_"+originalKey; std::string key=std::string(Ukey.begin(),Ukey.end()); - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - if(pge->garbageCollector.count(key)){ - delete pge->garbageCollector[key].decal; - } - pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE); - pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end()); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=std::string(renderStr.begin(),renderStr.end()); + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + delete pge->garbageCollector[key].decal; + pge->garbageCollector[key].decal=font.RenderStringToDecal(renderStr,WHITE); + pge->garbageCollector[key].originalStr=std::string(originalKey.begin(),originalKey.end()); } pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; - DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale,const float width,const bool disableDynamicScaling){ if(sText.length()==0)return; - std::string key{"DSPD"+std::string(pge->stripCol(sText))}; + std::string originalKey{pge->stripCol(sText)}; + std::string renderStr{pge->stripLeadingCol(sText)}; + std::string key{"DSPD"+originalKey}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=pge->GetWrappedTextSizeProp(sText,width,scale); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=renderStr; + const bool ShadowRerenderRequired=pge->garbageCollector.count(key+"_SHADOW")&&pge->garbageCollector[key+"_SHADOW"].originalStr!=renderStr; + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=pge->GetWrappedTextSizeProp(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!pge->garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); pge->garbageCollector[key].decal=newDecal; }else{ newDecal=pge->garbageCollector[key].decal; } - pge->garbageCollector[key].originalStr=sText; + pge->garbageCollector[key].originalStr=originalKey; pge->SetDrawTarget(newDecal->sprite); pge->Clear(BLANK); - pge->DrawStringProp({0,0},sText,WHITE,1U,width/scale.x); + pge->DrawStringProp({0,0},renderStr,WHITE,1U,width/scale.x); pge->SetDrawTarget(nullptr); newDecal->Update(); } pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; - DrawDecal(pos,pge->garbageCollector[key].decal,scale,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor,const bool disableDynamicScaling){ if(sText.length()==0)return; - std::string key{"DSSD_"+std::string(pge->stripCol(sText))}; + std::string originalKey{pge->stripCol(sText)}; + std::string renderStr{pge->stripLeadingCol(sText)}; + std::string key{"DSSD_"+originalKey}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=pge->GetWrappedTextSize(sText,width,scale); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=renderStr; + const bool ShadowRerenderRequired=pge->garbageCollector.count(key+"_SHADOW")&&pge->garbageCollector[key+"_SHADOW"].originalStr!=renderStr; + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=pge->GetWrappedTextSize(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!pge->garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); pge->garbageCollector[key].decal=newDecal; }else{ newDecal=pge->garbageCollector[key].decal; } - pge->garbageCollector[key].originalStr=sText; + pge->garbageCollector[key].originalStr=originalKey; pge->SetDrawTarget(newDecal->sprite); pge->Clear(BLANK); - pge->DrawString({0,0},sText,WHITE,1U,width/scale.x); + pge->DrawString({0,0},renderStr,WHITE,1U,width/scale.x); newDecal->Update(); vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; Decal*newShadowDecal=nullptr; - if(!pge->garbageCollector.count(key+"_SHADOW")){ + if(!ShadowRerenderRequired){ newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal; }else{ @@ -740,44 +753,48 @@ void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){ for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){ if(x!=0||y!=0){ - pge->DrawString(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4); + pge->DrawString(vf2d{x,y}+adjustedShadowSizeFactor,renderStr,WHITE,4U,width/scale.x*4); } } } - pge->SetDrawTarget(nullptr); + pge->SetDrawTarget(nullptr); newShadowDecal->Update(); } pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; pge->garbageCollector[key+"_SHADOW"].expireTime=pge->GetRunTime()+120.0f; DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},pge->garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol); - DrawDecal(pos,pge->garbageCollector[key].decal,scale,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor,const bool disableDynamicScaling){ if(sText.length()==0)return; - std::string key{"DSSPD"+std::string(pge->stripCol(sText))}; + std::string originalKey{pge->stripCol(sText)}; + std::string renderStr{pge->stripLeadingCol(sText)}; + std::string key{"DSSPD"+originalKey}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=pge->GetWrappedTextSizeProp(sText,width,scale); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=renderStr; + const bool ShadowRerenderRequired=pge->garbageCollector.count(key+"_SHADOW")&&pge->garbageCollector[key+"_SHADOW"].originalStr!=renderStr; + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=pge->GetWrappedTextSizeProp(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!pge->garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); pge->garbageCollector[key].decal=newDecal; }else{ newDecal=pge->garbageCollector[key].decal; } - pge->garbageCollector[key].originalStr=sText; + pge->garbageCollector[key].originalStr=originalKey; pge->SetDrawTarget(newDecal->sprite); pge->Clear(BLANK); - pge->DrawStringProp({0,0},sText,WHITE,1U,width/scale.x); + pge->DrawStringProp({0,0},renderStr,WHITE,1U,width/scale.x); newDecal->Update(); vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; Decal*newShadowDecal=nullptr; - if(!pge->garbageCollector.count(key+"_SHADOW")){ + if(!ShadowRerenderRequired){ newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal; }else{ @@ -788,7 +805,7 @@ void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_ for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){ for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){ if(x!=0||y!=0){ - pge->DrawStringProp(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4); + pge->DrawStringProp(vf2d{x,y}+adjustedShadowSizeFactor,renderStr,WHITE,4U,width/scale.x*4); } } } @@ -798,19 +815,20 @@ void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_ pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; pge->garbageCollector[key+"_SHADOW"].expireTime=pge->GetRunTime()+120.0f; DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},pge->garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol); - DrawDecal(pos,pge->garbageCollector[key].decal,scale,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){ if(sText.length()==0)return; - std::u32string Ukey=U"DSSD_"+font.GetFontName()+U"_"+pge->stripCol(sText); + std::u32string originalKey{pge->stripCol(sText)}; + std::u32string renderStr{pge->stripLeadingCol(sText)}; + std::u32string Ukey=U"DSSD_"+font.GetFontName()+U"_"+originalKey; std::string key=std::string(Ukey.begin(),Ukey.end()); - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - if(pge->garbageCollector.count(key)){ - delete pge->garbageCollector[key].decal; - } - pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE); - pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end()); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=std::string(renderStr.begin(),renderStr.end()); + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + delete pge->garbageCollector[key].decal; + pge->garbageCollector[key].decal=font.RenderStringToDecal(renderStr,WHITE); + pge->garbageCollector[key].originalStr=std::string(originalKey.begin(),originalKey.end()); } pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; std::erase_if(pge->garbageCollector,[&](auto&key){ @@ -827,25 +845,26 @@ void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const } } } - DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale){ if(sText.length()==0)return; - std::u32string Ukey=U"DDSSD_"+font.GetFontName()+U"_"+pge->stripCol(sText); + std::u32string originalKey{pge->stripCol(sText)}; + std::u32string renderStr{pge->stripLeadingCol(sText)}; + std::u32string Ukey=U"DDSSD_"+font.GetFontName()+U"_"+originalKey; std::string key=std::string(Ukey.begin(),Ukey.end()); - if(!pge->garbageCollector.count(key)||pge->garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - if(pge->garbageCollector.count(key)){ - delete pge->garbageCollector[key].decal; - } - pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE); - pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end()); + const bool RerenderRequired=pge->garbageCollector.count(key)&&pge->garbageCollector[key].originalStr!=std::string(renderStr.begin(),renderStr.end()); + if(!pge->garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + delete pge->garbageCollector[key].decal; + pge->garbageCollector[key].decal=font.RenderStringToDecal(renderStr,WHITE); + pge->garbageCollector[key].originalStr=std::string(originalKey.begin(),originalKey.end()); } pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f; DrawDecal(pos+vf2d{0,0.5f},pge->garbageCollector[key].decal,scale/4,shadowCol); DrawDecal(pos+vf2d{0.5f,0},pge->garbageCollector[key].decal,scale/4,shadowCol); DrawDecal(pos+vf2d{0.5f,0.5f},pge->garbageCollector[key].decal,scale/4,shadowCol); - DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col); + DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,pge->GetFinalRenderColor(col,sText)); } void olc::ViewPort::DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col)const{ diff --git a/Adventures in Lestoria/olcPixelGameEngine.h b/Adventures in Lestoria/olcPixelGameEngine.h index 3344cc67..a5b389df 100644 --- a/Adventures in Lestoria/olcPixelGameEngine.h +++ b/Adventures in Lestoria/olcPixelGameEngine.h @@ -931,6 +931,10 @@ namespace olc static std::unique_ptr platform; static std::map mapKeys; + namespace EngineTests{ + class EngineTest; + } + // O------------------------------------------------------------------------------O // | olc::PixelGameEngine - The main BASE class for your application | // O------------------------------------------------------------------------------O @@ -1204,7 +1208,6 @@ namespace olc void SetMosaicEffect(uint8_t effectLevel); HWButton*const GetKeyboardState(uint8_t key); - public: static std::map charToColor; static std::string Grey; @@ -1273,6 +1276,14 @@ namespace olc friend class ViewPort; + std::string stripLeadingCol(std::string_view originalText); + std::u32string stripLeadingCol(std::u32string_view originalText); + std::string stripCol(std::string_view originalText); + std::u32string stripCol(std::u32string_view originalText); + //If WHITE is provided as the blend color (as is the default), then we need to check the source string for a leading HTML color code. If we find one, return that as the final color we want to render the string as. Otherwise, return the original color. + const Pixel GetFinalRenderColor(const Pixel initialCol,std::string_view sourceStr); + const Pixel GetFinalRenderColor(const Pixel initialCol,std::u32string_view sourceStr); + private: // Inner mysterious workings olc::Sprite* pDrawTarget = nullptr; Pixel::Mode nPixelMode = Pixel::NORMAL; @@ -1338,9 +1349,6 @@ namespace olc std::list sCommandHistory; std::list::iterator sCommandHistoryIt; - std::string stripCol(std::string_view originalText); - std::u32string stripCol(std::u32string_view originalText); - // Text Entry Specific bool bTextEntryEnable = false; std::string sTextEntryString = ""; @@ -2125,6 +2133,16 @@ namespace olc }); } + std::string PixelGameEngine::stripLeadingCol(std::string_view originalText){ + if(originalText.length()>0&&originalText[0]=='#')return std::string(originalText.substr(7)); + return std::string(originalText); + } + + std::u32string PixelGameEngine::stripLeadingCol(std::u32string_view originalText){ + if(originalText.length()>0&&originalText[0]=='#')return std::u32string(originalText.substr(7)); + return std::u32string(originalText); + } + std::string PixelGameEngine::stripCol(std::string_view originalText){ std::string newStr{""}; for(int i=0;i0&&initialCol==WHITE&&sourceStr[0]=='#')return Pixel(std::stoi(std::string(sourceStr.substr(1,6)),nullptr,16)); + return initialCol; + } + const Pixel PixelGameEngine::GetFinalRenderColor(const Pixel initialCol,std::u32string_view sourceStr){ + if(sourceStr.length()>0&&initialCol==WHITE&&sourceStr[0]=='#')return Pixel(std::stoi(std::string(sourceStr.substr(1,6).begin(),sourceStr.substr(1,6).end()),nullptr,16)); + return initialCol; + } + bool PixelGameEngine::IsFocused() const { return bHasInputFocus; } @@ -3459,86 +3486,96 @@ namespace olc void PixelGameEngine::DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale,const float width,const bool disableDynamicScaling) { if(sText.length()==0)return; - std::string key{"DSD"+std::string(stripCol(sText))}; + std::string originalKey{stripCol(sText)}; + std::string renderStr{stripLeadingCol(sText)}; + std::string key{"DSD"+std::string(originalKey)}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=GetWrappedTextSize(sText,width,scale); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=renderStr; + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=GetWrappedTextSize(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); garbageCollector[key].decal=newDecal; }else{ newDecal=garbageCollector[key].decal; } - garbageCollector[key].originalStr=sText; + garbageCollector[key].originalStr=originalKey; SetDrawTarget(newDecal->sprite); Clear(BLANK); - DrawString({0,0},sText,WHITE,1U,width/scale.x); + DrawString({0,0},renderStr,WHITE,1U,width/scale.x); SetDrawTarget(nullptr); newDecal->Update(); } garbageCollector[key].expireTime=GetRunTime()+120.0f; - DrawDecal(pos,garbageCollector[key].decal,scale,col); + DrawDecal(pos,garbageCollector[key].decal,scale,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const olc::vf2d& scale, const float width,const bool disableDynamicScaling) { if(sText.length()==0)return; - std::string key{"DSPD_"+std::string(stripCol(sText))}; + std::string originalKey{stripCol(sText)}; + std::string renderStr{stripLeadingCol(sText)}; + std::string key{"DSPD_"+std::string(originalKey)}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=GetWrappedTextSizeProp(sText,width,scale); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=renderStr; + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=GetWrappedTextSizeProp(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); garbageCollector[key].decal=newDecal; }else{ newDecal=garbageCollector[key].decal; } - garbageCollector[key].originalStr=sText; + garbageCollector[key].originalStr=originalKey; SetDrawTarget(newDecal->sprite); Clear(BLANK); - DrawStringProp({0,0},sText,WHITE,1U,width/scale.x); + DrawStringProp({0,0},renderStr,WHITE,1U,width/scale.x); SetDrawTarget(nullptr); newDecal->Update(); } garbageCollector[key].expireTime=GetRunTime()+120.0f; - DrawDecal(pos,garbageCollector[key].decal,scale,col); + DrawDecal(pos,garbageCollector[key].decal,scale,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor,const bool disableDynamicScaling){ if(sText.length()==0)return; - std::string key{"DSSD_"+std::string(stripCol(sText))}; + std::string originalKey{stripCol(sText)}; + std::string renderStr{stripLeadingCol(sText)}; + std::string key{"DSSD_"+std::string(originalKey)}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=GetWrappedTextSize(sText,width,scale); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=renderStr; + const bool ShadowRerenderRequired=garbageCollector.count(key+"_SHADOW")&&garbageCollector[key+"_SHADOW"].originalStr!=renderStr; + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=GetWrappedTextSize(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); garbageCollector[key].decal=newDecal; }else{ newDecal=garbageCollector[key].decal; } - garbageCollector[key].originalStr=sText; + garbageCollector[key].originalStr=originalKey; SetDrawTarget(newDecal->sprite); Clear(BLANK); - DrawString({0,0},sText,WHITE,1U,width/scale.x); + DrawString({0,0},renderStr,WHITE,1U,width/scale.x); newDecal->Update(); vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; Decal*newShadowDecal=nullptr; - if(!garbageCollector.count(key+"_SHADOW")){ + if(!ShadowRerenderRequired){ newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); garbageCollector[key+"_SHADOW"].decal=newShadowDecal; }else{ @@ -3549,7 +3586,7 @@ namespace olc for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){ for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){ if(x!=0||y!=0){ - DrawString(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4); + DrawString(vf2d{x,y}+adjustedShadowSizeFactor,renderStr,WHITE,4U,width/scale.x*4); } } } @@ -3559,34 +3596,36 @@ namespace olc garbageCollector[key].expireTime=GetRunTime()+120.0f; garbageCollector[key+"_SHADOW"].expireTime=GetRunTime()+120.0f; DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol); - DrawDecal(pos,garbageCollector[key].decal,scale,col); + DrawDecal(pos,garbageCollector[key].decal,scale,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){ if(sText.length()==0)return; - std::u32string Ukey=U"DSD_"+font.GetFontName()+U"_"+stripCol(sText); + std::u32string originalKey{stripCol(sText)}; + std::u32string renderStr{stripLeadingCol(sText)}; + std::u32string Ukey=U"DSD_"+font.GetFontName()+U"_"+originalKey; std::string key=std::string(Ukey.begin(),Ukey.end()); - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - if(garbageCollector.count(key)){ - delete garbageCollector[key].decal; - } - garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE); - garbageCollector[key].originalStr=std::string(sText.begin(),sText.end()); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=std::string(renderStr.begin(),renderStr.end()); + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + delete garbageCollector[key].decal; + garbageCollector[key].decal=font.RenderStringToDecal(renderStr,WHITE); + garbageCollector[key].originalStr=std::string(originalKey.begin(),originalKey.end()); } garbageCollector[key].expireTime=GetRunTime()+120.0f; - DrawDecal(pos,garbageCollector[key].decal,scale/4,col); + DrawDecal(pos,garbageCollector[key].decal,scale/4,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){ if(sText.length()==0)return; - std::u32string Ukey=U"DSSD_"+font.GetFontName()+U"_"+stripCol(sText); + std::u32string originalKey{stripCol(sText)}; + std::u32string renderStr{stripLeadingCol(sText)}; + std::u32string Ukey=U"DSSD_"+font.GetFontName()+U"_"+originalKey; std::string key=std::string(Ukey.begin(),Ukey.end()); - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - if(garbageCollector.count(key)){ - delete garbageCollector[key].decal; - } - garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE); - garbageCollector[key].originalStr=std::string(sText.begin(),sText.end()); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=std::string(renderStr.begin(),renderStr.end()); + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + delete garbageCollector[key].decal; + garbageCollector[key].decal=font.RenderStringToDecal(renderStr,WHITE); + garbageCollector[key].originalStr=std::string(originalKey.begin(),originalKey.end()); } garbageCollector[key].expireTime=GetRunTime()+120.0f; for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){ @@ -3596,52 +3635,57 @@ namespace olc } } } - DrawDecal(pos,garbageCollector[key].decal,scale/4,col); + DrawDecal(pos,garbageCollector[key].decal,scale/4,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale){ if(sText.length()==0)return; - std::u32string Ukey=U"DDSSD_"+font.GetFontName()+U"_"+stripCol(sText); + std::u32string originalKey{stripCol(sText)}; + std::u32string renderStr{stripLeadingCol(sText)}; + std::u32string Ukey=U"DDSSD_"+font.GetFontName()+U"_"+originalKey; std::string key=std::string(Ukey.begin(),Ukey.end()); - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=std::string(sText.begin(),sText.end())){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - if(garbageCollector.count(key)){ - delete garbageCollector[key].decal; - } - garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE); - garbageCollector[key].originalStr=std::string(sText.begin(),sText.end()); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=std::string(renderStr.begin(),renderStr.end()); + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + delete garbageCollector[key].decal; + garbageCollector[key].decal=font.RenderStringToDecal(renderStr,WHITE); + garbageCollector[key].originalStr=std::string(originalKey.begin(),originalKey.end()); } garbageCollector[key].expireTime=GetRunTime()+120.0f; DrawDecal(pos+vf2d{0,0.5f},garbageCollector[key].decal,scale/4,shadowCol); DrawDecal(pos+vf2d{0.5f,0},garbageCollector[key].decal,scale/4,shadowCol); DrawDecal(pos+vf2d{0.5f,0.5f},garbageCollector[key].decal,scale/4,shadowCol); - DrawDecal(pos,garbageCollector[key].decal,scale/4,col); + DrawDecal(pos,garbageCollector[key].decal,scale/4,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor,const bool disableDynamicScaling){ if(sText.length()==0)return; - std::string key{"DSSPD_"+std::string(stripCol(sText))}; + std::string originalKey{stripCol(sText)}; + std::string renderStr{stripLeadingCol(sText)}; + std::string key{"DSSPD_"+originalKey}; key+=std::to_string(width); if(!disableDynamicScaling){ key+=scale.str(); } - if(!garbageCollector.count(key)||garbageCollector[key].originalStr!=sText){ //If the text key already exists, don't have to recreate the decal, just update the expire time. - vi2d imageSize=GetWrappedTextSizeProp(sText,width,scale); + const bool RerenderRequired=garbageCollector.count(key)&&garbageCollector[key].originalStr!=renderStr; + const bool ShadowRerenderRequired=garbageCollector.count(key+"_SHADOW")&&garbageCollector[key+"_SHADOW"].originalStr!=renderStr; + if(!garbageCollector.count(key)||RerenderRequired){ //If the text key already exists, don't have to recreate the decal, just update the expire time. + vi2d imageSize=GetWrappedTextSizeProp(originalKey,width,scale); if(imageSize.x<1||imageSize.y<1)return; Decal*newDecal=nullptr; - if(!garbageCollector.count(key)){ + if(!RerenderRequired){ newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); garbageCollector[key].decal=newDecal; }else{ newDecal=garbageCollector[key].decal; } - garbageCollector[key].originalStr=sText; + garbageCollector[key].originalStr=originalKey; SetDrawTarget(newDecal->sprite); Clear(BLANK); - DrawStringProp({0,0},sText,WHITE,1U,width/scale.x); + DrawStringProp({0,0},renderStr,WHITE,1U,width/scale.x); newDecal->Update(); vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; Decal*newShadowDecal=nullptr; - if(!garbageCollector.count(key+"_SHADOW")){ + if(!ShadowRerenderRequired){ newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); garbageCollector[key+"_SHADOW"].decal=newShadowDecal; }else{ @@ -3652,7 +3696,7 @@ namespace olc for(float y=-adjustedShadowSizeFactor.y;y<=adjustedShadowSizeFactor.y+0.1;y+=adjustedShadowSizeFactor.y/2){ for(float x=-adjustedShadowSizeFactor.x;x<=adjustedShadowSizeFactor.x+0.1;x+=adjustedShadowSizeFactor.x/2){ if(x!=0||y!=0){ - DrawStringProp(vf2d{x,y}+adjustedShadowSizeFactor, sText, WHITE,4U,width/scale.x*4); + DrawStringProp(vf2d{x,y}+adjustedShadowSizeFactor,renderStr,WHITE,4U,width/scale.x*4); } } } @@ -3662,7 +3706,7 @@ namespace olc garbageCollector[key].expireTime=GetRunTime()+120.0f; garbageCollector[key+"_SHADOW"].expireTime=GetRunTime()+120.0f; DrawDecal(pos-vf2d{shadowSizeFactor,shadowSizeFactor},garbageCollector[key+"_SHADOW"].decal,scale/4,shadowCol); - DrawDecal(pos,garbageCollector[key].decal,scale,col); + DrawDecal(pos,garbageCollector[key].decal,scale,GetFinalRenderColor(col,sText)); } void PixelGameEngine::DrawShadowString(const olc::vi2d& pos, std::string_view sText, Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float width,const float shadowSizeFactor){ @@ -4423,7 +4467,7 @@ namespace olc if (GetKey(olc::Key::DEL).bPressed && nTextEntryCursor < sTextEntryString.size()) sTextEntryString.erase(nTextEntryCursor, 1); - /* + if (GetKey(olc::Key::UP).bPressed) { if (!sCommandHistory.empty()) @@ -4474,7 +4518,7 @@ namespace olc OnTextEntryComplete(sTextEntryString); TextEntryEnable(false); } - }*/ + } } // User must override these functions as required. I have not made @@ -4726,11 +4770,12 @@ namespace olc // Our time per frame coefficient float actualElapsedTime = elapsedTime.count(); float fElapsedTime = std::clamp(elapsedTime.count(),0.f,1/30.f); //HACK fix. We can't have a negative time. Although using a more precise system clock should make this never occur. Also make sure if the game is too slow we advance by only 1/30th of a second. - fLastElapsed = fElapsedTime; - dRunTime += fElapsedTime; if (bConsoleSuspendTime) fElapsedTime = 0.0f; + + fLastElapsed = fElapsedTime; + dRunTime += fElapsedTime; // Some platforms will need to check for events platform->HandleSystemEvent(); @@ -4944,6 +4989,32 @@ namespace olc // {olc::Key::TAB, "\t", "\t"} }; #endif + +#ifdef OLC_KEYBOARD_US + vKeyboardMap = + { + {olc::Key::A, "a", "A"}, {olc::Key::B, "b", "B"}, {olc::Key::C, "c", "C"}, {olc::Key::D, "d", "D"}, {olc::Key::E, "e", "E"}, + {olc::Key::F, "f", "F"}, {olc::Key::G, "g", "G"}, {olc::Key::H, "h", "H"}, {olc::Key::I, "i", "I"}, {olc::Key::J, "j", "J"}, + {olc::Key::K, "k", "K"}, {olc::Key::L, "l", "L"}, {olc::Key::M, "m", "M"}, {olc::Key::N, "n", "N"}, {olc::Key::O, "o", "O"}, + {olc::Key::P, "p", "P"}, {olc::Key::Q, "q", "Q"}, {olc::Key::R, "r", "R"}, {olc::Key::S, "s", "S"}, {olc::Key::T, "t", "T"}, + {olc::Key::U, "u", "U"}, {olc::Key::V, "v", "V"}, {olc::Key::W, "w", "W"}, {olc::Key::X, "x", "X"}, {olc::Key::Y, "y", "Y"}, + {olc::Key::Z, "z", "Z"}, + + {olc::Key::K0, "0", ")"}, {olc::Key::K1, "1", "!"}, {olc::Key::K2, "2", "@"}, {olc::Key::K3, "3", "#"}, {olc::Key::K4, "4", "$"}, + {olc::Key::K5, "5", "%"}, {olc::Key::K6, "6", "^"}, {olc::Key::K7, "7", "&"}, {olc::Key::K8, "8", "*"}, {olc::Key::K9, "9", "("}, + + {olc::Key::NP0, "0", "0"}, {olc::Key::NP1, "1", "1"}, {olc::Key::NP2, "2", "2"}, {olc::Key::NP3, "3", "3"}, {olc::Key::NP4, "4", "4"}, + {olc::Key::NP5, "5", "5"}, {olc::Key::NP6, "6", "6"}, {olc::Key::NP7, "7", "7"}, {olc::Key::NP8, "8", "8"}, {olc::Key::NP9, "9", "9"}, + {olc::Key::NP_MUL, "*", "*"}, {olc::Key::NP_DIV, "/", "/"}, {olc::Key::NP_ADD, "+", "+"}, {olc::Key::NP_SUB, "-", "-"}, {olc::Key::NP_DECIMAL, ".", "."}, + + {olc::Key::PERIOD, ".", ">"}, {olc::Key::EQUALS, "=", "+"}, {olc::Key::COMMA, ",", "<"}, {olc::Key::MINUS, "-", "_"}, {olc::Key::SPACE, " ", " "}, + + {olc::Key::OEM_1, ";", ":"}, {olc::Key::OEM_2, "/", "?"}, {olc::Key::OEM_3, "`", "~"}, {olc::Key::OEM_4, "[", "{"}, + {olc::Key::OEM_5, "\\", "|"}, {olc::Key::OEM_6, "]", "}"}, {olc::Key::OEM_7, "\'", "\""}, + + // {olc::Key::TAB, "\t", "\t"} + }; +#endif } void PixelGameEngine::pgex_Register(olc::PGEX* pgex) diff --git a/Adventures in Lestoria/pixelGameEngine.cpp b/Adventures in Lestoria/pixelGameEngine.cpp index 88bc7bc2..89336772 100644 --- a/Adventures in Lestoria/pixelGameEngine.cpp +++ b/Adventures in Lestoria/pixelGameEngine.cpp @@ -43,6 +43,7 @@ All rights reserved. #include "olcPGEX_ViewPort.h" #include "olcUTIL_Geometry2D.h" #define OLC_PGE_APPLICATION +#define OLC_KEYBOARD_US #include "olcPixelGameEngine.h" #define OLC_PGEX_TRANSFORMEDVIEW #include "olcPGEX_TransformedView.h" diff --git a/Adventures in Lestoria/util.cpp b/Adventures in Lestoria/util.cpp index afe70583..dd98839b 100644 --- a/Adventures in Lestoria/util.cpp +++ b/Adventures in Lestoria/util.cpp @@ -76,14 +76,6 @@ float util::lerp(float n1,float n2,double t){ return float(n1*(1-t)+n2*t); } -std::string util::PixelToHTMLColorCode(const Pixel&col){ - std::string hexCode=std::format("#{:2x}{:2x}{:2x}",col.r,col.g,col.b); - for(char&c:hexCode){ - c=toupper(c); - } - return hexCode; -} - std::string util::timerStr(float time){ int seconds=int(time); int hours=seconds/3600; diff --git a/Adventures in Lestoria/util.h b/Adventures in Lestoria/util.h index ff91d81f..e251c7f3 100644 --- a/Adventures in Lestoria/util.h +++ b/Adventures in Lestoria/util.h @@ -55,7 +55,6 @@ namespace olc::util{ float degToRad(float deg); float radToDeg(float rad); float lerp(float n1,float n2,double t); - std::string PixelToHTMLColorCode(const Pixel&col); std::string timerStr(float time); std::string WrapText(PixelGameEngine*pge,std::string str,int width,bool proportional,vd2d scale); std::u32string WrapText(PixelGameEngine*pge,std::u32string str,int width,Font&font,vd2d scale); diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index ce3a4841..d79ef1e9 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ