# pragma region License
/*
License ( OLC - 3 )
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Copyright 2024 Joshua Sigona < sigonasr2 @ gmail . com >
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 © 2024 The FreeType
Project ( www . freetype . org ) . Please see LICENSE_FT . txt for more information .
All rights reserved .
*/
# pragma endregion
# pragma once
# include "Animation.h"
# include "IBullet.h"
# include <unordered_set>
# include <variant>
# include "Oscillator.h"
class Monster ;
class Player ;
using HitList = std : : unordered_set < std : : variant < Monster * , Player * > > ;
enum class EffectType {
NONE ,
SPELL_CIRCLE ,
MONSTER_SOUL ,
BLINK_PORTAL ,
TRAIL_OF_FIRE ,
} ;
struct Effect {
friend class AiL ;
friend struct FallingStone ;
vf2d pos = { 0 , 0 } ;
float lifetime = 0 ;
float fadeout = 0 ;
float fadein { 0.f } ;
vf2d size = { 1 , 1 } ;
Pixel col = WHITE ;
vf2d spd = { } ;
float rotation = 0 ;
float rotationSpd = 0 ;
vf2d scaleSpd { } ;
bool additiveBlending = false ;
float z { } ;
private :
bool dead = false ;
public :
Effect ( vf2d pos , float lifetime , const 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 ) ;
Effect ( vf2d pos , float lifetime , const 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 ) ;
Effect ( vf2d pos , float lifetime , const std : : string & imgFile , bool upperLevel , float fadein , float fadeout , vf2d size , vf2d spd , Pixel col = WHITE , float rotation = 0 , float rotationSpd = 0 , bool additiveBlending = false ) ;
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 ;
void _Draw ( ) const ;
virtual void Draw ( const Pixel blendCol ) const ;
bool OnUpperLevel ( ) ;
const EffectType GetType ( ) const ;
const float GetZ ( ) const ;
const bool & OnUpperLevel ( ) const ;
void SetType ( const EffectType type ) ;
protected :
float original_fadeOutTime ;
float original_fadeInTime { } ;
EffectType type { EffectType : : NONE } ;
private :
Animate2D : : Animation < std : : string > animation ;
Animate2D : : AnimationState internal_animState ;
bool upperLevel = false ;
double aliveTime { } ;
} ;
struct Meteor : Effect {
Meteor ( 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 ) ;
float startLifetime = 0 ;
bool shakeField = false ;
bool Update ( float fElapsedTime ) override ;
void Draw ( const Pixel blendCol ) const override ;
} ;
struct PulsatingFire : Effect {
PulsatingFire ( 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 ) ;
std : : vector < float > pulsatingFireValues ;
float lastParticleTimer = 0 ;
float lastDamageTimer = 0 ;
bool Update ( float fElapsedTime ) override ;
void Draw ( const Pixel blendCol ) const override ;
} ;
struct SwordSlash : Effect {
SwordSlash ( float lifetime , std : : string imgFile , float damageMult , float swordSweepAngle , vf2d size = { 1 , 1 } , float fadeout = 0.0f , vf2d spd = { } , Pixel col = WHITE , float rotation = 0 , float rotationSpd = 0 , bool additiveBlending = false ) ;
bool Update ( float fElapsedTime ) override ;
private :
HitList hitList ;
const float damageMult ;
const float swordSweepAngle ;
} ;
//This draws effects using screen coordinates instead of world coordinates, useful for applying effects directly on the screen.
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 Pixel blendCol ) const override final ;
} ;
struct SpellCircle : Effect {
SpellCircle ( vf2d pos , float lifetime , std : : string imgFile , std : : string spellInsigniaFile , bool upperLevel , float size = 1.0f , float fadeout = 0.0f , vf2d spd = { } , Pixel col = WHITE , float rotation = 0 , float rotationSpd = 0 , bool additiveBlending = false , float insigniaSize = 1.0f , float insigniaFadeout = 0.0f , vf2d insigniaSpd = { } , Pixel insigniaCol = WHITE , float insigniaRotation = 0 , float insigniaRotationSpd = 0 , bool insigniaAdditiveBlending = false ) ;
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 Pixel blendCol ) const override final ;
} ;
struct RockLaunch : Effect {
//The lifetime is for how long the effect lasts after it's launched. You don't have to calculate extra lifetime to compensate for the delayTime, it is done for you.
RockLaunch ( vf2d pos , float lifetime , std : : string imgFile , float delayTime , float size , float fadeout , vf2d spd , Pixel col , float rotation , float rotationSpd , bool additiveBlending = false ) ;
virtual bool Update ( float fElapsedTime ) override final ;
private :
float delayTime ;
vf2d futureSpd ;
} ;
struct ShineEffect : Effect {
//An effect that starts invisible, becomes visible, then fades out again.
ShineEffect ( vf2d pos , float fadeinTime , float fadeoutTime , std : : string imgFile , float size , vf2d spd , Pixel col , float rotation , float rotationSpd , bool additiveBlending = false ) ;
virtual bool Update ( float fElapsedTime ) override final ;
private :
float fadeinTime ;
const Pixel originalCol ;
} ;
//Spawns and moves towards the player after some amount of time.
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 Pixel blendCol ) const override final ;
public :
enum Phase {
RISING ,
TRACKING_PLAYER ,
DEAD ,
} ;
uint8_t alpha { 0U } ;
Phase phase { RISING } ;
float moveSpd { 24.f } ;
float fadeoutTime ;
} ;
struct FadeInOutEffect : Effect {
//cycleSpd is how long it takes to get from fully opaque to fully transparent, and back to fully opaque
FadeInOutEffect ( vf2d pos , const std : : string & img , float lifetime , float cycleSpd , bool onUpperLevel , float size , vf2d spd , Pixel col , float rotation , float rotationSpd , bool additiveBlending = false , float particleSpawnFreq = 0.f , const std : : function < Effect ( const Effect & self ) > & particleGenerator = { } ) ;
//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 Pixel blendCol ) const override ;
std : : function < Effect ( const Effect & self ) > particleGenerator ;
const float particleSpawnFreq ;
Oscillator < vf2d > posOscillator ;
Oscillator < vf2d > sizeOscillator ;
Oscillator < Pixel > colOscillator ;
float particleSpawnTimer { } ;
const float originalParticleSpawnTimer { } ;
} ;
struct PoisonPool : FadeInOutEffect {
PoisonPool ( vf2d pos , const std : : string & img , float radius , int damage , float damageFreq , const HurtType friendly , float lifetime , float cycleSpd , bool onUpperLevel , float size , vf2d spd , 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 final ;
const int damage ;
float damageTimer { } ;
const float originalDamageTimer { } ;
const float radius ;
HurtType friendly ;
const size_t poisonPoolSFXID { } ;
} ;