From f0169b06abac9c4a3fceb230a3cc7a6f9a9d41bd Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Tue, 26 Sep 2023 06:35:21 -0500 Subject: [PATCH] Display DPS tracker + encounter timer --- Crawler/Crawler.cpp | 90 ++++++++++++++++++++++++++++++++++++--------- Crawler/Crawler.h | 11 +++++- Crawler/Monster.cpp | 15 ++++++-- Crawler/Monster.h | 3 +- Crawler/Version.h | 2 +- Crawler/utils.cpp | 24 ++++++++++++ Crawler/utils.h | 1 + 7 files changed, 122 insertions(+), 24 deletions(-) diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index a90bc92a..3d22e0b7 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -123,7 +123,12 @@ bool Crawler::OnUserCreate(){ bool Crawler::OnUserUpdate(float fElapsedTime){ fElapsedTime=std::clamp(fElapsedTime,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. levelTime+=fElapsedTime; - bossDisplayTimer=std::max(0.f,bossDisplayTimer-fElapsedTime); + if(totalBossEncounterMobs>0){ + bossDisplayTimer=std::max(0.f,bossDisplayTimer-fElapsedTime); + } + if(encounterStarted){ + encounterDuration+=fElapsedTime; + } HandleUserInput(fElapsedTime); UpdateEffects(fElapsedTime); player->Update(fElapsedTime); @@ -1025,21 +1030,7 @@ void Crawler::RenderHud(){ std::string displayText=player->notificationDisplay.first; DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)-24}-GetTextSizeProp(displayText)/2,displayText,BLUE,VERY_DARK_BLUE); } - if(bossDisplayTimer>0){ - std::string displayText="- "+bossName+" -"; - - uint8_t alpha=0; - if(bossDisplayTimer>4){ - alpha=uint8_t((5-bossDisplayTimer)*255); - }else - if(bossDisplayTimer>1){ - alpha=255; - }else{ - alpha=uint8_t((bossDisplayTimer)*255); - } - vf2d textScale={3,5}; - DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/2)}-vf2d{GetTextSizeProp(displayText)}*textScale/2,displayText,{252, 186, 3, alpha},{128,0,0,alpha},textScale,2); - } + DisplayBossEncounterInfo(); 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.4,versionStr,WHITE,BLACK,{0.4,0.4},0.4); if("debug_player_info"_I){ @@ -1163,6 +1154,11 @@ void Crawler::LoadLevel(MapName map){ currentLevel=map; WORLD_SIZE={MAP_DATA[map].MapData.width,MAP_DATA[map].MapData.height}; levelTime=0; + bossName=""; + encounterDuration=0; + totalDamageDealt=0; + encounterStarted=false; + totalBossEncounterMobs=0; #pragma region Monster Spawn Data Setup for(auto key:MAP_DATA[map].SpawnerData){ @@ -1581,8 +1577,11 @@ void Crawler::InitializeLevels(){ LEVEL_NAMES.SetInitialized(); } -void Crawler::SpawnMonster(vf2d pos,MonsterData*data,bool upperLevel){ - monstersToBeSpawned.push_back(Monster(pos,*data,upperLevel)); +void Crawler::SpawnMonster(vf2d pos,MonsterData*data,bool upperLevel,bool isBossSpawn){ + monstersToBeSpawned.push_back(Monster(pos,*data,upperLevel,isBossSpawn)); + if(isBossSpawn){ + totalBossEncounterMobs++; + } } void Crawler::DrawPie(vf2d center,float radius,float degreesCut,Pixel col){ @@ -1609,4 +1608,59 @@ void Crawler::InitializeDefaultKeybinds(){ void Crawler::SetBossNameDisplay(std::string name,float time){ bossName=name; bossDisplayTimer=time; +} + +bool Crawler::InBossEncounter(){ + return bossName!=""; +} + +void Crawler::StartBossEncounter(){ + if(!encounterStarted){ + encounterStarted=true; + totalDamageDealt=encounterDuration=0; + } +} + +void Crawler::DisplayBossEncounterInfo(){ + if(bossDisplayTimer>0){ + std::string displayText="- "+bossName+" -"; + + uint8_t alpha=0; + if(bossDisplayTimer>4){ + alpha=uint8_t((5-bossDisplayTimer)*255); + }else + if(bossDisplayTimer>1){ + alpha=255; + }else{ + alpha=uint8_t((bossDisplayTimer)*255); + } + vf2d textScale={3,5}; + DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/2)}-vf2d{GetTextSizeProp(displayText)}*textScale/2,displayText,{252, 186, 3, alpha},{128,0,0,alpha},textScale,2); + } + if(InBossEncounter()){ + Pixel displayCol=totalBossEncounterMobs==0?Pixel{224, 133, 29}:WHITE; + std::string timeDisplay=util::timerStr(encounterDuration); + vf2d timerTextSize=GetTextSizeProp(timeDisplay); + DrawShadowStringPropDecal(vf2d{ScreenWidth()-2-timerTextSize.x,2+10*0},timeDisplay,displayCol); + vf2d displayTextSize=GetTextSizeProp(bossName); + DrawShadowStringPropDecal(vf2d{ScreenWidth()-2-displayTextSize.x,2+10*1},bossName,displayCol); + if(encounterDuration>=1){ + std::string dpsText="DPS: "+std::to_string(int(totalDamageDealt/encounterDuration)); + vf2d dpsDisplayTextSize=GetTextSizeProp(dpsText); + DrawShadowStringPropDecal(vf2d{ScreenWidth()-2-dpsDisplayTextSize.x,2+10*2},dpsText,displayCol); + } + } +} + + +void Crawler::BossDamageDealt(int damage){ + totalDamageDealt+=damage; +} + +void Crawler::ReduceBossEncounterMobCount(){ + totalBossEncounterMobs--; + if(totalBossEncounterMobs<0){ + std::cout<<"WARNING! Boss Encounter mob count is less than zero, THIS SHOULD NOT BE HAPPENING!"<monstersToBeSpawned; float bossDisplayTimer=0; std::string bossName; + int totalDamageDealt=0; + float encounterDuration=0; + bool encounterStarted=false; + int totalBossEncounterMobs=0; public: Crawler(); bool OnUserCreate() override; @@ -115,11 +119,16 @@ public: void RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos); void RenderTile(TileRenderData&tileSheet,Pixel col); bool IsReflectiveTile(TilesheetData tileSheet,int tileID); - void SpawnMonster(vf2d pos,MonsterData*data,bool upperLevel=false); //Queues a monster for spawning on the next frame. + void SpawnMonster(vf2d pos,MonsterData*data,bool upperLevel=false,bool isBossSpawn=false); //Queues a monster for spawning on the next frame. void DrawPie(vf2d center,float radius,float degreesCut,Pixel col); void RenderCooldowns(); void InitializeDefaultKeybinds(); void SetBossNameDisplay(std::string name,float time=5); + bool InBossEncounter(); + void StartBossEncounter(); + void DisplayBossEncounterInfo(); + void BossDamageDealt(int damage); + void ReduceBossEncounterMobCount(); struct TileGroupData{ vi2d tilePos; diff --git a/Crawler/Monster.cpp b/Crawler/Monster.cpp index 4d8fb7fa..8e0504cb 100644 --- a/Crawler/Monster.cpp +++ b/Crawler/Monster.cpp @@ -23,8 +23,8 @@ safemapSTRATEGY_DATA; safemapSTRATEGY_ID_DATA; std::mapMonsterData::imgs; -Monster::Monster(vf2d pos,MonsterData data,bool upperLevel): - pos(pos),hp(data.GetHealth()),maxhp(data.GetHealth()),atk(data.GetAttack()),moveSpd(data.GetMoveSpdMult()),size(data.GetSizeMult()),targetSize(data.GetSizeMult()),strategy(data.GetAIStrategy()),id(data.GetID()),upperLevel(upperLevel){ +Monster::Monster(vf2d pos,MonsterData data,bool upperLevel,bool bossMob): + pos(pos),hp(data.GetHealth()),maxhp(data.GetHealth()),atk(data.GetAttack()),moveSpd(data.GetMoveSpdMult()),size(data.GetSizeMult()),targetSize(data.GetSizeMult()),strategy(data.GetAIStrategy()),id(data.GetID()),upperLevel(upperLevel),isBoss(bossMob){ bool firstAnimation=true; for(std::string&anim:data.GetAnimations()){ animation.AddState(anim,ANIMATION_DATA[anim]); @@ -243,6 +243,9 @@ std::string Monster::GetDeathAnimationName(){ } bool Monster::Hurt(int damage,bool onUpperLevel,float z){ if(!IsAlive()||onUpperLevel!=OnUpperLevel()||HasIframes()||abs(GetZ()-z)>1) return false; + if(game->InBossEncounter()){ + game->StartBossEncounter(); + } float mod_dmg=damage; for(Buff&b:GetBuffs(BuffType::DAMAGE_REDUCTION)){ mod_dmg-=damage*b.intensity; @@ -258,9 +261,15 @@ bool Monster::Hurt(int damage,bool onUpperLevel,float z){ lastHitTimer=0.05; if(!IsAlive()){ animation.ChangeState(internal_animState,GetDeathAnimationName()); + if(isBoss){ + game->ReduceBossEncounterMobCount(); + } }else{ hp=std::max(1,hp); //Make sure it stays alive if it's supposed to be alive... } + if(game->InBossEncounter()){ + game->BossDamageDealt(int(mod_dmg)); + } GetInt(Attribute::HITS_UNTIL_DEATH)=std::max(0,GetInt(Attribute::HITS_UNTIL_DEATH)-1); iframe_timer=GetFloat(Attribute::IFRAME_TIME_UPON_HIT); return true; @@ -291,7 +300,7 @@ void MonsterSpawner::SetTriggered(bool trigger,bool spawnMonsters){ triggered=trigger; if(spawnMonsters){ for(std::pair&monsterInfo:monsters){ - game->SpawnMonster(pos+monsterInfo.second,&MONSTER_DATA[monsterInfo.first],DoesUpperLevelSpawning()); + game->SpawnMonster(pos+monsterInfo.second,&MONSTER_DATA[monsterInfo.first],DoesUpperLevelSpawning(),bossNameDisplay!=""); } if(bossNameDisplay!=""){ game->SetBossNameDisplay(bossNameDisplay); diff --git a/Crawler/Monster.h b/Crawler/Monster.h index 5ae1e8e9..bbb938bf 100644 --- a/Crawler/Monster.h +++ b/Crawler/Monster.h @@ -94,10 +94,11 @@ private: bool diesNormally=true; //If set to false, the monster death is handled in a special way. Set it to true when it's time to die. float targetSize=0; std::map>attributes; + bool isBoss=false; protected: public: Monster()=delete; - Monster(vf2d pos,MonsterData data,bool upperLevel=false); + Monster(vf2d pos,MonsterData data,bool upperLevel=false,bool bossMob=false); vf2d&GetPos(); int GetHealth(); int GetAttack(); diff --git a/Crawler/Version.h b/Crawler/Version.h index f9b6d416..d5190273 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -2,7 +2,7 @@ #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 0 -#define VERSION_BUILD 1567 +#define VERSION_BUILD 1572 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Crawler/utils.cpp b/Crawler/utils.cpp index a368bddf..1c0e047e 100644 --- a/Crawler/utils.cpp +++ b/Crawler/utils.cpp @@ -22,4 +22,28 @@ float util::radToDeg(float rad){ float util::lerp(float n1,float n2,double t){ return n1*(1-t)+n2*t; +} + +std::string util::timerStr(float time){ + int seconds=int(time); + int hours=seconds/3600; + int minutes=seconds/60; + + std::string timeStr=""; + if(hours>0){ + if(hours<10)timeStr+="0"; + timeStr+=std::to_string(hours)+":"; + } + + if(minutes>0){ + if(minutes%60<10)timeStr+="0"; + timeStr+=std::to_string(minutes%60)+":"; + } + + if(seconds>0){ + if(seconds%60<10&&minutes>0)timeStr+="0"; + timeStr+=std::to_string(seconds%60); + } + + return timeStr; } \ No newline at end of file diff --git a/Crawler/utils.h b/Crawler/utils.h index 42e2763b..24e583db 100644 --- a/Crawler/utils.h +++ b/Crawler/utils.h @@ -11,4 +11,5 @@ namespace util{ float degToRad(float deg); float radToDeg(float rad); float lerp(float n1,float n2,double t); + std::string timerStr(float time); } \ No newline at end of file