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.

mac-build
sigonasr2 4 months ago
parent 62086cbd92
commit cfd73ab036
  1. 31
      Adventures in Lestoria Tests/EnchantTests.cpp
  2. 2
      Adventures in Lestoria Tests/EngineTests.cpp
  3. 2
      Adventures in Lestoria Tests/ItemTests.cpp
  4. 2
      Adventures in Lestoria Tests/MonsterTests.cpp
  5. 2
      Adventures in Lestoria Tests/PlayerTests.cpp
  6. 40
      Adventures in Lestoria/AdventuresInLestoria.cpp
  7. 4
      Adventures in Lestoria/AdventuresInLestoria.h
  8. 2
      Adventures in Lestoria/DEFINES.h
  9. 16
      Adventures in Lestoria/MenuLabel.h
  10. 13
      Adventures in Lestoria/Player.cpp
  11. 2
      Adventures in Lestoria/Version.h
  12. 3
      Adventures in Lestoria/assets/config/Interface.txt
  13. 2
      Adventures in Lestoria/assets/config/items/ItemEnchants.txt
  14. 12
      Adventures in Lestoria/olcPGEX_ViewPort.h
  15. 12
      Adventures in Lestoria/olcPixelGameEngine.h
  16. 8
      Adventures in Lestoria/olcUTIL_DataFile.h
  17. BIN
      x64/Release/Adventures in Lestoria.exe

@ -50,6 +50,7 @@ using namespace olc::utils;
INCLUDE_GFX
INCLUDE_ITEM_DATA
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng;
@ -71,6 +72,7 @@ namespace EnchantTests
Player*player;
const HWButton*testKey;
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.
testGame.reset(new AiL(true));
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.");
}
}
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.");
}
};
}

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

@ -48,6 +48,7 @@ using namespace olc::utils;
INCLUDE_GFX
INCLUDE_ITEM_DATA
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng;
@ -61,6 +62,7 @@ namespace ItemTests
Player*player;
HWButton*testKey;
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.
testGame.reset(new AiL(true));
ItemAttribute::Initialize();

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

@ -49,6 +49,7 @@ using namespace olc::utils;
INCLUDE_GFX
INCLUDE_ITEM_DATA
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_INITIALIZEGAMECONFIGURATIONS
extern std::mt19937 rng;
@ -62,6 +63,7 @@ namespace PlayerTests
Player*player;
HWButton*testKey;
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.
testGame.reset(new AiL(true));
ItemAttribute::Initialize();

@ -161,15 +161,33 @@ float AiL::SIZE_CHANGE_SPEED=1;
AiL::AiL(bool testingMode){
olc_SetTestingMode(testingMode);
GFX.Reset();
DATA.Reset();
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;
game=this;
gameStarted=time(NULL);
}
void AiL::InitializeGameConfigurations(){
void InitializeGameConfigurations(){
DATA.Reset();
utils::datafile::Read(DATA,"assets/config/configuration.txt");
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_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_SET_CONFIG);
}
@ -229,8 +242,6 @@ void AiL::InitializeGameConfigurations(){
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();
for(const std::string&cl:values){
LOG(cl);
@ -2060,10 +2071,9 @@ void AiL::RenderHud(){
hudOverlay.Draw();
Pixel vignetteOverlayColor="Interface.Vignette Color"_Pixel;
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);
DrawDecal({0,0},GFX["vignette.png"].Decal(),{1.f,1.f},vignetteOverlayColor);
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},vignetteOverlayCol);
}
void AiL::RenderCooldowns(){
@ -3080,6 +3090,7 @@ int main(const int argn,char**args)
}
}
{
InitializeGameConfigurations();
AiL demo;
demo.UsingSteamAPI(usingSteam);
@ -4334,8 +4345,9 @@ const float AiL::GetEncounterDuration()const{
return encounterDuration;
}
void AiL::ShowDamageVignetteOverlay(){
void AiL::ShowDamageVignetteOverlay(const Pixel col){
vignetteDisplayTime="Interface.Vignette Appearance Time"_F+"Interface.Vignette Fadeout Time"_F;
vignetteOverlayCol=col;
}
void AiL::GlobalGameUpdates(){

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

@ -73,6 +73,8 @@ using MonsterSpawnerID=int;
#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
#undef INFINITE
#define INFINITE 999999

@ -92,15 +92,15 @@ protected:
vf2d adjustedScale={scale,scale};
vf2d labelTextSize=
proportional?
vf2d(game->GetWrappedTextSizeProp(finalLabel,rect.size.x-2,adjustedScale)):
vf2d(game->GetWrappedTextSize(finalLabel,rect.size.x-2,adjustedScale));
vf2d(game->GetWrappedTextSizeProp(finalLabel,rect.size.x-4,adjustedScale)):
vf2d(game->GetWrappedTextSize(finalLabel,rect.size.x-4,adjustedScale));
if(fitToLabel){
labelTextSize=
proportional?
vf2d(game->GetTextSizeProp(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){
adjustedScale.x/=sizeRatio;
labelTextSize.x/=sizeRatio;
@ -110,7 +110,7 @@ protected:
vf2d drawPos=vf2d{-1,0}+rect.middle()-vf2d{labelTextSize}/2; //Assume centered.
if(!centered){
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
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{
if(shadow){
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{
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{
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{
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);
}
}
}

@ -903,10 +903,19 @@ bool Player::Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag dama
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);

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

@ -30,6 +30,9 @@ Interface
# Damage Vignette Overlay Color
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.
HUD Health Display Color = 255,255,255,255

@ -608,6 +608,8 @@ Item Enchants
Description = "{LETHAL DAMAGE AVOID CHANCE}% chance to avoid taking lethal damage."
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 Modifier[0] = ..., 0, 0

@ -650,7 +650,7 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText
if(imageSize.x<1||imageSize.y<1)return;
Decal*newDecal=nullptr;
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;
}else{
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;
Decal*newDecal=nullptr;
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;
}else{
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;
Decal*newDecal=nullptr;
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;
}else{
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;
Decal*newShadowDecal=nullptr;
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;
}else{
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;
Decal*newDecal=nullptr;
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;
}else{
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;
Decal*newShadowDecal=nullptr;
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;
}else{
newShadowDecal=pge->garbageCollector[key+"_SHADOW"].decal;

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

@ -73,6 +73,10 @@ namespace olc::utils
class datafile
{
public:
enum class OverwriteMode{
NO_OVERWRITE,
OVERWRITE,
};
inline datafile() = default;
inline static bool DEBUG_ACCESS_OPTIONS=false;
inline static bool INITIAL_SETUP_COMPLETE=false;
@ -325,7 +329,7 @@ namespace olc::utils
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;
INITIAL_SETUP_COMPLETE=false;
@ -393,7 +397,7 @@ namespace olc::utils
sPropName = line.substr(0, x);
trim(sPropName);
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
// the first assignment operator, trim any whitespace from ends

Loading…
Cancel
Save