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_ptr
- lhs,const IT&rhs){return !lhs.expired()&&lhs.lock()->ActualName()==const_cast(rhs);};
friend const bool operator==(const IT&lhs,std::weak_ptr
- rhs){return operator==(rhs,lhs);};
friend const bool operator==(const IT&lhs,std::shared_ptr
- rhs){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