diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj
index 0edd3d04..c69926ff 100644
--- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj
+++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj
@@ -349,6 +349,10 @@
+
+
+
+
@@ -575,6 +579,10 @@
+
+
+
+
diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
index 73f186aa..0e82ccea 100644
--- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
+++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
@@ -435,6 +435,9 @@
Header Files
+
+ Header Files
+
@@ -740,6 +743,9 @@
Source Files\Interface
+
+ Source Files
+
diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp
index bd7ef6f3..ad3f2759 100644
--- a/Adventures in Lestoria/AdventuresInLestoria.cpp
+++ b/Adventures in Lestoria/AdventuresInLestoria.cpp
@@ -199,6 +199,9 @@ bool AiL::OnUserCreate(){
InitializeLevels();
+ healthCounter.Initialize(&player->hp,"Interface.HUD Health Tick Rate"_F,"Interface.HUD Health Display Color"_Pixel,"Interface.HUD Heal Damage Color"_Pixel,"Interface.HUD Take Damage Color"_Pixel,"Interface.HUD Health Change Time"_F);
+ manaCounter.Initialize(&player->mana,"Interface.HUD Mana Tick Rate"_F,"Interface.HUD Mana Display Color"_Pixel,"Interface.HUD Restore Mana Color"_Pixel,"Interface.HUD Reduce Mana Color"_Pixel,"Interface.HUD Mana Change Time"_F);
+
//Initialize Camera.
camera=Camera2D{WINDOW_SIZE};
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
@@ -1402,6 +1405,9 @@ Player*AiL::GetPlayer(){
}
void AiL::RenderHud(){
+ healthCounter.Update();
+ manaCounter.Update();
+
auto RenderAimingCursor=[&](){
if(Input::UsingGamepad()&&Input::AxesActive()){
vf2d aimingLocation=player->GetAimingLocation();
@@ -1453,10 +1459,10 @@ void AiL::RenderHud(){
DrawDecal({2,2},GFX["heart.png"].Decal());
DrawDecal({2,20},GFX["mana.png"].Decal());
- std::string text=player->GetHealth()>0?std::to_string(player->GetHealth()):"X";
- std::string text_mana=std::to_string(player->GetMana());
- DrawShadowStringPropDecal({20,3},text,WHITE,BLACK,{2,2},INFINITE);
- DrawShadowStringPropDecal({24,23},text_mana,{192,192,255},BLACK,{1.5f,1.5f},INFINITE);
+ std::string text=player->GetHealth()>0?std::to_string(healthCounter.GetDisplayValue()):"X";
+ std::string text_mana=std::to_string(manaCounter.GetDisplayValue());
+ DrawShadowStringPropDecal({20,3},text,healthCounter.GetDisplayColor(),BLACK,{2,2},INFINITE);
+ DrawShadowStringPropDecal({24,23},text_mana,manaCounter.GetDisplayColor(),BLACK,{1.5f,1.5f},INFINITE);
if(player->notEnoughManaDisplay.second>0){
std::string displayText="Not enough mana for "+player->notEnoughManaDisplay.first+"!";
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)}-GetTextSizeProp(displayText)/2,displayText,DARK_RED,VERY_DARK_RED);
@@ -2106,10 +2112,8 @@ void AiL::ChangePlayerClass(Class cl){
player.reset(NEW Witch(player.get()));
}break;
}
- player->level=level;
+ player->level=1;
player->levelCap=levelCap;
- player->totalXPEarned=totalXPEarned;
- player->currentLevelXP=currentLevelXP;
player->stats=previousStats;
player->SetBaseStat("Health",DATA.GetProperty(player->GetClassName()+".BaseHealth").GetInt());
player->hp=player->GetBaseStat("Health");
@@ -2120,6 +2124,10 @@ void AiL::ChangePlayerClass(Class cl){
player->atkGrowthRate=float(DATA.GetProperty(player->GetClassName()+".AtkGrowthRate").GetReal());
player->money=oldMoney;
player->cooldownSoundInstance=cooldownSoundInstance;
+ player->AddXP(totalXPEarned);
+ player->AddAccumulatedXP(totalXPEarned);
+ game->healthCounter.UpdateNumberPointer(&player->hp);
+ game->manaCounter.UpdateNumberPointer(&player->mana);
sig::Animation::SetupPlayerAnimations();
GetPlayer()->UpdateIdleAnimation(DOWN);
GetPlayer()->SetItem1UseFunc(itemAbility1);
diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h
index 3daef371..696631ad 100644
--- a/Adventures in Lestoria/AdventuresInLestoria.h
+++ b/Adventures in Lestoria/AdventuresInLestoria.h
@@ -55,6 +55,7 @@ All rights reserved.
#include "Audio.h"
#include "olcPGEX_SplashScreen.h"
#include "olcPixelGameEngine.h"
+#include "DynamicCounter.h"
#define CreateBullet(type) BULLET_LIST.push_back(std::make_unique(type
#define EndBullet ));
@@ -137,6 +138,8 @@ private:
float fadeInDuration=0;
float fadeOutTotalTime=0;
bool disableFadeIn=false;
+ DynamicCounter healthCounter;
+ DynamicCounter manaCounter;
void ValidateGameStatus();
#ifndef __EMSCRIPTEN__
diff --git a/Adventures in Lestoria/DynamicCounter.cpp b/Adventures in Lestoria/DynamicCounter.cpp
new file mode 100644
index 00000000..82f35bcf
--- /dev/null
+++ b/Adventures in Lestoria/DynamicCounter.cpp
@@ -0,0 +1,99 @@
+#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 © 2023 The FreeType
+Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
+All rights reserved.
+*/
+#pragma endregion
+
+#include "DynamicCounter.h"
+#include "AdventuresInLestoria.h"
+#include "DEFINES.h"
+
+INCLUDE_game
+
+DynamicCounter::DynamicCounter(){}
+
+void DynamicCounter::Initialize(const int*number,float tickRate,Pixel originalCol,Pixel increaseCol,Pixel decreaseCol,float colorChangeTime){
+ this->targetNumber=number;
+ this->tickRate=tickRate;
+ this->originalCol=originalCol;
+ this->increaseCol=increaseCol;
+ this->decreaseCol=decreaseCol;
+ this->colorChangeTime=colorChangeTime;
+}
+
+void DynamicCounter::Update(){
+ if(targetNumber==nullptr)ERR("WARNING! This dynamic counter has not been properly initialized! Call Initialize() first!");
+ targetChangedTimer=std::max(0.f,targetChangedTimer-game->GetElapsedTime());
+
+ bool targetNumberChanged=*targetNumber!=lastTargetNumber;
+
+ tickTimer+=game->GetElapsedTime();
+ while(tickTimer>tickRate){
+ tickTimer-=tickRate;
+ if(displayNumber!=int(*targetNumber)){
+ if(displayNumber>int(*targetNumber)){
+ displayNumber--;
+
+ if(targetNumberChanged){
+ adjustedCol=decreaseCol;
+ targetChangedTimer=colorChangeTime;
+ }
+ }else{
+ displayNumber++;
+
+ if(targetNumberChanged){
+ adjustedCol=increaseCol;
+ targetChangedTimer=colorChangeTime;
+ }
+ }
+ }
+ }
+
+ lastTargetNumber=int(*targetNumber);
+
+ displayCol=PixelLerp(adjustedCol,originalCol,1-(targetChangedTimer/colorChangeTime));
+}
+
+const int&DynamicCounter::GetDisplayValue()const{
+ return displayNumber;
+}
+
+const Pixel&DynamicCounter::GetDisplayColor()const{
+ return displayCol;
+}
+
+void DynamicCounter::UpdateNumberPointer(const int*newPtr){
+ targetNumber=newPtr;
+}
\ No newline at end of file
diff --git a/Adventures in Lestoria/DynamicCounter.h b/Adventures in Lestoria/DynamicCounter.h
new file mode 100644
index 00000000..f74223d7
--- /dev/null
+++ b/Adventures in Lestoria/DynamicCounter.h
@@ -0,0 +1,63 @@
+#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 © 2023 The FreeType
+Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
+All rights reserved.
+*/
+#pragma endregion
+#pragma once
+
+#include "olcPixelGameEngine.h"
+
+class DynamicCounter{
+public:
+ DynamicCounter();
+ void Initialize(const int*number,float tickRate=0.01f,Pixel originalCol=WHITE,Pixel increaseCol=WHITE,Pixel decreaseCol=WHITE,float colorChangeTime=0.4f);
+ void Update();
+ const int&GetDisplayValue()const;
+ const Pixel&GetDisplayColor()const;
+ void UpdateNumberPointer(const int*newPtr);
+private:
+ int displayNumber;
+ const int*targetNumber=nullptr;
+ int lastTargetNumber;
+ float targetChangedTimer;
+ float colorChangeTime;
+ float tickRate;
+ float tickTimer;
+ Pixel originalCol;
+ Pixel displayCol;
+ Pixel adjustedCol;
+ Pixel increaseCol;
+ Pixel decreaseCol;
+};
\ No newline at end of file
diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp
index 4debdffd..6dfa5d68 100644
--- a/Adventures in Lestoria/Player.cpp
+++ b/Adventures in Lestoria/Player.cpp
@@ -1203,9 +1203,9 @@ const float Player::GetDamageReductionPct()const{
void Player::AddXP(const uint32_t xpGain){
currentLevelXP+=xpGain;
totalXPEarned+=xpGain;
- uint32_t nextLevelXP=NextLevelXPRequired();
if(Level()nextLevelXP){
+ uint32_t nextLevelXP=NextLevelXPRequired();
+ while(currentLevelXP>nextLevelXP){
currentLevelXP-=nextLevelXP;
level++;
OnLevelUp();
diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt
index f49a84dd..157290a2 100644
--- a/Adventures in Lestoria/TODO.txt
+++ b/Adventures in Lestoria/TODO.txt
@@ -16,7 +16,6 @@ Settings Menu
January 31st
============
-Make new unlocked nodes more obvious, made neighboring nodes more obvious
Implement Ursule, Mother of Bears Boss
Story proofreading/correcting/storyboarding
@@ -27,7 +26,6 @@ Story proofreading/correcting/storyboarding
- Export/Import Save Files Online/Offline
- Lock up unimplemented classes.
-- Don't enable all stage plates normally.
- Add Death screen (Zoom in on fatal blow, slow time down... Display some game over text... Allow retry or return to world map.)
diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h
index 56634d79..ad79f529 100644
--- a/Adventures in Lestoria/Version.h
+++ b/Adventures in Lestoria/Version.h
@@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 3
#define VERSION_PATCH 0
-#define VERSION_BUILD 6264
+#define VERSION_BUILD 6271
#define stringify(a) stringify_(a)
#define stringify_(a) #a
diff --git a/Adventures in Lestoria/assets/config/Interface.txt b/Adventures in Lestoria/assets/config/Interface.txt
index 5ee84070..2cc4c511 100644
--- a/Adventures in Lestoria/assets/config/Interface.txt
+++ b/Adventures in Lestoria/assets/config/Interface.txt
@@ -14,4 +14,34 @@ Interface
# The text color of input keys.
InputButtonTextCol = 175,199,191,255
+
+ # The original health display color.
+ HUD Health Display Color = 255,255,255,255
+
+ # The color the HUD changes when we take damage.
+ HUD Take Damage Color = 128,0,0,255
+
+ # The color the HUD changes when we take damage.
+ HUD Heal Damage Color = 0,192,0,255
+
+ # The amount of time it takes for the health to go from a damaging color back to its original color.
+ HUD Health Change Time = 0.4s
+
+ # How long between each reduction/addition of health.
+ HUD Health Tick Rate = 0.01s
+
+ # The original mana display color.
+ HUD Mana Display Color = 192,192,255,255
+
+ # The color the HUD changes when we take damage.
+ HUD Reduce Mana Color = 192,192,255,255
+
+ # The color the HUD changes when we take damage.
+ HUD Restore Mana Color = 192,192,255,255
+
+ # The amount of time it takes for the health to go from a damaging color back to its original color.
+ HUD Mana Change Time = 0.4s
+
+ # How long between each reduction/addition of health.
+ HUD Mana Tick Rate = 0.01s
}
\ No newline at end of file
diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe
index bf15321b..4430a127 100644
Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ