Cherry pick Boss indicator and knockback bugfixes into demo build from commit 862d047b06. Release Build 9420. Demo Patch 3.

sigonasr2 9 months ago
parent 71dea81ff5
commit 619cd19bcb
  1. 149
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 3
      Adventures in Lestoria/AdventuresInLestoria.h
  3. 2
      Adventures in Lestoria/Item.cpp
  4. 2
      Adventures in Lestoria/LoadingScreen.cpp
  5. 44
      Adventures in Lestoria/Monster.cpp
  6. 1
      Adventures in Lestoria/Monster.h
  7. 5
      Adventures in Lestoria/MonsterData.cpp
  8. 2
      Adventures in Lestoria/MonsterData.h
  9. 26
      Adventures in Lestoria/Player.cpp
  10. 4
      Adventures in Lestoria/SaveFile.cpp
  11. 2
      Adventures in Lestoria/State_Death.cpp
  12. 4
      Adventures in Lestoria/State_LevelComplete.cpp
  13. 4
      Adventures in Lestoria/State_OverworldMap.cpp
  14. 2
      Adventures in Lestoria/Version.h
  15. BIN
      Adventures in Lestoria/assets/bossIndicator.png
  16. BIN
      Adventures in Lestoria/assets/bossIndicatorStripe.png
  17. 1
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  18. BIN
      Adventures in Lestoria/assets/gamepack.pak
  19. 20
      Adventures in Lestoria/olcPGEX_ViewPort.h
  20. 24
      Adventures in Lestoria/olcPixelGameEngine.h
  21. BIN
      x64/Release/Adventures in Lestoria.exe

@ -1669,58 +1669,6 @@ void AiL::RenderWorld(float fElapsedTime){
}
#pragma endregion
for(std::vector<std::shared_ptr<DamageNumber>>::iterator it=DAMAGENUMBER_LIST.begin();it!=DAMAGENUMBER_LIST.end();++it){
DamageNumber*dn=(*it).get();
#define NumberScalesWithDamage true
#define NormalNumber false
auto DrawDamageNumber=[&](const bool ScaleWithNumber,std::string_view text,std::pair<Pixel,Pixel>colorsEnemy,std::pair<Pixel,Pixel>colorsFriendly,vf2d scaling={1.f,1.f}){
vf2d textSize=GetTextSizeProp(text)*scaling;
if(!dn->friendly){
vf2d additionalScaling={1.f,1.f};
if(ScaleWithNumber)additionalScaling=dn->size;
textSize*=additionalScaling;
vf2d drawPos=dn->pos-textSize/2.f;
drawPos.x=std::clamp(drawPos.x,view.GetWorldTL().x,view.GetWorldBR().x-textSize.x);
drawPos.y=std::clamp(drawPos.y,view.GetWorldTL().y,view.GetWorldBR().y-textSize.y);
view.DrawShadowStringPropDecal(drawPos,text,colorsEnemy.first,colorsEnemy.second,scaling*additionalScaling);
}else{
vf2d drawPos=dn->pos-textSize/2.f;
drawPos.x=std::clamp(drawPos.x,view.GetWorldTL().x,view.GetWorldBR().x-textSize.x);
drawPos.y=std::clamp(drawPos.y,view.GetWorldTL().y,view.GetWorldBR().y-textSize.y);
view.DrawShadowStringPropDecal(drawPos,text,colorsFriendly.first,colorsFriendly.second,scaling);
}
};
switch(dn->type){
case HEALTH_LOSS:{
std::string text=std::to_string(dn->damage);
DrawDamageNumber(NumberScalesWithDamage,text,{DARK_RED,{0,0,0,0}},{RED,VERY_DARK_GREY});
}break;
case HEALTH_GAIN:{
std::string text="+"+std::to_string(dn->damage);
DrawDamageNumber(NormalNumber,text,{DARK_GREEN,{0,0,0,0}},{GREEN,VERY_DARK_GREY});
}break;
case MANA_GAIN:{
std::string text="+"+std::to_string(dn->damage);
DrawDamageNumber(NormalNumber,text,{BLUE,VERY_DARK_GREY},{BLUE,VERY_DARK_GREY});
}break;
case INTERRUPT:{
std::string text="Interrupted!";
DrawDamageNumber(NormalNumber,text,{BLACK,VERY_DARK_GREY},{BLACK,VERY_DARK_GREY},{0.5f,1});
}break;
case CRIT:{
std::string text=std::to_string(dn->damage);
DrawDamageNumber(NumberScalesWithDamage,text,{YELLOW,DARK_YELLOW},{BLACK,{0,0,0,0}});
}break;
}
}
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
m->strategyDrawOverlay(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy());
}
@ -1766,6 +1714,38 @@ void AiL::RenderHud(){
}
}
};
#pragma region Boss Indicators
if(bossIndicatorPos.has_value()){
const vf2d&bossIndicator=bossIndicatorPos.value();
const bool BossIsOutsideView=!geom2d::overlaps(geom2d::rect<float>{view.GetWorldTL(),view.GetWorldVisibleArea()},bossIndicator);
if(BossIsOutsideView){
const bool flicker=sinf(GetRunTime())>0.5f&&sinf(GetRunTime())<0.55f;
#pragma region Side Indicators
const float yPos{std::clamp(view.WorldToScreen(bossIndicator).y,0.f,view.GetWorldVisibleArea().y)};
if(bossIndicator.x<view.GetWorldTL().x){ //Left-side indicator
DrawRotatedDecal({0,yPos},GFX["bossIndicator.png"].Decal(),0.f,{0,16},{8,1},flicker?RED:DARK_RED);
}else
if(bossIndicator.x>view.GetWorldBR().x){
DrawRotatedDecal({float(ScreenWidth()-8),yPos},GFX["bossIndicator.png"].Decal(),0.f,{0,16},{8,1},flicker?RED:DARK_RED);
}
#pragma endregion
#pragma region Top+Bottom Indicators
const float xPos{std::clamp(view.WorldToScreen(bossIndicator).x,0.f,view.GetWorldVisibleArea().x)};
if(bossIndicator.y<view.GetWorldTL().y){ //Left-side indicator
DrawRotatedDecal({xPos,4},GFX["bossIndicator.png"].Decal(),PI/2,{0.5f,16.f},{8,1},flicker?RED:DARK_RED);
}else
if(bossIndicator.y>view.GetWorldBR().y){
DrawRotatedDecal({xPos,float(ScreenHeight()-4)},GFX["bossIndicator.png"].Decal(),PI/2,{0.5f,16.f},{8,1},flicker?RED:DARK_RED);
}
#pragma endregion
}
}
#pragma endregion
minimap.Update();
minimap.Draw();
@ -1798,7 +1778,7 @@ void AiL::RenderHud(){
Pixel healthOutlineCol=BLACK;
if(player->GetHealth()/player->GetMaxHealth()<="Player.Health Warning Pct"_F/100.f){
float runTimeAmt=fmod(GetRuntime(),"Player.Health Warning Flicker Time"_F*2);
float runTimeAmt=fmod(GetRunTime(),"Player.Health Warning Flicker Time"_F*2);
if(runTimeAmt<"Player.Health Warning Flicker Time"_F){
healthOutlineCol="Player.Health Warning Outline Color"_Pixel;
}
@ -1842,6 +1822,59 @@ void AiL::RenderHud(){
}
DisplayBossEncounterInfo();
for(std::vector<std::shared_ptr<DamageNumber>>::iterator it=DAMAGENUMBER_LIST.begin();it!=DAMAGENUMBER_LIST.end();++it){
DamageNumber*dn=(*it).get();
#define NumberScalesWithDamage true
#define NormalNumber false
auto DrawDamageNumber=[&](const bool ScaleWithNumber,std::string_view text,std::pair<Pixel,Pixel>colorsEnemy,std::pair<Pixel,Pixel>colorsFriendly,vf2d scaling={1.f,1.f}){
vf2d textSize=GetTextSizeProp(text)*scaling;
if(!dn->friendly){
vf2d additionalScaling={1.f,1.f};
if(ScaleWithNumber)additionalScaling=dn->size;
textSize*=additionalScaling;
vf2d drawPos=dn->pos-textSize/2.f;
drawPos.x=std::clamp(drawPos.x,view.GetWorldTL().x,view.GetWorldBR().x-textSize.x);
drawPos.y=std::clamp(drawPos.y,view.GetWorldTL().y,view.GetWorldBR().y-textSize.y);
view.DrawShadowStringPropDecal(drawPos,text,colorsEnemy.first,colorsEnemy.second,scaling*additionalScaling);
}else{
vf2d drawPos=dn->pos-textSize/2.f;
drawPos.x=std::clamp(drawPos.x,view.GetWorldTL().x,view.GetWorldBR().x-textSize.x);
drawPos.y=std::clamp(drawPos.y,view.GetWorldTL().y,view.GetWorldBR().y-textSize.y);
view.DrawShadowStringPropDecal(drawPos,text,colorsFriendly.first,colorsFriendly.second,scaling);
}
};
switch(dn->type){
case HEALTH_LOSS:{
std::string text=std::to_string(dn->damage);
DrawDamageNumber(NumberScalesWithDamage,text,{DARK_RED,{0,0,0,0}},{RED,VERY_DARK_GREY});
}break;
case HEALTH_GAIN:{
std::string text="+"+std::to_string(dn->damage);
DrawDamageNumber(NormalNumber,text,{DARK_GREEN,{0,0,0,0}},{GREEN,VERY_DARK_GREY});
}break;
case MANA_GAIN:{
std::string text="+"+std::to_string(dn->damage);
DrawDamageNumber(NormalNumber,text,{BLUE,VERY_DARK_GREY},{BLUE,VERY_DARK_GREY});
}break;
case INTERRUPT:{
std::string text="Interrupted!";
DrawDamageNumber(NormalNumber,text,{BLACK,VERY_DARK_GREY},{BLACK,VERY_DARK_GREY},{0.5f,1});
}break;
case CRIT:{
std::string text=std::to_string(dn->damage);
DrawDamageNumber(NumberScalesWithDamage,text,{YELLOW,DARK_YELLOW},{BLACK,{0,0,0,0}});
}break;
}
}
#ifdef _DEBUG
if("debug_player_info"_I){
DrawShadowStringDecal({0,128},player->GetPos().str());
@ -2148,6 +2181,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
}
#pragma endregion
bossIndicatorPos.reset();
SPAWNER_LIST.clear();
foregroundTileGroups.clear();
upperForegroundTileGroups.clear();
@ -3507,7 +3541,7 @@ void AiL::ValidateGameStatus(){
void AiL::RenderVersionInfo(){
saveGameDisplayTime=std::max(0.f,saveGameDisplayTime-game->GetElapsedTime());
if(saveGameDisplayTime>3.f){
DrawShadowStringDecal({4.f,4.f},"Saving Game...",{255,255,255,uint8_t((sin(game->GetRuntime())+1)*127)},{0,0,0,uint8_t((sin(game->GetRuntime())+1)*127)});
DrawShadowStringDecal({4.f,4.f},"Saving Game...",{255,255,255,uint8_t((sin(game->GetRunTime())+1)*127)},{0,0,0,uint8_t((sin(game->GetRunTime())+1)*127)});
}else
if(saveGameDisplayTime>0.f){
uint8_t alpha=uint8_t(util::lerp(0,255,saveGameDisplayTime/3.f));
@ -3984,6 +4018,7 @@ rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filt
void AiL::UpdateMonsters(){
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(m->HasArrowIndicator())bossIndicatorPos=m->GetPos();
m->Update(game->GetElapsedTime());
}
for(Monster&m:game->monstersToBeSpawned){
@ -4015,6 +4050,8 @@ void AiL::ShowDamageVignetteOverlay(){
}
void AiL::GlobalGameUpdates(){
bossIndicatorPos={};
levelTime+=GetElapsedTime();
SteamAPI_RunCallbacks();
STEAMINPUT(
@ -4101,4 +4138,8 @@ void AiL::ComputeModeColors(TilesetData&tileset){
#pragma endregion
}
}
}
void AiL::SetBossIndicatorPos(const vf2d pos){
bossIndicatorPos=pos;
}

@ -200,6 +200,7 @@ private:
Audio audioEngine;
SteamKeyboardCallbackHandler*steamKeyboardCallbackListener=nullptr;
SteamStatsReceivedHandler*steamStatsReceivedHandlerListener=nullptr;
std::optional<vf2d>bossIndicatorPos{};
public:
AiL();
bool OnUserCreate() override;
@ -337,7 +338,7 @@ public:
void SetCompletedStageFlag();
void ResetCompletedStageFlag();
Minimap minimap;
void SetBossIndicatorPos(const vf2d pos);
struct TileGroupData{
vi2d tilePos;
int layer;

@ -1015,7 +1015,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));
Pixel shimmeringCol=PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f));
col=util::PixelToHTMLColorCode(shimmeringCol);
}

@ -90,7 +90,7 @@ void LoadingScreen::Draw(){
}
game->GetPlayer()->GetWalkEAnimation();
Animate2D::FrameSequence&playerWalkE=ANIMATION_DATA[game->GetPlayer()->GetWalkEAnimation()];
game->DrawPartialRotatedDecal({(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f),WINDOW_SIZE.y-36.f},playerWalkE.GetFrame(game->GetRuntime()).GetSourceImage()->Decal(),game->GetPlayer()->GetSpinAngle(),{12,12},playerWalkE.GetFrame(game->GetRuntime()).GetSourceRect().pos,playerWalkE.GetFrame(game->GetRuntime()).GetSourceRect().size,playerScale*scale,blendCol);
game->DrawPartialRotatedDecal({(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f),WINDOW_SIZE.y-36.f},playerWalkE.GetFrame(game->GetRunTime()).GetSourceImage()->Decal(),game->GetPlayer()->GetSpinAngle(),{12,12},playerWalkE.GetFrame(game->GetRunTime()).GetSourceRect().pos,playerWalkE.GetFrame(game->GetRunTime()).GetSourceRect().size,playerScale*scale,blendCol);
}
}

@ -237,7 +237,7 @@ bool Monster::Update(float fElapsedTime){
monsterHurtSoundCooldown=std::max(0.f,monsterHurtSoundCooldown-fElapsedTime);
lastHitPlayer=std::max(0.f,lastHitPlayer-fElapsedTime);
lastPathfindingCooldown=std::max(0.f,lastPathfindingCooldown-fElapsedTime);
if(HasArrowIndicator())game->SetBossIndicatorPos(GetPos());
if(size!=targetSize){
if(size>targetSize){
size=std::max(targetSize,size-AiL::SIZE_CHANGE_SPEED*fElapsedTime);
@ -275,9 +275,18 @@ bool Monster::Update(float fElapsedTime){
m->Collision(*this);
geom2d::line line(pos,m->GetPos());
float dist = line.length();
while(dist<=0.001){
line={pos+vf2d{util::random(0.2f)-0.1f,util::random(0.2f)-0.1f},m->GetPos()};
dist=line.length();
}
m->SetPos(line.rpoint(dist*1.1f));
if(m->IsAlive()){
vel=line.vector().norm()*-128;
float knockbackStrength=1.f;
std::vector<Buff> knockbackBuffs=m->GetBuffs(COLLISION_KNOCKBACK_STRENGTH);
for(Buff&b:knockbackBuffs){
knockbackStrength+=b.intensity;
}
Knockback(line.vector().norm()*-128*knockbackStrength);
}
}
}
@ -413,33 +422,11 @@ void Monster::Collision(Player*p){
}
}
#pragma region Knockback due to buffs
vf2d knockbackVecNorm=geom2d::line<float>(GetPos(),p->GetPos()).vector().norm();
float knockbackStrength=0.f;
std::vector<Buff> knockbackBuffs=GetBuffs(COLLISION_KNOCKBACK_STRENGTH);
for(Buff&b:knockbackBuffs){
knockbackStrength+=b.intensity;
}
p->Knockback(knockbackVecNorm*knockbackStrength);
#pragma endregion
B(Attribute::COLLIDED_WITH_PLAYER)=true;
Collision();
}
void Monster::Collision(Monster&m){
#pragma region Knockback due to buffs
vf2d knockbackVecNorm=geom2d::line<float>(GetPos(),m.GetPos()).vector().norm();
float knockbackStrength=0.f;
std::vector<Buff> knockbackBuffs=GetBuffs(COLLISION_KNOCKBACK_STRENGTH);
for(Buff&b:knockbackBuffs){
knockbackStrength+=b.intensity;
}
m.Knockback(knockbackVecNorm*knockbackStrength);
#pragma endregion
Collision();
}
void Monster::Collision(){
@ -785,7 +772,10 @@ geom2d::circle<float>Monster::Hitbox(){
void Monster::Knockback(const vf2d&vel){
//A new angle will be applied, but will be constrained by whichever applied velocity is strongest (either the current velocity, or the new one). This prevents continuous uncapped velocities to knockbacks applied.
float maxVelThreshold=std::max(vel.mag(),this->vel.mag());
if(vel==vf2d{})return;
float maxVelThreshold;
if(this->vel==vf2d{})maxVelThreshold=vel.mag();
else maxVelThreshold=std::max(vel.mag(),this->vel.mag());
this->vel+=vel;
float newVelAngle=this->vel.polar().y;
this->vel=vf2d{maxVelThreshold,newVelAngle}.cart();
@ -849,4 +839,8 @@ const bool Monster::IsNPC()const{
const bool MonsterData::IsNPC()const{
return isNPC;
}
const bool Monster::HasArrowIndicator()const{
return MONSTER_DATA.at(GetName()).HasArrowIndicator();
}

@ -145,6 +145,7 @@ public:
const float GetDamageReductionFromBuffs()const;
const float GetCollisionDamage()const;
const bool IsNPC()const;
const bool HasArrowIndicator()const;
private:
std::string name;
vf2d pos;

@ -199,6 +199,8 @@ void MonsterData::InitializeMonsterData(){
DATA["Monsters"][MonsterName]["CollisionDmg"].GetInt()
);
if(DATA["Monsters"][MonsterName].HasProperty("ShowBossIndicator"))monster.hasArrowIndicator=DATA["Monsters"][MonsterName]["ShowBossIndicator"].GetBool();
monster.hurtSound=hurtSound;
monster.deathSound=deathSound;
monster.walkSound=walkSound;
@ -409,4 +411,7 @@ const EventName&MonsterData::GetDeathSound(){
}
const EventName&MonsterData::GetWalkSound(){
return walkSound;
}
const bool MonsterData::HasArrowIndicator()const{
return hasArrowIndicator;
}

@ -69,6 +69,7 @@ private:
EventName walkSound="";
std::vector<MonsterDropData> dropData;
bool isNPC=false;
bool hasArrowIndicator{false};
public:
MonsterData();
MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd=1.0f,float size=1.0f,std::string strategy="Run Towards",int collisionDmg=0);
@ -95,4 +96,5 @@ public:
static void InitializeMonsterData();
static void InitializeNPCData();
static std::map<std::string,Renderable*>imgs;
const bool HasArrowIndicator()const;
};

@ -306,7 +306,10 @@ State::State Player::GetState(){
void Player::Knockback(vf2d vel){
//A new angle will be applied, but will be constrained by whichever applied velocity is strongest (either the current velocity, or the new one). This prevents continuous uncapped velocities to knockbacks applied.
float maxVelThreshold=std::max(vel.mag(),this->vel.mag());
if(vel==vf2d{})return;
float maxVelThreshold;
if(this->vel==vf2d{})maxVelThreshold=vel.mag();
else maxVelThreshold=std::max(vel.mag(),this->vel.mag());
this->vel+=vel;
float newVelAngle=this->vel.polar().y;
this->vel=vf2d{maxVelThreshold,newVelAngle}.cart();
@ -520,16 +523,27 @@ void Player::Update(float fElapsedTime){
}
geom2d::line line(pos,m->GetPos());
float dist = line.length();
if(dist<=0.001){
m->SetPos(m->GetPos()+vf2d{util::random(2)-1,util::random(2)-1});
}else{
m->SetPos(line.rpoint(dist*1.1f));
while(dist<=0.001){
line={pos+vf2d{util::random(0.2f)-0.1f,util::random(0.2f)-0.1f},m->GetPos()};
dist=line.length();
}
m->SetPos(line.rpoint(dist*1.1f));
if(m->IsAlive()&&!m->IsNPC()){ //Don't set the knockback if this monster is actually an NPC. Let's just push them around.
vel+=line.vector().norm()*-128;
float knockbackStrength=1.f;
std::vector<Buff>knockbackBuffs=m->GetBuffs(COLLISION_KNOCKBACK_STRENGTH);
for(Buff&b:knockbackBuffs){
knockbackStrength+=b.intensity;
}
Knockback(line.vector().norm()*-128.f*knockbackStrength);
}
}
}
if(!std::isfinite(vel.x)||!std::isfinite(vel.y)){
ERR(std::format("WARNING! The velocity vector for the player is NOT normal! Current vel:{} . Attempting manual resetting of velocity.",vel.str()));
vel={};
}
if(vel.x>0){
vel.x=std::max(0.f,vel.x-friction*fElapsedTime);
} else {

@ -134,7 +134,7 @@ const void SaveFile::SaveGame(){
saveFile["Overworld Map Location"].SetString(State_OverworldMap::GetCurrentConnectionPoint().name);
saveFile["Chapter"].SetInt(game->GetCurrentChapter());
saveFile["Save Name"].SetString(std::string(GetSaveFileName()));
saveFile["Game Time"].SetReal(game->GetRuntime());
saveFile["Game Time"].SetReal(game->GetRunTime());
saveFile["TravelingMerchant"].SetString(std::string(Merchant::GetCurrentTravelingMerchant().GetKeyName()));
saveFile["Minimap Display Mode"].SetInt(int(game->minimap.GetMinimapMode()));
@ -216,7 +216,7 @@ const void SaveFile::SaveGame(){
utils::datafile::Read(metadata,"save_file_path"_S+"metadata.dat");
}
}
metadata.GetProperty(std::format("save{}",saveFileID)).SetReal(game->GetRuntime(),0U);
metadata.GetProperty(std::format("save{}",saveFileID)).SetReal(game->GetRunTime(),0U);
metadata.GetProperty(std::format("save{}",saveFileID)).SetInt(game->GetCurrentChapter(),1U);
metadata.GetProperty(std::format("save{}",saveFileID)).SetInt(game->GetPlayer()->Level(),2U);
metadata.GetProperty(std::format("save{}",saveFileID)).SetString(game->GetPlayer()->GetClassName(),3U);

@ -84,7 +84,7 @@ void State_Death::OnUserUpdate(AiL*game){
}
Input::StopVibration();
game->SetMosaicEffect(uint8_t(util::lerp(9.f,1.f,(gameSlowdownPct-7)/3.f)));
Input::SetLightbar(PixelLerp(BLACK,DARK_RED,sin(1.5f*game->GetRuntime())/2.f+0.5f));
Input::SetLightbar(PixelLerp(BLACK,DARK_RED,sin(1.5f*game->GetRunTime())/2.f+0.5f));
}
if(gameSlowdownPct<10.f){

@ -139,8 +139,8 @@ void State_LevelComplete::DrawOverlay(AiL*game){
game->DrawRotatedDecal(levelUpTextPos+vf2d{2.f,1.f},GFX["overworld_arrow.png"].Decal(),-PI/2,GFX["overworld_arrow.png"].Sprite()->Size(),{1.f,1.f},BLACK);
game->DrawRotatedDecal(levelUpTextPos+vf2d{2.f,0.f},GFX["overworld_arrow.png"].Decal(),-PI/2,GFX["overworld_arrow.png"].Sprite()->Size(),{1.f,1.f},YELLOW);
game->DrawShadowStringPropDecal(levelUpTextPos+vf2d{-69.f,4.f},std::format("HP +{}",int(game->GetPlayer()->GetHealthGrowthRate())),PixelLerp({226,234,244},WHITE,sin((40*game->GetRuntime())/2.f+0.5f)));
game->DrawShadowStringPropDecal(levelUpTextPos+vf2d{-69.f,12.f},std::format("ATK+{}",int(game->GetPlayer()->GetAtkGrowthRate())),PixelLerp({226,234,244},WHITE,sin((40*game->GetRuntime())/2.f+0.5f)));
game->DrawShadowStringPropDecal(levelUpTextPos+vf2d{-69.f,4.f},std::format("HP +{}",int(game->GetPlayer()->GetHealthGrowthRate())),PixelLerp({226,234,244},WHITE,sin((40*game->GetRunTime())/2.f+0.5f)));
game->DrawShadowStringPropDecal(levelUpTextPos+vf2d{-69.f,12.f},std::format("ATK+{}",int(game->GetPlayer()->GetAtkGrowthRate())),PixelLerp({226,234,244},WHITE,sin((40*game->GetRunTime())/2.f+0.5f)));
}
void State_LevelComplete::TurnOffXPSound(){

@ -163,7 +163,7 @@ void State_OverworldMap::Draw(AiL*game){
if(!Unlock::IsUnlocked(cp)){
game->view.FillRectDecal(cp.rect.pos,cp.rect.size,{0,0,0,128});
}else{
float exclamationScale=fmod(game->GetRuntime(),1.0f)<0.2f?1.f:1.2f;
float exclamationScale=fmod(game->GetRunTime(),1.0f)<0.2f?1.f:1.2f;
if(!cp.Visited()){
game->view.DrawDecal(cp.rect.pos+vf2d{-1.f,0.f},GFX["exclamation.png"].Decal(),{exclamationScale,exclamationScale},BLACK);
game->view.DrawDecal(cp.rect.pos+vf2d{-1.f,-1.f},GFX["exclamation.png"].Decal(),{exclamationScale,exclamationScale});
@ -209,7 +209,7 @@ void State_OverworldMap::Draw(AiL*game){
direction++;
}
float arrowDist=fmod(game->GetRuntime(),1.0f)<0.5f?14:18;
float arrowDist=fmod(game->GetRunTime(),1.0f)<0.5f?14:18;
for(auto&[index,medianAngle]:neighbors){
game->view.DrawRotatedDecal(game->GetPlayer()->GetPos()+vf2d{arrowDist,GetAngle(medianAngle)}.cart()+vf2d{0.f,1.f},GFX["overworld_arrow.png"].Decal(),GetAngle(medianAngle),GFX["overworld_arrow.png"].Sprite()->Size()/2,{1.f,1.f},{0,0,0});

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

@ -86,6 +86,7 @@ Images
GFX_CustomFont = font.png
GFX_Vignette = vignette.png
GFX_Checkmark = checkmark.png
GFX_BossIndicator = bossIndicator.png
# Ability Icons
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png

@ -658,7 +658,7 @@ void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, std::string_view sText
pge->SetDrawTarget(nullptr);
newDecal->Update();
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f;
DrawDecal(pos,pge->garbageCollector[key].decal,scale,col);
}
@ -673,7 +673,7 @@ void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::
pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f;
DrawDecal(pos,pge->garbageCollector[key].decal,scale/4,col);
}
@ -701,7 +701,7 @@ void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, std::string_view s
pge->SetDrawTarget(nullptr);
newDecal->Update();
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f;
DrawDecal(pos,pge->garbageCollector[key].decal,scale,col);
}
@ -747,8 +747,8 @@ void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, std::string_view
pge->SetDrawTarget(nullptr);
newShadowDecal->Update();
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
pge->garbageCollector[key+"_SHADOW"].expireTime=pge->GetRuntime()+120.0f;
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);
}
@ -795,8 +795,8 @@ void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, std::string_
pge->SetDrawTarget(nullptr);
newShadowDecal->Update();
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
pge->garbageCollector[key+"_SHADOW"].expireTime=pge->GetRuntime()+120.0f;
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);
}
@ -812,9 +812,9 @@ void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const
pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
pge->garbageCollector[key].expireTime=pge->GetRunTime()+120.0f;
std::erase_if(pge->garbageCollector,[&](auto&key){
if(key.second.expireTime<pge->GetRuntime()){
if(key.second.expireTime<pge->GetRunTime()){
delete key.second.decal;
return true;
}
@ -841,7 +841,7 @@ void olc::ViewPort::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, c
pge->garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
pge->garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
}
pge->garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
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);

@ -1066,7 +1066,7 @@ namespace olc
// Specify which Sprite should be the target of drawing functions, use nullptr
// to specify the primary screen
void SetDrawTarget(Sprite* target);
double GetRuntime() const;
double GetRunTime() const;
void SetRuntime(const double runTime);
// Gets the current Frames Per Second
uint32_t GetFPS() const;
@ -2257,7 +2257,7 @@ namespace olc
return 0;
}
double PixelGameEngine::GetRuntime() const
double PixelGameEngine::GetRunTime() const
{ return dRunTime; }
void PixelGameEngine::SetRuntime(const double runTime){
@ -2271,7 +2271,7 @@ namespace olc
}
void PixelGameEngine::ClearTimedOutGarbage(){
std::erase_if(garbageCollector,[&](auto&key){
if(key.second.expireTime<GetRuntime()){
if(key.second.expireTime<GetRunTime()){
delete key.second.decal;
return true;
}
@ -3600,7 +3600,7 @@ namespace olc
SetDrawTarget(nullptr);
newDecal->Update();
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
garbageCollector[key].expireTime=GetRunTime()+120.0f;
DrawDecal(pos,garbageCollector[key].decal,scale,col);
}
@ -3629,7 +3629,7 @@ namespace olc
SetDrawTarget(nullptr);
newDecal->Update();
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
garbageCollector[key].expireTime=GetRunTime()+120.0f;
DrawDecal(pos,garbageCollector[key].decal,scale,col);
}
@ -3675,8 +3675,8 @@ namespace olc
SetDrawTarget(nullptr);
newShadowDecal->Update();
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
garbageCollector[key+"_SHADOW"].expireTime=GetRuntime()+120.0f;
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);
}
@ -3692,7 +3692,7 @@ namespace olc
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
garbageCollector[key].expireTime=GetRunTime()+120.0f;
DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
}
@ -3707,7 +3707,7 @@ namespace olc
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
garbageCollector[key].expireTime=GetRunTime()+120.0f;
for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
if(x!=0||y!=0){
@ -3729,7 +3729,7 @@ namespace olc
garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
garbageCollector[key].originalStr=std::string(sText.begin(),sText.end());
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
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);
@ -3778,8 +3778,8 @@ namespace olc
SetDrawTarget(nullptr);
newShadowDecal->Update();
}
garbageCollector[key].expireTime=GetRuntime()+120.0f;
garbageCollector[key+"_SHADOW"].expireTime=GetRuntime()+120.0f;
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);
}

Loading…
Cancel
Save