Fixed oscillating buff colors for buffs that have infinite duration. Added hasten buff oscillating color visual. Mana and health icons have proper integer snapping. Release Build 12313.
All checks were successful
Emscripten Build / Build_and_Deploy_Web_Build (push) Successful in 6m43s

This commit is contained in:
sigonasr2 2026-01-21 16:04:13 -06:00
parent e181172f1a
commit b715dd994d
9 changed files with 24 additions and 18 deletions

View File

@ -74,6 +74,7 @@ namespace BuffTests
Menu::InitializeMenus();
Tutorial::Initialize();
Stats::InitializeDamageReductionTable();
Monster::InitializeStrategies();
GameState::Initialize();
GameState::STATE=GameState::states.at(States::State::GAME_RUN);

View File

@ -81,6 +81,7 @@ namespace EnchantTests
Menu::InitializeMenus();
Tutorial::Initialize();
Stats::InitializeDamageReductionTable();
Monster::InitializeStrategies();
GameState::Initialize();
GameState::STATE=GameState::states.at(States::State::GAME_RUN);

View File

@ -444,6 +444,12 @@ bool AiL::OnConsoleCommand(const std::string& sCommand){
std::weak_ptr<Item>accessory{Inventory::AddItem(args[1])};
if(args.size()>=3)accessory.lock()->_EnchantItem(ItemEnchant{args[2]});
ConsoleOut()<<"Added "<<args[1]<<" to player's inventory."<<std::endl;
}else
if(args[0]=="/mana"){
if(args.size()>=2){
GetPlayer()->mana=std::stoi(args[1]);
ConsoleOut()<<"Set Player's mana to "<<GetPlayer()->mana<<std::endl;
}else ConsoleOut()<<"Usage: /mana <val>"<<std::endl;
}else{
ConsoleOut()<<"Invalid command! Use /help to see available commands."<<std::endl;
}
@ -1072,14 +1078,16 @@ void AiL::RenderWorld(float fElapsedTime){
const std::vector<Buff>damageReductionBuffs{player->GetBuffs(BuffType::DAMAGE_REDUCTION)};
const std::vector<Buff>inkSlowdownDebuff{player->GetBuffs(BuffType::INK_SLOWDOWN)};
const std::vector<Buff>curseDebuff{player->GetBuffs(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_DOT)};
const std::vector<Buff>hastenBuff{player->GetBuffs(BuffType::HASTEN)};
const bool displayCoinSymbol{player->GetBuffs(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_COIN).size()>0};
Pixel playerCol{WHITE};
if(attackBuffs.size()>0)playerCol={255,uint8_t(255*abs(sin(1.4f*attackBuffs[0].duration))),uint8_t(255*abs(sin(1.4f*attackBuffs[0].duration)))};
else if(adrenalineRushBuffs.size()>0)playerCol={uint8_t(255*abs(sin(6.f*adrenalineRushBuffs[0].duration))),255,uint8_t(255*abs(sin(6.f*adrenalineRushBuffs[0].duration)))};
else if(movespeedBuffs.size()>0)playerCol={uint8_t(255*abs(sin(2.f*movespeedBuffs[0].duration))),255,uint8_t(255*abs(sin(2.f*movespeedBuffs[0].duration)))};
else if(inkSlowdownDebuff.size()>0)playerCol={uint8_t(255*abs(sin(2.f*inkSlowdownDebuff[0].duration))),uint8_t(255*abs(sin(2.f*inkSlowdownDebuff[0].duration))),uint8_t(255*abs(sin(2.f*inkSlowdownDebuff[0].duration)))};
if(attackBuffs.size()>0)playerCol={255,uint8_t(255*abs(sin(1.4f*attackBuffs[0].lifetime))),uint8_t(255*abs(sin(1.4f*attackBuffs[0].lifetime)))};
else if(adrenalineRushBuffs.size()>0)playerCol={uint8_t(255*abs(sin(6.f*adrenalineRushBuffs[0].lifetime))),255,uint8_t(255*abs(sin(6.f*adrenalineRushBuffs[0].lifetime)))};
else if(movespeedBuffs.size()>0)playerCol={uint8_t(255*abs(sin(2.f*movespeedBuffs[0].lifetime))),255,uint8_t(255*abs(sin(2.f*movespeedBuffs[0].lifetime)))};
else if(inkSlowdownDebuff.size()>0)playerCol={uint8_t(255*abs(sin(2.f*inkSlowdownDebuff[0].lifetime))),uint8_t(255*abs(sin(2.f*inkSlowdownDebuff[0].lifetime))),uint8_t(255*abs(sin(2.f*inkSlowdownDebuff[0].lifetime)))};
else if(curseDebuff.size()>0)playerCol={uint8_t(128*abs(sin(2.f*GetRunTime()))+127),uint8_t(128*abs(sin(2.f*GetRunTime()))),uint8_t(128*abs(sin(2.f*GetRunTime()))+127)};
else if(hastenBuff.size()>0)playerCol={uint8_t(abs(sin(0.4f*GetRunTime()))+127),uint8_t(0),uint8_t(0)};
if(player->HasIframes())playerCol.a*=0.62f;
@ -1998,11 +2006,11 @@ void AiL::RenderHud(){
DrawDecal({2,2},GFX["heart_outline.png"].Decal(),{1.f,1.f},healthOutlineCol);
const Decal*heartImg{GFX["heart.png"].Decal()};
if(player->GetShield()>0)heartImg=GFX["shield_heart.png"].Decal();
float healthRatio{float(healthCounter.GetDisplayValue())/player->GetMaxHealth()};
float manaRatio{float(manaCounter.GetDisplayValue())/player->GetMaxMana()};
DrawPartialDecal(vf2d{2.f,floor(2+(15*(1-healthRatio)))},const_cast<Decal*>(heartImg),vf2d{0.f,floor(15*(1-healthRatio))},vf2d{17.f,floor(15*healthRatio)});
int healthRatio{int((float(healthCounter.GetDisplayValue())/player->GetMaxHealth())*100)};
int manaRatio{int((float(manaCounter.GetDisplayValue())/player->GetMaxMana())*100)};
DrawPartialDecal(vf2d{2.f,2+(15*(100-healthRatio))/100.f},const_cast<Decal*>(heartImg),vf2d{0.f,15*(100-healthRatio)/100.f},vf2d{17.f,15*healthRatio/100.f});
DrawDecal({2,20},GFX["mana_outline.png"].Decal());
DrawPartialDecal(vf2d{2,float(20+(15*(1-manaRatio)))},GFX["mana.png"].Decal(),vf2d{0.f,float(15*(1-manaRatio))},vf2d{17,float(15*manaRatio)});
DrawPartialDecal(vf2d{2,20+(15*(100-manaRatio))/100.f},GFX["mana.png"].Decal(),vf2d{0.f,15*(100-manaRatio)/100.f},vf2d{17,15*manaRatio/100.f});
std::string text=player->GetHealth()>0?std::to_string(healthCounter.GetDisplayValue()+shieldCounter.GetDisplayValue()):"X";
std::string text_mana=std::to_string(manaCounter.GetDisplayValue());

View File

@ -7,4 +7,5 @@ Items with spaces must be surrounded in quotation marks "".
Valid Commands are:
/help - Shows this help file.
/give <Item Name> [Amount] - Gives an item of type <Item Name> into the player's inventory. Optionally adds [Amount] amount of items to the player's inventory.
/accessory <Accessory Name> [Enchant Name] - Gives an accessory of type <Accessory Name> into the player's inventory. Optionally adds an enchant of type [Enchant Name].
/accessory <Accessory Name> [Enchant Name] - Gives an accessory of type <Accessory Name> into the player's inventory. Optionally adds an enchant of type [Enchant Name].
/mana <val> - Sets player's mana to val.

View File

@ -497,13 +497,14 @@ void Monster::Draw()const{
const auto HasBuff=[&](const BuffType buff){return GetBuffs(buff).size()>0;};
//The lerpCutAmount is how much to divide the initial color by, which is used as the lerp oscillation amount. 0.5 means half the color is always active, and the other half linearly oscillates. 0.1 would mean 90% of the color is normal and 10% of the color oscillates.
const auto GetBuffBlendCol=[&](const BuffType buff,const float oscillationTime_s,const Pixel blendCol,const float lerpCutAmount=0.5f){return Pixel{uint8_t(blendCol.r*(1-lerpCutAmount)+blendCol.r*lerpCutAmount*abs(sin(oscillationTime_s*PI*GetBuffs(buff)[0].duration))),uint8_t(blendCol.g*(1-lerpCutAmount)+blendCol.g*lerpCutAmount*abs(sin(oscillationTime_s*PI*GetBuffs(buff)[0].duration))),uint8_t(blendCol.b*(1-lerpCutAmount)+blendCol.b*lerpCutAmount*abs(sin(oscillationTime_s*PI*GetBuffs(buff)[0].duration)))};};
const auto GetBuffBlendCol=[&](const BuffType buff,const float oscillationTime_s,const Pixel blendCol,const float lerpCutAmount=0.5f){return Pixel{uint8_t(blendCol.r*(1-lerpCutAmount)+blendCol.r*lerpCutAmount*abs(sin(oscillationTime_s*PI*GetBuffs(buff)[0].lifetime))),uint8_t(blendCol.g*(1-lerpCutAmount)+blendCol.g*lerpCutAmount*abs(sin(oscillationTime_s*PI*GetBuffs(buff)[0].lifetime))),uint8_t(blendCol.b*(1-lerpCutAmount)+blendCol.b*lerpCutAmount*abs(sin(oscillationTime_s*PI*GetBuffs(buff)[0].lifetime)))};};
if(HasBuff(BuffType::BURNING_ARROW_BURN))blendCol=GetBuffBlendCol(BuffType::BURNING_ARROW_BURN,1.f,{255,160,0});
else if(HasBuff(BuffType::DAMAGE_AMPLIFICATION))blendCol=GetBuffBlendCol(BuffType::DAMAGE_AMPLIFICATION,1.4f,{255,0,0});
else if(HasBuff(BuffType::CURSE_OF_DEATH))blendCol=GetBuffBlendCol(BuffType::CURSE_OF_DEATH,1.4f,{255,0,0});
else if(HasBuff(BuffType::COLOR_MOD))blendCol=GetBuffBlendCol(BuffType::COLOR_MOD,1.4f,PixelRaw(GetBuffs(BuffType::COLOR_MOD)[0].intensity),1.f);
else if(HasBuff(BuffType::SLOWDOWN))blendCol=GetBuffBlendCol(BuffType::SLOWDOWN,1.4f,{255,255,128},0.5f);
else if(HasBuff(BuffType::HASTEN))blendCol=GetBuffBlendCol(BuffType::HASTEN,0.4f,{128,0,0},1.f);
else if(glowPurpleBuff.has_value())blendCol=Pixel{uint8_t(255*abs(sin(1.4*glowPurpleBuff.value().duration))),uint8_t(255*abs(sin(1.4*glowPurpleBuff.value().duration))),uint8_t(128+127*abs(sin(1.4*glowPurpleBuff.value().duration)))};
const vf2d hitTimerOffset=vf2d{sin(20*PI*lastHitTimer+randomFrameOffset),0.f}*2.f*GetSizeMult();

View File

@ -716,10 +716,7 @@ class TMXParser{
int&neighborElement=newConnection.neighbors[direction];
if(neighborElement!=-1)ERR(std::format("WARNING! Connection Point in direction {} is already occupied by node {}!",direction,neighborElement));
const int val{key2.second.GetInteger()};
if(val==0){
LOG(std::format("WARNING! {} is supposedly connected to {}, this is very likely a mistake!!!",newConnection.name,State_OverworldMap::connections[val].name));
continue; //Prevents accidental connections to index 0 (Which shouldn't be happening)!
}
if(val==0)continue; //A value of "0" indicates it is unset in Tiled.
newConnection.neighbors[direction]=val;
}
}

View File

@ -13,9 +13,6 @@ You get placed in an arena that changes every 5 waves visually and spawns random
Instead of the area buffs i switched to giving highest exp and locking extra lore behind first time wave completions.
Red flashing entity with hasten buff
"0" is always invalid?
Mana icon pixel snapping
DEMO
====

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 12298
#define VERSION_BUILD 12313
#define stringify(a) stringify_(a)
#define stringify_(a) #a