Implemented Trail of Fire enchant, added Trail of Fire effect. Fix effects not having their type set with the new Effect constructor arrangement. Adjusted Trail of Fire damage potency from 10% to 30% per tick. Release Build 11309.

pull/65/head
sigonasr2 3 months ago
parent 901f2e38bc
commit 6fbb8a8ed1
  1. 13
      Adventures in Lestoria Tests/EnchantTests.cpp
  2. 12
      Adventures in Lestoria/AdventuresInLestoria.cpp
  3. 17
      Adventures in Lestoria/Effect.cpp
  4. 16
      Adventures in Lestoria/Effect.h
  5. 4
      Adventures in Lestoria/FadeInOutEffect.cpp
  6. 2
      Adventures in Lestoria/FallingStone.cpp
  7. 7
      Adventures in Lestoria/FireBolt.cpp
  8. 10
      Adventures in Lestoria/ForegroundEffect.cpp
  9. 2
      Adventures in Lestoria/Meteor.cpp
  10. 4
      Adventures in Lestoria/MonsterSoul.cpp
  11. 8
      Adventures in Lestoria/Oscillator.h
  12. 2
      Adventures in Lestoria/PulsatingFire.cpp
  13. 8
      Adventures in Lestoria/SoundEffect.cpp
  14. 6
      Adventures in Lestoria/SoundEffect.h
  15. 6
      Adventures in Lestoria/SpellCircle.cpp
  16. 59
      Adventures in Lestoria/TrailEffect.h
  17. 2
      Adventures in Lestoria/Version.h
  18. BIN
      Adventures in Lestoria/assets/FlamesTexture.png
  19. 5
      Adventures in Lestoria/assets/config/audio/events.txt
  20. 5
      Adventures in Lestoria/assets/config/items/ItemEnchants.txt
  21. BIN
      Adventures in Lestoria/assets/gamepack.pak
  22. BIN
      Adventures in Lestoria/assets/sounds/burn.ogg
  23. BIN
      x64/Release/Adventures in Lestoria.exe

@ -1225,5 +1225,18 @@ namespace EnchantTests
Game::Update(0.f);
Assert::AreEqual(size_t(1),game->GetBackgroundEffects().size(),L"There should be a background effect (i.e. the Black Hole).");
}
TEST_METHOD(FireBoltNoEnchantCheck){
Game::ChangeClass(player,WIZARD);
player->CheckAndPerformAbility(player->GetAbility1(),testKeyboardInput);
Game::Update(0.5f);
Assert::AreEqual(size_t(0),game->GetEffect(EffectType::TRAIL_OF_FIRE).size(),L"Trail of Fire should not be generated.");
}
TEST_METHOD(FireBoltEnchantCheck){
Game::ChangeClass(player,WIZARD);
Game::GiveAndEquipEnchantedRing("Trail of Fire");
player->CheckAndPerformAbility(player->GetAbility1(),testKeyboardInput);
Game::Update(0.5f);
Assert::AreEqual(size_t(1),game->GetEffect(EffectType::TRAIL_OF_FIRE).size(),L"Trail of Fire should be generated with the enchant.");
}
};
}

@ -1425,7 +1425,7 @@ void AiL::RenderWorld(float fElapsedTime){
auto it=backgroundEffectsLower.begin();
while(it!=backgroundEffectsLower.end()){
const Effect&e=**it;
e.Draw();
e._Draw();
++it;
}
}
@ -1566,7 +1566,7 @@ void AiL::RenderWorld(float fElapsedTime){
++monstersBeforeLowerIt;
}
for(const Effect*const e:backgroundEffectsLower){
e->Draw();
e->_Draw();
}
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const int dropInd=*dropsBeforeLowerIt;
@ -1595,7 +1595,7 @@ void AiL::RenderWorld(float fElapsedTime){
b->_Draw();
}
for(const Effect*const e:foregroundEffectsLower){
e->Draw();
e->_Draw();
}
#pragma endregion
#pragma region Permanent Foreground Rendering
@ -1718,7 +1718,7 @@ void AiL::RenderWorld(float fElapsedTime){
auto it=backgroundEffectsUpper.begin();
while(it!=backgroundEffectsUpper.end()){
const Effect&e=**it;
e.Draw();
e._Draw();
++it;
}
}
@ -1867,7 +1867,7 @@ void AiL::RenderWorld(float fElapsedTime){
++monstersBeforeUpperIt;
}
for(const Effect*const e:backgroundEffectsUpper){
e->Draw();
e->_Draw();
}
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const int dropInd=*dropsBeforeUpperIt;
@ -1896,7 +1896,7 @@ void AiL::RenderWorld(float fElapsedTime){
b->_Draw();
}
for(const Effect*const e:foregroundEffectsUpper){
e->Draw();
e->_Draw();
}
#pragma endregion
#pragma region Permanent Upper Foreground Rendering

@ -54,7 +54,7 @@ Effect::Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel
:Effect(pos,lifetime,imgFile,upperLevel,fadein,fadeout,size,spd,EffectType::NONE,col,rotation,rotationSpd,additiveBlending){}
Effect::Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,EffectType type,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadein(fadein),original_fadeInTime(fadein),fadeout(fadeout),original_fadeOutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadein(fadein),original_fadeInTime(fadein),fadeout(fadeout),original_fadeOutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending),type(type){
this->animation.AddState(imgFile,ANIMATION_DATA.at(imgFile));
this->animation.ChangeState(internal_animState,imgFile);
}
@ -80,7 +80,7 @@ bool Effect::Update(float fElapsedTime){
return true;
}
void Effect::Draw()const{
void Effect::_Draw()const{
if(additiveBlending)game->SetDecalMode(DecalMode::ADDITIVE);
const bool FadeInFinished{original_fadeInTime==0||fadein==original_fadeInTime};
const bool HasFadeout{fadeout>0};
@ -90,17 +90,22 @@ void Effect::Draw()const{
game->view.DrawDecal(pos-vf2d{3,3}*shadowScale/2+vf2d{0,12*size.y},GFX["circle.png"].Decal(),shadowScale,BLACK);
}
Pixel blendCol{col};
[[unlikely]]if(!FadeInFinished){
game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadein/original_fadeInTime*col.a)});
blendCol={col.r,col.g,col.b,uint8_t(fadein/original_fadeInTime*col.a)};
}else
[[likely]]if(HasFadeout){
game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeOutTime*col.a)});
}else{
game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,col);
blendCol={col.r,col.g,col.b,uint8_t(fadeout/original_fadeOutTime*col.a)};
}
Draw(blendCol);
game->SetDecalMode(DecalMode::NORMAL);
}
void Effect::Draw(const Pixel blendCol)const{
game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,blendCol);
}
Animate2D::Frame Effect::GetFrame()const{
return animation.GetFrame(internal_animState);
}

@ -50,6 +50,7 @@ enum class EffectType{
SPELL_CIRCLE,
MONSTER_SOUL,
BLINK_PORTAL,
TRAIL_OF_FIRE,
};
struct Effect{
@ -76,7 +77,8 @@ public:
Effect(vf2d pos,float lifetime,const std::string&imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,EffectType type,Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
virtual bool Update(float fElapsedTime);
Animate2D::Frame GetFrame()const;
virtual void Draw()const;
void _Draw()const;
virtual void Draw(const Pixel blendCol)const;
bool OnUpperLevel();
const EffectType GetType()const;
const float GetZ()const;
@ -98,7 +100,7 @@ struct Meteor:Effect{
float startLifetime=0;
bool shakeField=false;
bool Update(float fElapsedTime)override;
void Draw()const override;
void Draw(const Pixel blendCol)const override;
};
struct PulsatingFire:Effect{
@ -107,7 +109,7 @@ struct PulsatingFire:Effect{
float lastParticleTimer=0;
float lastDamageTimer=0;
bool Update(float fElapsedTime)override;
void Draw()const override;
void Draw(const Pixel blendCol)const override;
};
struct SwordSlash:Effect{
@ -123,7 +125,7 @@ private:
struct ForegroundEffect:Effect{
ForegroundEffect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
ForegroundEffect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
virtual void Draw()const override final;
virtual void Draw(const Pixel blendCol)const override final;
};
struct SpellCircle:Effect{
@ -131,7 +133,7 @@ struct SpellCircle:Effect{
SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string spellInsigniaFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false,vf2d insigniaSize={1,1},float insigniaFadeout=0.0f,vf2d insigniaSpd={},Pixel insigniaCol=WHITE,float insigniaRotation=0,float insigniaRotationSpd=0,bool insigniaAdditiveBlending=false);
Effect spellInsignia{vf2d{},0.f,"spell_insignia.png",false,{}};
virtual bool Update(float fElapsedTime)override final;
virtual void Draw()const override final;
virtual void Draw(const Pixel blendCol)const override final;
};
struct RockLaunch:Effect{
@ -156,7 +158,7 @@ private:
struct MonsterSoul:Effect{
MonsterSoul(vf2d pos,float fadeoutTime,float size,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending=false);
virtual bool Update(float fElapsedTime)override final;
virtual void Draw()const override final;
virtual void Draw(const Pixel blendCol)const override final;
public:
enum Phase{
RISING,
@ -175,7 +177,7 @@ struct FadeInOutEffect:Effect{
//A version with oscillators for position and colors, for extra animation effects!
FadeInOutEffect(Oscillator<vf2d>pos,const std::string&img,float lifetime,bool onUpperLevel,Oscillator<vf2d>size,vf2d spd,Oscillator<Pixel>col,float rotation,float rotationSpd,bool additiveBlending=false,float particleSpawnFreq=0.f,const std::function<Effect(const Effect&self)>&particleGenerator={});
virtual bool Update(float fElapsedTime)override;
virtual void Draw()const override;
virtual void Draw(const Pixel blendCol)const override;
std::function<Effect(const Effect&self)>particleGenerator;
const float particleSpawnFreq;
Oscillator<vf2d>posOscillator;

@ -60,6 +60,6 @@ bool FadeInOutEffect::Update(float fElapsedTime){
col=colOscillator.Update(fElapsedTime);
return Effect::Update(fElapsedTime);
}
void FadeInOutEffect::Draw()const{
Effect::Draw();
void FadeInOutEffect::Draw(const Pixel blendCol)const{
Effect::Draw(blendCol);
}

@ -84,7 +84,7 @@ void FallingStone::Update(float fElapsedTime){
}
void FallingStone::Draw(const Pixel blendCol)const{
if(lifetime<=indicatorDisplayTime){
indicator.Draw();
indicator._Draw();
}
Bullet::Draw(blendCol);
}

@ -41,13 +41,16 @@ All rights reserved.
#include "DEFINES.h"
#include "util.h"
#include "SoundEffect.h"
#include "TrailEffect.h"
INCLUDE_game
INCLUDE_MONSTER_LIST
FireBolt::FireBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:Bullet(pos,vel,radius,damage,
"energy_bolt.png",upperLevel,false,INFINITE,true,friendly,col){}
"energy_bolt.png",upperLevel,false,INFINITE,true,friendly,col){
if(game->GetPlayer()->HasEnchant("Trail of Fire"))flameTrail=dynamic_cast<TrailEffect&>(game->AddEffect(std::make_unique<TrailEffect>(pos,"Trail of Fire"_ENC["TRAIL DURATION"],"FlamesTexture.png","Trail of Fire"_ENC["TRAIL DAMAGE"]/100.f*game->GetPlayer()->GetAttack(),"Trail of Fire"_ENC["TRAIL TICK FREQUENCY"],upperLevel,1.f,vf2d{1.f,2.f},30000.f,Oscillator<Pixel>{{255,0,0,128},Pixel(0xE74F30),2.f},EffectType::TRAIL_OF_FIRE,true),true));
}
void FireBolt::Update(float fElapsedTime){
lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime);
@ -72,6 +75,8 @@ void FireBolt::Update(float fElapsedTime){
SoundEffect::PlaySFX("Wizard Fire Bolt Hit",pos);
}
if(flameTrail)flameTrail.value().get().SetEndPos(pos);
}
BulletDestroyState FireBolt::PlayerHit(Player*player)

@ -47,12 +47,6 @@ ForegroundEffect::ForegroundEffect(vf2d pos,float lifetime,std::string imgFile,b
:Effect(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){}
ForegroundEffect::ForegroundEffect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:Effect(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){}
void ForegroundEffect::Draw()const{
if(additiveBlending)game->SetDecalMode(DecalMode::ADDITIVE);
if(fadeout==0){
game->DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,col);
} else {
game->DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeOutTime*255)});
}
game->SetDecalMode(DecalMode::NORMAL);
void ForegroundEffect::Draw(const Pixel blendCol)const{
game->DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,blendCol);
}

@ -70,7 +70,7 @@ bool Meteor::Update(float fElapsedTime){
return Effect::Update(fElapsedTime);
}
void Meteor::Draw()const{
void Meteor::Draw(const Pixel blendCol)const{
if(lifetime>0){
vf2d scale=vf2d{192,64}/3.f*(startLifetime+1-lifetime)*0.25*size;
vf2d meteorOffset=vf2d{lifetime*"Wizard.Ability 3.MeteorXMovementMult"_I,0}*"Wizard.Ability 3.MeteorShadowStartingDist"_F;

@ -84,9 +84,9 @@ bool MonsterSoul::Update(float fElapsedTime){
}
return updateResult;
}
void MonsterSoul::Draw()const{
void MonsterSoul::Draw(const Pixel blendCol)const{
game->SetDecalMode(DecalMode::ADDITIVE);
game->view.DrawRotatedDecal(pos-vf2d{0,GetZ()},GFX["monstersoulglow.png"].Decal(),0.f,GFX["monstersoulglow.png"].Sprite()->Size()/2,size*util::lerp(0.6f,1.4f,abs(sin(2*PI*lifetime))));
game->SetDecalMode(DecalMode::NORMAL);
Effect::Draw();
Effect::Draw(blendCol);
}

@ -42,16 +42,16 @@ All rights reserved.
template<class T>
class Oscillator{
public:
Oscillator()
inline Oscillator()
:Oscillator({},{},0.f){}
Oscillator(T val1,T val2,float cycleSpd)
inline Oscillator(T val1,T val2,float cycleSpd)
:val1(val1),val2(val2),first(this->val1),second(this->val2),cycleSpd(cycleSpd),currentVal(val1){}
const T&Update(const float fElapsedTime){
inline const T&Update(const float fElapsedTime){
currentVal=util::lerp(val1,val2,sin(PI*timer*cycleSpd)/2+0.5f);
timer+=fElapsedTime;
return get();
}
const T&get(){
inline const T&get()const{
return currentVal;
};
const T&first;

@ -75,7 +75,7 @@ bool PulsatingFire::Update(float fElapsedTime){
return Effect::Update(fElapsedTime);
}
void PulsatingFire::Draw()const{
void PulsatingFire::Draw(const Pixel blendCol)const{
for(int i=0;i<8;i++){
Animate2D::FrameSequence*effectSpr=nullptr;
switch(int(pulsatingFireValues[i]*5)){

@ -86,7 +86,7 @@ void SoundEffect::Initialize(){
}
}
void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){
void SoundEffect::PlaySFX(const std::string&eventName,const vf2d&pos){
if(game->TestingModeEnabled()||eventName.length()==0)return;
const SoundEffect&sfx=GetRandomSFXFromFile(eventName);
@ -112,7 +112,7 @@ void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){
}
}
size_t SoundEffect::PlayLoopingSFX(const std::string_view eventName,const vf2d&pos){
size_t SoundEffect::PlayLoopingSFX(const std::string&eventName,const vf2d&pos){
if(game->TestingModeEnabled()||eventName.length()==0)return 0U;
const SoundEffect&sfx=GetRandomSFXFromFile(eventName);
const size_t id=Audio::Engine().LoadSound(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()));
@ -128,8 +128,8 @@ void SoundEffect::StopLoopingSFX(const int id){
RepeatingSoundEffect::playingSoundEffects.erase(id);
}
SoundEffect&SoundEffect::GetRandomSFXFromFile(const std::string_view eventName){
auto itr=SOUND_EFFECTS.equal_range(std::string(eventName));
SoundEffect&SoundEffect::GetRandomSFXFromFile(const std::string&eventName){
auto itr=SOUND_EFFECTS.equal_range(eventName);
size_t soundCount=std::distance(itr.first,itr.second);
if(soundCount==0)ERR("WARNING! Sound Effect "<<std::quoted(eventName)<<" does not have any sound effects loaded/doesn't exist!")
size_t soundEffectChoice=util::random()%soundCount;

@ -54,14 +54,14 @@ private:
class SoundEffect{
public:
SoundEffect(const std::string_view filename,const float&vol,const float&minPitch=0.9f,const float&maxPitch=1.1f,const bool combatSound=false);
static void PlaySFX(const std::string_view eventName,const vf2d&pos);
static void PlaySFX(const std::string&eventName,const vf2d&pos);
//Sets up a sound to be looped continuously.
static size_t PlayLoopingSFX(const std::string_view eventName,const vf2d&pos);
static size_t PlayLoopingSFX(const std::string&eventName,const vf2d&pos);
static void StopLoopingSFX(const int id);
static void Initialize();
static const vf2d CENTERED;
private:
static SoundEffect&GetRandomSFXFromFile(const std::string_view eventName);
static SoundEffect&GetRandomSFXFromFile(const std::string&eventName);
static std::multimap<EventName,SoundEffect>SOUND_EFFECTS;
std::string filename;
float vol;

@ -45,9 +45,9 @@ SpellCircle::SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string
SpellCircle::SpellCircle(vf2d pos,float lifetime,std::string imgFile,std::string spellInsigniaFile,bool upperLevel,float size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending,float insigniaSize,float insigniaFadeout,vf2d insigniaSpd,Pixel insigniaCol,float insigniaRotation,float insigniaRotationSpd,bool insigniaAdditiveBlending)
:SpellCircle(pos,lifetime,imgFile,spellInsigniaFile,upperLevel,vf2d{size,size},fadeout,spd,col,rotation,rotationSpd,additiveBlending,vf2d{insigniaSize,insigniaSize},insigniaFadeout,insigniaSpd,insigniaCol,insigniaRotation,insigniaRotationSpd,insigniaAdditiveBlending){}
void SpellCircle::Draw()const{
Effect::Draw();
spellInsignia.Draw();
void SpellCircle::Draw(const Pixel blendCol)const{
Effect::Draw(blendCol);
spellInsignia._Draw();
}
bool SpellCircle::Update(float fElapsedTime){

@ -37,21 +37,68 @@ All rights reserved.
#pragma endregion
#pragma once
#include "Effect.h"
#include "AdventuresInLestoria.h"
#include "SoundEffect.h"
class TrailEffect:Effect{
inline TrailEffect(vf2d startPos,float lifetime,const std::string&imgFile,bool upperLevel,float fadeout,vf2d scale,float imgXOffsetSpd,Oscillator<Pixel>col,EffectType type=EffectType::NONE,bool additiveBlending=false)
:Effect(pos,lifetime,imgFile,upperLevel,scale,fadeout,{},col.first,0.f,0.f,additiveBlending){}
INCLUDE_game
INCLUDE_GFX
INCLUDE_MONSTER_LIST
struct TrailEffect:Effect{
inline TrailEffect(vf2d startPos,float lifetime,const std::string&imgFile,int damage,float damageTickFrequency,bool upperLevel,float fadeout,vf2d scale,float imgXOffsetSpd,Oscillator<Pixel>col,EffectType type=EffectType::NONE,bool additiveBlending=false)
:endPos(startPos),imageXSpd(imgXOffsetSpd),damage(damage),col(col),damageTickFrequency(damageTickFrequency),Effect(startPos,lifetime,imgFile,upperLevel,0.f,fadeout,scale,{},type,WHITE,0.f,0.f,additiveBlending){}
inline void SetEndPos(const vf2d pos){
this->endPos=pos;
}
inline bool Update(float fElapsedTime){
col.Update(fElapsedTime);
imageXOffset+=imageXSpd*fElapsedTime;
rotation=util::angleTo(pos,endPos);
hitTimer-=fElapsedTime;
if(hitTimer<=0.f){
for(std::shared_ptr<Monster>&monster:MONSTER_LIST){
vf2d closestPointToFlameTrail{geom2d::closest(geom2d::line<float>{pos,endPos},monster->GetPos())};
float distToTrail{util::distance(monster->GetPos(),closestPointToFlameTrail)};
if(!monster->InUndamageableState(OnUpperLevel(),GetZ())&&distToTrail<=12*size.y){
monster->Hurt(damage,OnUpperLevel(),GetZ(),HurtFlag::DOT);
SoundEffect::PlaySFX("Burn",monster->GetPos());
}
}
hitTimer+=damageTickFrequency;
}
return Effect::Update(fElapsedTime);
}
inline void Draw()const{
inline void Draw(const Pixel blendCol)const{
geom2d::line<float>flameTrailLine{pos,endPos};
geom2d::line<float>flameTrailLineRectLine1{pos+vf2d{GetFrame().GetSourceImage()->Sprite()->height/2.f*size.y,rotation-PI/2}.cart(),endPos+vf2d{GetFrame().GetSourceImage()->Sprite()->height/2.f*size.y,rotation-PI/2}.cart()};
geom2d::line<float>flameTrailLineRectLine2{pos+vf2d{GetFrame().GetSourceImage()->Sprite()->height/2.f*size.y,rotation+PI/2}.cart(),endPos+vf2d{GetFrame().GetSourceImage()->Sprite()->height/2.f*size.y,rotation+PI/2}.cart()};
vf2d flameTrailSize{flameTrailLine.length(),float(GetFrame().GetSourceImage()->Sprite()->height)};
flameTrailSize*=size;
const auto PixelToUVSpace=[this,&flameTrailSize](vf2d pixelPos){
pixelPos.x+=imageXOffset;
return pixelPos/GetFrame().GetSourceImage()->Sprite()->Size()/size;
};
game->view.DrawPolygonDecal(GetFrame().GetSourceImage()->Decal(),std::vector<vf2d>{
flameTrailLine.upoint(0.5f),flameTrailLineRectLine1.start,flameTrailLineRectLine1.upoint(0.5f),flameTrailLineRectLine1.end,
flameTrailLineRectLine2.end,flameTrailLineRectLine2.upoint(0.5f),flameTrailLineRectLine2.start,flameTrailLineRectLine1.start,
},std::vector<vf2d>{
PixelToUVSpace(flameTrailSize/2),PixelToUVSpace({}),PixelToUVSpace({flameTrailSize.x/2.f,0}),PixelToUVSpace({flameTrailSize.x,0.f}),
PixelToUVSpace(flameTrailSize),PixelToUVSpace({flameTrailSize.x/2.f,flameTrailSize.y}),PixelToUVSpace({0.f,flameTrailSize.y}),PixelToUVSpace({}),
},std::vector<Pixel>{
col.get(),{0,0,0,0},col.get(),{0,0,0,0},
{0,0,0,0},col.get(),{0,0,0,0},{0,0,0,0},
},blendCol);
}
private:
Oscillator<Pixel>col;
vf2d endPos{};
float imageXSpd;
float imageXOffset{};
int damage;
float damageTickFrequency;
float hitTimer{};
};

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 5
#define VERSION_BUILD 11271
#define VERSION_BUILD 11309
#define stringify(a) stringify_(a)
#define stringify_(a) #a

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@ -56,6 +56,11 @@ Events
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = bomb_explosion.ogg, 100%
}
Burn
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
File[0] = burn.ogg, 70%
}
Button Click
{
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)

@ -504,11 +504,12 @@ Item Enchants
}
Trail of Fire
{
Description = "The Firebolt leaves behind a trail of fire, burning targets standing in it for {TRAIL DAMAGE}% attack every second for {TRAIL DURATION} seconds."
Description = "Firebolt leaves behind a trail of fire, burning targets standing in it for {TRAIL DAMAGE}% attack every second for {TRAIL DURATION} seconds."
Affects = Ability 1
TRAIL DAMAGE = 10%
TRAIL DAMAGE = 30%
TRAIL DURATION = 10s
TRAIL TICK FREQUENCY = 1s
# Stat, Lowest, Highest Value
# Stat Modifier[0] = ..., 0, 0

Loading…
Cancel
Save