Implemented Death Defiance enchant. Correct shadow render strings being square (not using proper Y sizes to create cached text). Move game configuration initialization out to global scope to allow config variables to be used when initializing the AiL class. Release Build 10670.

This commit is contained in:
sigonasr2 2024-08-06 04:39:36 -05:00
parent 62086cbd92
commit cfd73ab036
17 changed files with 112 additions and 41 deletions

View File

@ -50,6 +50,7 @@ using namespace olc::utils;
INCLUDE_GFX INCLUDE_GFX
INCLUDE_ITEM_DATA INCLUDE_ITEM_DATA
INCLUDE_DAMAGENUMBER_LIST INCLUDE_DAMAGENUMBER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng; extern std::mt19937 rng;
@ -71,6 +72,7 @@ namespace EnchantTests
Player*player; Player*player;
const HWButton*testKey; const HWButton*testKey;
TEST_METHOD_INITIALIZE(PlayerInitialize){ TEST_METHOD_INITIALIZE(PlayerInitialize){
InitializeGameConfigurations();
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run. rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
testGame.reset(new AiL(true)); testGame.reset(new AiL(true));
ItemAttribute::Initialize(); ItemAttribute::Initialize();
@ -260,5 +262,34 @@ namespace EnchantTests
Assert::AreEqual(4.5_Pct+0.5_Pct*i,player->GetHP4RecoveryPct(),0.1_Pct,L"HP Recovery/4 Pct is increasing by 0.5% per 10% missing health."); Assert::AreEqual(4.5_Pct+0.5_Pct*i,player->GetHP4RecoveryPct(),0.1_Pct,L"HP Recovery/4 Pct is increasing by 0.5% per 10% missing health.");
} }
} }
TEST_METHOD(DeathDefianceCheck){
for(int i:std::ranges::iota_view(0,10)){
player->Heal(100);
player->Hurt(1000,player->OnUpperLevel(),player->GetZ());
if(player->IsAlive()){Assert::Fail(L"Player survived while not having the Death Defiance Enchant! THIS SHOULD NOT BE HAPPENING!");}
player->_SetIframes(0.f);
}
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
Inventory::EquipItem(nullRing,EquipSlot::RING1);
nullRing.lock()->EnchantItem("Death Defiance");
player->Heal(100);
for(int i:std::ranges::iota_view(0,10)){
const int prevPlayerHP{player->GetHealth()};
player->Hurt(1,player->OnUpperLevel(),player->GetZ());
Assert::AreNotEqual(prevPlayerHP,player->GetHealth(),L"Death Defiance triggered even though the player did not take lethal damage!");
player->_SetIframes(0.f);
}
bool survivedAtLeastOnce{false};
for(int i:std::ranges::iota_view(0,10)){
player->Heal(100);
player->Hurt(1000,player->OnUpperLevel(),player->GetZ());
if(player->IsAlive()){
survivedAtLeastOnce=true;
break;
}
player->_SetIframes(0.f);
}
Assert::AreEqual(true,survivedAtLeastOnce,L"Player should have survived at least one time with Death Defiance.");
}
}; };
} }

View File

@ -41,6 +41,7 @@ All rights reserved.
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
INCLUDE_INITIALIZEGAMECONFIGURATIONS
namespace EngineTests namespace EngineTests
{ {
@ -49,6 +50,7 @@ namespace EngineTests
public: public:
std::unique_ptr<AiL>testGame; std::unique_ptr<AiL>testGame;
TEST_METHOD_INITIALIZE(PlayerInitialize){ TEST_METHOD_INITIALIZE(PlayerInitialize){
InitializeGameConfigurations();
testGame.reset(new AiL(true)); testGame.reset(new AiL(true));
} }
TEST_METHOD(StripColorTest){ TEST_METHOD(StripColorTest){

View File

@ -48,6 +48,7 @@ using namespace olc::utils;
INCLUDE_GFX INCLUDE_GFX
INCLUDE_ITEM_DATA INCLUDE_ITEM_DATA
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng; extern std::mt19937 rng;
@ -61,6 +62,7 @@ namespace ItemTests
Player*player; Player*player;
HWButton*testKey; HWButton*testKey;
TEST_METHOD_INITIALIZE(ItemInitialize){ TEST_METHOD_INITIALIZE(ItemInitialize){
InitializeGameConfigurations();
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run. rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
testGame.reset(new AiL(true)); testGame.reset(new AiL(true));
ItemAttribute::Initialize(); ItemAttribute::Initialize();

View File

@ -50,6 +50,7 @@ INCLUDE_game
INCLUDE_GFX INCLUDE_GFX
INCLUDE_DAMAGENUMBER_LIST INCLUDE_DAMAGENUMBER_LIST
INCLUDE_MONSTER_LIST INCLUDE_MONSTER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
TEST_MODULE_INITIALIZE(AiLTestSuite) TEST_MODULE_INITIALIZE(AiLTestSuite)
{ {
@ -65,6 +66,7 @@ namespace MonsterTests
#pragma region Setup Functions #pragma region Setup Functions
//Makes MONSTER_DATA["TestName"] available. //Makes MONSTER_DATA["TestName"] available.
void SetupTestMonster(){ void SetupTestMonster(){
InitializeGameConfigurations();
testGame.reset(new AiL(true)); testGame.reset(new AiL(true));
ItemAttribute::Initialize(); ItemAttribute::Initialize();
ItemInfo::InitializeItems(); ItemInfo::InitializeItems();

View File

@ -49,6 +49,7 @@ using namespace olc::utils;
INCLUDE_GFX INCLUDE_GFX
INCLUDE_ITEM_DATA INCLUDE_ITEM_DATA
INCLUDE_DAMAGENUMBER_LIST INCLUDE_DAMAGENUMBER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng; extern std::mt19937 rng;
@ -62,6 +63,7 @@ namespace PlayerTests
Player*player; Player*player;
HWButton*testKey; HWButton*testKey;
TEST_METHOD_INITIALIZE(PlayerInitialize){ TEST_METHOD_INITIALIZE(PlayerInitialize){
InitializeGameConfigurations();
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run. rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
testGame.reset(new AiL(true)); testGame.reset(new AiL(true));
ItemAttribute::Initialize(); ItemAttribute::Initialize();

View File

@ -161,15 +161,33 @@ float AiL::SIZE_CHANGE_SPEED=1;
AiL::AiL(bool testingMode){ AiL::AiL(bool testingMode){
olc_SetTestingMode(testingMode); olc_SetTestingMode(testingMode);
GFX.Reset(); GFX.Reset();
DATA.Reset();
MONSTER_LIST.clear(); MONSTER_LIST.clear();
InitializeGameConfigurations();
#pragma region Extra Config Initializations
if(TestingModeEnabled()){ //Unit Test-specific custom configurations.
std::string CONFIG_PATH = "config_path"_S;
std::string ITEM_CONFIG = CONFIG_PATH + "item_config"_S;
std::string ITEM_SET_CONFIG = CONFIG_PATH + "item_set_config"_S;
ITEM_CONFIG = CONFIG_PATH + "item-test_config"_S;
ITEM_SET_CONFIG = CONFIG_PATH + "item_set-test_config"_S;
utils::datafile::Read(DATA,ITEM_CONFIG,',',datafile::OverwriteMode::OVERWRITE);
utils::datafile::Read(DATA,ITEM_SET_CONFIG,',',datafile::OverwriteMode::OVERWRITE);
auto keys=DATA.GetProperty("ItemConfiguration");
for(auto&[key,value]:keys){
std::string config=DATA["ItemConfiguration"][key].GetString();
utils::datafile::Read(DATA,CONFIG_PATH + "item_directory"_S + config,',',datafile::OverwriteMode::OVERWRITE);
}
}
DEBUG_PATHFINDING="debug_pathfinding"_I;
#pragma endregion
sAppName="GAME_NAME"_S; sAppName="GAME_NAME"_S;
game=this; game=this;
gameStarted=time(NULL); gameStarted=time(NULL);
} }
void AiL::InitializeGameConfigurations(){ void InitializeGameConfigurations(){
DATA.Reset();
utils::datafile::Read(DATA,"assets/config/configuration.txt"); utils::datafile::Read(DATA,"assets/config/configuration.txt");
std::filesystem::create_directories("save_file_path"_S); std::filesystem::create_directories("save_file_path"_S);
@ -205,11 +223,6 @@ void AiL::InitializeGameConfigurations(){
std::string ITEM_CONFIG = CONFIG_PATH + "item_config"_S; std::string ITEM_CONFIG = CONFIG_PATH + "item_config"_S;
std::string ITEM_SET_CONFIG = CONFIG_PATH + "item_set_config"_S; std::string ITEM_SET_CONFIG = CONFIG_PATH + "item_set_config"_S;
if(TestingModeEnabled()){ //Unit Test-specific custom configurations.
ITEM_CONFIG = CONFIG_PATH + "item-test_config"_S;
ITEM_SET_CONFIG = CONFIG_PATH + "item_set-test_config"_S;
}
utils::datafile::Read(DATA,ITEM_CONFIG); utils::datafile::Read(DATA,ITEM_CONFIG);
utils::datafile::Read(DATA,ITEM_SET_CONFIG); utils::datafile::Read(DATA,ITEM_SET_CONFIG);
} }
@ -229,8 +242,6 @@ void AiL::InitializeGameConfigurations(){
utils::datafile::Read(DATA,CONFIG_PATH + "item_directory"_S + config); utils::datafile::Read(DATA,CONFIG_PATH + "item_directory"_S + config);
} }
DEBUG_PATHFINDING="debug_pathfinding"_I;
std::vector<std::string>values=DATA.GetProperty("class_list").GetValues(); std::vector<std::string>values=DATA.GetProperty("class_list").GetValues();
for(const std::string&cl:values){ for(const std::string&cl:values){
LOG(cl); LOG(cl);
@ -2060,10 +2071,9 @@ void AiL::RenderHud(){
hudOverlay.Draw(); hudOverlay.Draw();
Pixel vignetteOverlayColor="Interface.Vignette Color"_Pixel;
const float vignetteTotalDisplayTime="Interface.Vignette Appearance Time"_F+"Interface.Vignette Fadeout Time"_F; const float vignetteTotalDisplayTime="Interface.Vignette Appearance Time"_F+"Interface.Vignette Fadeout Time"_F;
if(vignetteDisplayTime<"Interface.Vignette Fadeout Time"_F)vignetteOverlayColor.a=util::lerp(0,255,vignetteDisplayTime/"Interface.Vignette Fadeout Time"_F); if(vignetteDisplayTime<"Interface.Vignette Fadeout Time"_F)vignetteOverlayCol.a=util::lerp(0,255,vignetteDisplayTime/"Interface.Vignette Fadeout Time"_F);
DrawDecal({0,0},GFX["vignette.png"].Decal(),{1.f,1.f},vignetteOverlayColor); DrawDecal({0,0},GFX["vignette.png"].Decal(),{1.f,1.f},vignetteOverlayCol);
} }
void AiL::RenderCooldowns(){ void AiL::RenderCooldowns(){
@ -3080,6 +3090,7 @@ int main(const int argn,char**args)
} }
} }
{ {
InitializeGameConfigurations();
AiL demo; AiL demo;
demo.UsingSteamAPI(usingSteam); demo.UsingSteamAPI(usingSteam);
@ -4334,8 +4345,9 @@ const float AiL::GetEncounterDuration()const{
return encounterDuration; return encounterDuration;
} }
void AiL::ShowDamageVignetteOverlay(){ void AiL::ShowDamageVignetteOverlay(const Pixel col){
vignetteDisplayTime="Interface.Vignette Appearance Time"_F+"Interface.Vignette Fadeout Time"_F; vignetteDisplayTime="Interface.Vignette Appearance Time"_F+"Interface.Vignette Fadeout Time"_F;
vignetteOverlayCol=col;
} }
void AiL::GlobalGameUpdates(){ void AiL::GlobalGameUpdates(){

View File

@ -229,6 +229,7 @@ private:
float lastLockOnTargetTime{}; float lastLockOnTargetTime{};
void AdminConsole(); void AdminConsole();
virtual bool OnConsoleCommand(const std::string& sCommand)override final; virtual bool OnConsoleCommand(const std::string& sCommand)override final;
Pixel vignetteOverlayCol{"Interface.Vignette Color"_Pixel};
public: public:
AiL(bool testingMode=false); AiL(bool testingMode=false);
bool OnUserCreate() override; bool OnUserCreate() override;
@ -362,7 +363,7 @@ public:
void UpdateMonsters(); void UpdateMonsters();
void ActivateActionSetForAllControllers(InputActionSetHandle_t actionSetHandle); void ActivateActionSetForAllControllers(InputActionSetHandle_t actionSetHandle);
const float GetEncounterDuration()const; const float GetEncounterDuration()const;
void ShowDamageVignetteOverlay(); void ShowDamageVignetteOverlay(const Pixel="Interface.Vignette Color"_Pixel);
void GlobalGameUpdates(); void GlobalGameUpdates();
const bool QuitRequested()const; const bool QuitRequested()const;
void SetQuitAllowed(bool quittingAllowed); //Locks the game from quitting during sensitive operations such as file saving/loading. void SetQuitAllowed(bool quittingAllowed); //Locks the game from quitting during sensitive operations such as file saving/loading.
@ -377,7 +378,6 @@ public:
Overlay&GetOverlay(); Overlay&GetOverlay();
void SetWindSpeed(vf2d newWindSpd); void SetWindSpeed(vf2d newWindSpd);
const vf2d&GetWindSpeed()const; const vf2d&GetWindSpeed()const;
void InitializeGameConfigurations();
void InitializePlayer(); void InitializePlayer();
void SetWorldZoom(float newZoomScale); void SetWorldZoom(float newZoomScale);
//Plays the correct footstep sound based on player's current tile. //Plays the correct footstep sound based on player's current tile.

View File

@ -73,6 +73,8 @@ using MonsterSpawnerID=int;
#define ACCESS_PLAYER Player*p=game->GetPlayer(); #define ACCESS_PLAYER Player*p=game->GetPlayer();
#define INCLUDE_INITIALIZEGAMECONFIGURATIONS extern void InitializeGameConfigurations();
#define VARIANTS float,int,std::string,bool,vf2d,std::vector<std::any>,size_t #define VARIANTS float,int,std::string,bool,vf2d,std::vector<std::any>,size_t
#undef INFINITE #undef INFINITE
#define INFINITE 999999 #define INFINITE 999999

View File

@ -92,15 +92,15 @@ protected:
vf2d adjustedScale={scale,scale}; vf2d adjustedScale={scale,scale};
vf2d labelTextSize= vf2d labelTextSize=
proportional? proportional?
vf2d(game->GetWrappedTextSizeProp(finalLabel,rect.size.x-2,adjustedScale)): vf2d(game->GetWrappedTextSizeProp(finalLabel,rect.size.x-4,adjustedScale)):
vf2d(game->GetWrappedTextSize(finalLabel,rect.size.x-2,adjustedScale)); vf2d(game->GetWrappedTextSize(finalLabel,rect.size.x-4,adjustedScale));
if(fitToLabel){ if(fitToLabel){
labelTextSize= labelTextSize=
proportional? proportional?
vf2d(game->GetTextSizeProp(finalLabel)*adjustedScale): vf2d(game->GetTextSizeProp(finalLabel)*adjustedScale):
vf2d(game->GetTextSize(finalLabel)*adjustedScale); vf2d(game->GetTextSize(finalLabel)*adjustedScale);
float sizeRatio=(labelTextSize.x)/(rect.size.x-2); float sizeRatio=(labelTextSize.x)/(rect.size.x-4);
if(sizeRatio>1){ if(sizeRatio>1){
adjustedScale.x/=sizeRatio; adjustedScale.x/=sizeRatio;
labelTextSize.x/=sizeRatio; labelTextSize.x/=sizeRatio;
@ -110,7 +110,7 @@ protected:
vf2d drawPos=vf2d{-1,0}+rect.middle()-vf2d{labelTextSize}/2; //Assume centered. vf2d drawPos=vf2d{-1,0}+rect.middle()-vf2d{labelTextSize}/2; //Assume centered.
if(!centered){ if(!centered){
if(rightAlign){ if(rightAlign){
drawPos=vf2d{rect.pos.x+rect.size.x-labelTextSize.x-2,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here. drawPos=vf2d{rect.pos.x+rect.size.x-labelTextSize.x-4,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here.
}else{ //Left Align }else{ //Left Align
drawPos=vf2d{rect.pos.x+2,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here. drawPos=vf2d{rect.pos.x+2,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here.
} }
@ -138,15 +138,15 @@ protected:
}else{ }else{
if(shadow){ if(shadow){
if(proportional){ if(proportional){
window.DrawShadowStringPropDecal(drawPos,finalLabel,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-2,1.0f); window.DrawShadowStringPropDecal(drawPos,finalLabel,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-4,1.0f);
}else{ }else{
window.DrawShadowStringDecal(drawPos,finalLabel,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-2,1.0f); window.DrawShadowStringDecal(drawPos,finalLabel,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-4,1.0f);
} }
}else{ }else{
if(proportional){ if(proportional){
window.DrawStringPropDecal(drawPos,finalLabel,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-2,1.0f); window.DrawStringPropDecal(drawPos,finalLabel,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-4,1.0f);
}else{ }else{
window.DrawStringDecal(drawPos,finalLabel,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-2,1.0f); window.DrawStringDecal(drawPos,finalLabel,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x-4,1.0f);
} }
} }
} }

View File

@ -903,10 +903,19 @@ bool Player::Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag dama
if(Menu::IsMenuOpen()&&mod_dmg>0)Menu::CloseAllMenus(); if(Menu::IsMenuOpen()&&mod_dmg>0)Menu::CloseAllMenus();
const bool tookLethalDamage{int(mod_dmg)>=hp};
bool survivedHitDueToDefiance{false};
if(tookLethalDamage&&game->GetPlayer()->HasEnchant("Death Defiance"))survivedHitDueToDefiance=util::random(1.f)<="Death Defiance"_ENC["LETHAL DAMAGE AVOID CHANCE"]/100.f;
if(!IsDOT&&mod_dmg>0)game->ShowDamageVignetteOverlay(); if(!IsDOT&&mod_dmg>0){
Pixel vignetteOverlayCol{"Interface.Vignette Color"_Pixel};
if(tookLethalDamage&&survivedHitDueToDefiance)vignetteOverlayCol="Interface.Vignette Death Defiance Color"_Pixel;
game->ShowDamageVignetteOverlay(vignetteOverlayCol);
}
hp=std::max(0,hp-int(mod_dmg)); if(tookLethalDamage&&survivedHitDueToDefiance)ApplyIframes("Death Defiance"_ENC["LETHAL DAMAGE SURVIVE IFRAME TIME"]);
else hp=std::max(0,hp-int(mod_dmg));
if(!IsAlive()&&GameState::STATE!=GameState::states[States::DEATH])GameState::ChangeState(States::DEATH); if(!IsAlive()&&GameState::STATE!=GameState::states[States::DEATH])GameState::ChangeState(States::DEATH);

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 3 #define VERSION_PATCH 3
#define VERSION_BUILD 10653 #define VERSION_BUILD 10670
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

View File

@ -30,6 +30,9 @@ Interface
# Damage Vignette Overlay Color # Damage Vignette Overlay Color
Vignette Color = 218, 44, 143, 255 Vignette Color = 218, 44, 143, 255
# Damage Vignette Death Defiance Overlay Color
Vignette Death Defiance Color = 79, 255, 255, 255
# The original health display color. # The original health display color.
HUD Health Display Color = 255,255,255,255 HUD Health Display Color = 255,255,255,255

View File

@ -608,6 +608,8 @@ Item Enchants
Description = "{LETHAL DAMAGE AVOID CHANCE}% chance to avoid taking lethal damage." Description = "{LETHAL DAMAGE AVOID CHANCE}% chance to avoid taking lethal damage."
LETHAL DAMAGE AVOID CHANCE = 30% LETHAL DAMAGE AVOID CHANCE = 30%
# If the player took lethal damage, they are given iframes to survive longer.
LETHAL DAMAGE SURVIVE IFRAME TIME = 2.0s
# Stat, Lowest, Highest Value # Stat, Lowest, Highest Value
# Stat Modifier[0] = ..., 0, 0 # Stat Modifier[0] = ..., 0, 0

View File

@ -650,7 +650,7 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
pge->garbageCollector[key].decal=newDecal; pge->garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=pge->garbageCollector[key].decal; newDecal=pge->garbageCollector[key].decal;
@ -698,7 +698,7 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, std::string_view s
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
pge->garbageCollector[key].decal=newDecal; pge->garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=pge->garbageCollector[key].decal; newDecal=pge->garbageCollector[key].decal;
@ -730,7 +730,7 @@ void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
pge->garbageCollector[key].decal=newDecal; pge->garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=pge->garbageCollector[key].decal; newDecal=pge->garbageCollector[key].decal;
@ -743,7 +743,7 @@ void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
Decal*newShadowDecal=nullptr; Decal*newShadowDecal=nullptr;
if(!ShadowRerenderRequired){ if(!ShadowRerenderRequired){
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.y/scale.y*4)+adjustedShadowSizeFactor.y*2));
pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal; pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
}else{ }else{
newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal; newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal;
@ -782,7 +782,7 @@ void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
pge->garbageCollector[key].decal=newDecal; pge->garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=pge->garbageCollector[key].decal; newDecal=pge->garbageCollector[key].decal;
@ -795,7 +795,7 @@ void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
Decal*newShadowDecal=nullptr; Decal*newShadowDecal=nullptr;
if(!ShadowRerenderRequired){ if(!ShadowRerenderRequired){
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.y/scale.y*4)+adjustedShadowSizeFactor.y*2));
pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal; pge->garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
}else{ }else{
newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal; newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal;

View File

@ -3499,7 +3499,7 @@ namespace olc
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
garbageCollector[key].decal=newDecal; garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=garbageCollector[key].decal; newDecal=garbageCollector[key].decal;
@ -3531,7 +3531,7 @@ namespace olc
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
garbageCollector[key].decal=newDecal; garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=garbageCollector[key].decal; newDecal=garbageCollector[key].decal;
@ -3563,7 +3563,7 @@ namespace olc
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
garbageCollector[key].decal=newDecal; garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=garbageCollector[key].decal; newDecal=garbageCollector[key].decal;
@ -3576,7 +3576,7 @@ namespace olc
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
Decal*newShadowDecal=nullptr; Decal*newShadowDecal=nullptr;
if(!ShadowRerenderRequired){ if(!ShadowRerenderRequired){
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.y/scale.y*4)+adjustedShadowSizeFactor.y*2));
garbageCollector[key+"_SHADOW"].decal=newShadowDecal; garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
}else{ }else{
newShadowDecal=garbageCollector[key+"_SHADOW"].decal; newShadowDecal=garbageCollector[key+"_SHADOW"].decal;
@ -3673,7 +3673,7 @@ namespace olc
if(imageSize.x<1||imageSize.y<1)return; if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr; Decal*newDecal=nullptr;
if(!RerenderRequired){ if(!RerenderRequired){
newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.x/scale.x)); newDecal=new Decal(new Sprite(imageSize.x/scale.x,imageSize.y/scale.y));
garbageCollector[key].decal=newDecal; garbageCollector[key].decal=newDecal;
}else{ }else{
newDecal=garbageCollector[key].decal; newDecal=garbageCollector[key].decal;
@ -3686,7 +3686,7 @@ namespace olc
vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale; vf2d adjustedShadowSizeFactor=vf2d{shadowSizeFactor,shadowSizeFactor}*4/scale;
Decal*newShadowDecal=nullptr; Decal*newShadowDecal=nullptr;
if(!ShadowRerenderRequired){ if(!ShadowRerenderRequired){
newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.x/scale.x*4)+adjustedShadowSizeFactor.y*2)); newShadowDecal=new Decal(new Sprite((imageSize.x/scale.x*4)+adjustedShadowSizeFactor.x*2,(imageSize.y/scale.y*4)+adjustedShadowSizeFactor.y*2));
garbageCollector[key+"_SHADOW"].decal=newShadowDecal; garbageCollector[key+"_SHADOW"].decal=newShadowDecal;
}else{ }else{
newShadowDecal=garbageCollector[key+"_SHADOW"].decal; newShadowDecal=garbageCollector[key+"_SHADOW"].decal;

View File

@ -73,6 +73,10 @@ namespace olc::utils
class datafile class datafile
{ {
public: public:
enum class OverwriteMode{
NO_OVERWRITE,
OVERWRITE,
};
inline datafile() = default; inline datafile() = default;
inline static bool DEBUG_ACCESS_OPTIONS=false; inline static bool DEBUG_ACCESS_OPTIONS=false;
inline static bool INITIAL_SETUP_COMPLETE=false; inline static bool INITIAL_SETUP_COMPLETE=false;
@ -325,7 +329,7 @@ namespace olc::utils
return false; return false;
} }
inline static bool Read(datafile& n, const std::string& sFileName, const char sListSep = ',') inline static bool Read(datafile& n, const std::string& sFileName, const char sListSep = ',', const OverwriteMode mode=OverwriteMode::NO_OVERWRITE)
{ {
bool previousSetupState=INITIAL_SETUP_COMPLETE; bool previousSetupState=INITIAL_SETUP_COMPLETE;
INITIAL_SETUP_COMPLETE=false; INITIAL_SETUP_COMPLETE=false;
@ -393,7 +397,7 @@ namespace olc::utils
sPropName = line.substr(0, x); sPropName = line.substr(0, x);
trim(sPropName); trim(sPropName);
auto&top=stkPath.top().get(); auto&top=stkPath.top().get();
if(stkPath.top().get().HasProperty(sPropName))ERR(std::format("WARNING! Duplicate key found! Key {} already exists! Duplicate line: {}",sPropName,line)); if(mode==OverwriteMode::NO_OVERWRITE&&stkPath.top().get().HasProperty(sPropName))ERR(std::format("WARNING! Duplicate key found! Key {} already exists! Duplicate line: {}",sPropName,line));
// Extract the property value, which is all characters after // Extract the property value, which is all characters after
// the first assignment operator, trim any whitespace from ends // the first assignment operator, trim any whitespace from ends