Fiinished implementation of stack-based Effects system. Only remaining issue is edge-case when list is full (missing return path). Release Build 13190
All checks were successful
Emscripten Build / Build_and_Deploy_Web_Build (push) Successful in 8m36s
All checks were successful
Emscripten Build / Build_and_Deploy_Web_Build (push) Successful in 8m36s
This commit is contained in:
parent
1089f00d26
commit
6d15c427a5
@ -231,7 +231,7 @@
|
||||
<AdditionalIncludeDirectories>C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;$(ProjectDir)steam;$(ProjectDir)discord-files;C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\LabUser\Documents\include;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\niconiconii\OneDrive\Documents\include;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\sigon\OneDrive\Documents\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<TreatSpecificWarningsAsErrors>4099;5030;4715;4172;4834</TreatSpecificWarningsAsErrors>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalOptions>/w14099 /w15030 /w14715 /w14172 /w14834 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/w14099 /w15030 /w14715 /w14172 /w14834 /bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -400,10 +400,6 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BlackHole.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BlizzardSnowEmitter.h" />
|
||||
<ClInclude Include="BombBoom.h">
|
||||
<SubType>
|
||||
@ -424,7 +420,6 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FallEffect.h" />
|
||||
<ClInclude Include="FriendlyType.h" />
|
||||
<ClInclude Include="HurtDamageInfo.h">
|
||||
<SubType>
|
||||
@ -489,7 +484,6 @@
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Error.h" />
|
||||
<ClInclude Include="ExpandingRing.h" />
|
||||
<ClInclude Include="FloatingMenuComponent.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -768,10 +762,6 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TrailEffect.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Tutorial.h" />
|
||||
<ClInclude Include="VisualNovel.h" />
|
||||
<ClInclude Include="Test.h" />
|
||||
@ -832,6 +822,7 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BlackHole.cpp" />
|
||||
<ClCompile Include="BlacksmithCraftingWindow.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -872,6 +863,7 @@
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Error.cpp" />
|
||||
<ClCompile Include="ExpandingRing.cpp" />
|
||||
<ClCompile Include="ExplosiveTrap.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -880,6 +872,7 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FallEffect.cpp" />
|
||||
<ClCompile Include="FlipCoinEffect.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -988,7 +981,6 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FallingDebris.h" />
|
||||
<ClCompile Include="Feather.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -1300,6 +1292,7 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TrailEffect.cpp" />
|
||||
<ClCompile Include="Trapper.cpp" />
|
||||
<ClCompile Include="Turret.cpp" />
|
||||
<ClCompile Include="Tutorial.cpp" />
|
||||
|
||||
@ -666,9 +666,6 @@
|
||||
<ClInclude Include="Pixel.h">
|
||||
<Filter>Header Files\Engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ExpandingRing.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TEST_DEFINES.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -693,12 +690,6 @@
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BlackHole.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TrailEffect.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Oscillator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -732,9 +723,6 @@
|
||||
<ClInclude Include="BlizzardSnowEmitter.h">
|
||||
<Filter>Source Files\Emitters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FallEffect.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TileGroupDataFile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -842,9 +830,6 @@
|
||||
<ClCompile Include="SlimeKing.cpp">
|
||||
<Filter>Source Files\Monster Strategies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FallingDebris.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RunAway.cpp">
|
||||
<Filter>Source Files\Monster Strategies</Filter>
|
||||
</ClCompile>
|
||||
@ -1382,6 +1367,18 @@
|
||||
<ClCompile Include="ThunderOrb.cpp">
|
||||
<Filter>Source Files\Bullet Types</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TrailEffect.cpp">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BlackHole.cpp">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FallEffect.cpp">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ExpandingRing.cpp">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
||||
@ -809,22 +809,20 @@ void AiL::UpdateCamera(float fElapsedTime){
|
||||
view.SetWorldOffset(camera.GetViewPosition());
|
||||
}
|
||||
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
|
||||
void AiL::UpdateEffects(float fElapsedTime){
|
||||
std::ranges::for_each(EMITTER_LIST,[&fElapsedTime](const std::unique_ptr<IEmitter>&emitter){
|
||||
emitter->Update(fElapsedTime);
|
||||
});
|
||||
|
||||
const auto RunEffectUpdate=[&](const std::array<EffectData,EFFECT_LIMIT>&arr,size_t&effCount){
|
||||
const auto RunEffectUpdate=[&](std::array<EffectData,EFFECT_LIMIT>&arr,size_t&effCount){
|
||||
size_t effectSlot{};
|
||||
std::ranges::for_each(EffectManager::backgroundEffectList,[&fElapsedTime,&effectSlot](EffectData&effect){
|
||||
std::ranges::for_each(arr,[&fElapsedTime,&effectSlot,&effCount](EffectData&effect){
|
||||
enum class AliveState:bool{ALIVE,DEAD};
|
||||
AliveState previousAliveState{*effect.lifetime<=0.f?AliveState::DEAD:AliveState::ALIVE};
|
||||
std::visit(EffectOverloads{},*effect.effect,std::variant<float>{fElapsedTime});
|
||||
AliveState newAliveState{*effect.lifetime<=0.f?AliveState::DEAD:AliveState::ALIVE};
|
||||
if(previousAliveState==AliveState::ALIVE&&newAliveState==AliveState::DEAD)EffectManager::activeBackgroundEffectCount--;
|
||||
AliveState previousAliveState{!effect.effect?AliveState::DEAD:AliveState::ALIVE};\
|
||||
if(previousAliveState==AliveState::DEAD)return;
|
||||
if(!std::visit(EffectOverloads{},*effect.effect,std::variant<float>{fElapsedTime})){effect.effect.reset();}
|
||||
AliveState newAliveState{!effect.effect?AliveState::DEAD:AliveState::ALIVE};
|
||||
if(previousAliveState==AliveState::ALIVE&&newAliveState==AliveState::DEAD)effCount--;
|
||||
[[unlikely]]if(previousAliveState==AliveState::DEAD&&newAliveState==AliveState::ALIVE)ERR(std::format("WARNING! Effect in slot {} has resurrected! THIS SHOULD NOT BE HAPPENING!",effectSlot));
|
||||
[[unlikely]]if(EffectManager::GetForegroundEffectCount()>=EFFECT_LIMIT||EffectManager::GetBackgroundEffectCount()>=EFFECT_LIMIT)ERR(std::format("WARNING! Effect count limits out-of-bounds! Foreground Count: {}, Background Count: {}, Limit: {} THIS SHOULD NOT BE HAPPENING!",EffectManager::GetForegroundEffectCount(),EffectManager::GetBackgroundEffectCount(),EFFECT_LIMIT));
|
||||
effectSlot++;
|
||||
@ -1064,15 +1062,15 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
auto dropsAfterLower{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y>=pl->GetPos().y&&!drop.OnUpperLevel();})};
|
||||
auto bulletsUpper{BULLET_LIST|std::views::filter([](const std::unique_ptr<IBullet>&bullet){return bullet->OnUpperLevel();})};
|
||||
auto bulletsLower{BULLET_LIST|std::views::filter([](const std::unique_ptr<IBullet>&bullet){return !bullet->OnUpperLevel();})};
|
||||
std::vector<std::reference_wrapper<EffectData>>activeForegroundEffects,activeBackgroundEffects;
|
||||
std::ranges::for_each(EffectManager::foregroundEffectList,[&activeForegroundEffects=activeForegroundEffects](const EffectData&eff){if((*eff.lifetime)>=0)activeForegroundEffects.emplace_back(eff.effect);});
|
||||
std::ranges::for_each(EffectManager::backgroundEffectList,[&activeBackgroundEffects=activeBackgroundEffects](const EffectData&eff){if((*eff.lifetime)>=0)activeBackgroundEffects.emplace_back(eff.effect);});
|
||||
std::ranges::sort(activeForegroundEffects,[](const std::reference_wrapper<EffectData>&eff1,const std::reference_wrapper<EffectData>&eff2){return EFF(*eff1.get().effect).pos<EFF(*eff2.get().effect).pos;});
|
||||
std::ranges::sort(activeBackgroundEffects,[](const std::reference_wrapper<EffectData>&eff1,const std::reference_wrapper<EffectData>&eff2){return EFF(*eff1.get().effect).pos<EFF(*eff2.get().effect).pos;});
|
||||
auto foregroundEffectsUpper{activeForegroundEffects|std::views::filter([](const std::reference_wrapper<EffectData>&effect){return EFF(*effect.get().effect).OnUpperLevel();})};
|
||||
auto foregroundEffectsLower{activeForegroundEffects|std::views::filter([](const std::reference_wrapper<EffectData>&effect){return !EFF(*effect.get().effect).OnUpperLevel();})};
|
||||
auto backgroundEffectsUpper{activeBackgroundEffects|std::views::filter([](const std::reference_wrapper<EffectData>&effect){return EFF(*effect.get().effect).OnUpperLevel();})};
|
||||
auto backgroundEffectsLower{activeBackgroundEffects|std::views::filter([](const std::reference_wrapper<EffectData>&effect){return !EFF(*effect.get().effect).OnUpperLevel();})};
|
||||
std::vector<std::reference_wrapper<EffectT>>activeForegroundEffects,activeBackgroundEffects;
|
||||
std::ranges::for_each(EffectManager::foregroundEffectList,[&activeForegroundEffects=activeForegroundEffects](EffectData&eff){if(eff.effect)activeForegroundEffects.emplace_back(std::ref(*eff.effect));});
|
||||
std::ranges::for_each(EffectManager::backgroundEffectList,[&activeBackgroundEffects=activeBackgroundEffects](EffectData&eff){if(eff.effect)activeBackgroundEffects.emplace_back(std::ref(*eff.effect));});
|
||||
std::ranges::sort(activeForegroundEffects,[](const std::reference_wrapper<EffectT>&eff1,const std::reference_wrapper<EffectT>&eff2){return EFF(eff1.get()).pos<EFF(eff2.get()).pos;});
|
||||
std::ranges::sort(activeBackgroundEffects,[](const std::reference_wrapper<EffectT>&eff1,const std::reference_wrapper<EffectT>&eff2){return EFF(eff1.get()).pos<EFF(eff2.get()).pos;});
|
||||
auto foregroundEffectsUpper{activeForegroundEffects|std::views::filter([](const std::reference_wrapper<EffectT>&effect){return EFF(effect.get()).OnUpperLevel();})};
|
||||
auto foregroundEffectsLower{activeForegroundEffects|std::views::filter([](const std::reference_wrapper<EffectT>&effect){return !EFF(effect.get()).OnUpperLevel();})};
|
||||
auto backgroundEffectsUpper{activeBackgroundEffects|std::views::filter([](const std::reference_wrapper<EffectT>&effect){return EFF(effect.get()).OnUpperLevel();})};
|
||||
auto backgroundEffectsLower{activeBackgroundEffects|std::views::filter([](const std::reference_wrapper<EffectT>&effect){return !EFF(effect.get()).OnUpperLevel();})};
|
||||
auto upperEndZones{GetActiveZonesForCurrentMap()["EndZone"]|std::views::filter([](const ZoneData&zone){return zone.isUpper;})};
|
||||
auto endZones{GetActiveZonesForCurrentMap()["EndZone"]|std::views::filter([](const ZoneData&zone){return !zone.isUpper;})};
|
||||
#pragma endregion
|
||||
@ -1119,8 +1117,8 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
if(player->PoisonArrowAutoAttackReady()&&player->poisonArrowLastParticleTimer==0.f){
|
||||
const float particleSize{fmod(game->GetRunTime(),0.4f)<0.2f?1.f:1.5f};
|
||||
|
||||
game->AddEffect(Effect{player->GetPos()-vf2d{0,4.f}-player->GetFacingDirVector()*6.f,0.2f,"energy_particle.png",player->OnUpperLevel(),vf2d{particleSize,particleSize}*1.2f,0.05f,vf2d{},Pixel{0,255,255,120},util::random(2*PI),0.f,true});
|
||||
game->AddEffect(Effect{player->GetPos()-vf2d{0,4.f}-player->GetFacingDirVector()*6.f,0.2f,"energy_particle.png",player->OnUpperLevel(),vf2d{particleSize,particleSize},0.05f,vf2d{},DARK_GREEN,util::random(2*PI)});
|
||||
game->AddEffect(Effect{player->GetPos()-vf2d{0,4.f}-player->GetFacingDirVector()*6.f,0.2f,"energy_particle.png",player->OnUpperLevel(),vf2d{particleSize,particleSize}*1.2f,0.05f,vf2d{},Pixel{0,255,255,120},util::random(2*PI),0.f,true},false);
|
||||
game->AddEffect(Effect{player->GetPos()-vf2d{0,4.f}-player->GetFacingDirVector()*6.f,0.2f,"energy_particle.png",player->OnUpperLevel(),vf2d{particleSize,particleSize},0.05f,vf2d{},DARK_GREEN,util::random(2*PI)},false);
|
||||
player->poisonArrowLastParticleTimer=0.15f;
|
||||
}
|
||||
|
||||
@ -1410,7 +1408,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
{
|
||||
auto it=backgroundEffectsLower.begin();
|
||||
while(it!=backgroundEffectsLower.end()){
|
||||
const Effect&e=EFF(*(*it).get().effect);
|
||||
const Effect&e=EFF((*it).get());
|
||||
e._Draw();
|
||||
++it;
|
||||
}
|
||||
@ -1551,8 +1549,8 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
m.Draw();
|
||||
++monstersBeforeLowerIt;
|
||||
}
|
||||
for(std::reference_wrapper<EffectData>e:backgroundEffectsLower){
|
||||
EFF(*e.get().effect)._Draw();
|
||||
for(std::reference_wrapper<EffectT>e:backgroundEffectsLower){
|
||||
EFF(e.get())._Draw();
|
||||
}
|
||||
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
|
||||
const ItemDrop&drop{*dropsBeforeLowerIt};
|
||||
@ -1582,8 +1580,8 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
for(std::unique_ptr<IBullet>&b:bulletsLower){
|
||||
b->_Draw();
|
||||
}
|
||||
for(std::reference_wrapper<EffectData>e:foregroundEffectsLower){
|
||||
EFF(*e.get().effect)._Draw();
|
||||
for(std::reference_wrapper<EffectT>e:foregroundEffectsLower){
|
||||
EFF(e.get())._Draw();
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Permanent Foreground Rendering
|
||||
@ -1705,7 +1703,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
{
|
||||
auto it=backgroundEffectsUpper.begin();
|
||||
while(it!=backgroundEffectsUpper.end()){
|
||||
const Effect&e=EFF(*(*it).get().effect);
|
||||
const Effect&e=EFF((*it).get());
|
||||
e._Draw();
|
||||
++it;
|
||||
}
|
||||
@ -1858,8 +1856,8 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
m.Draw();
|
||||
++monstersBeforeUpperIt;
|
||||
}
|
||||
for(std::reference_wrapper<EffectData>e:backgroundEffectsUpper){
|
||||
EFF(*e.get().effect)._Draw();
|
||||
for(std::reference_wrapper<EffectT>e:backgroundEffectsUpper){
|
||||
EFF(e.get())._Draw();
|
||||
}
|
||||
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
|
||||
const ItemDrop&drop{*dropsBeforeUpperIt};
|
||||
@ -1887,8 +1885,8 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
for(std::unique_ptr<IBullet>&b:bulletsUpper){
|
||||
b->_Draw();
|
||||
}
|
||||
for(std::reference_wrapper<EffectData>e:foregroundEffectsUpper){
|
||||
EFF(*e.get().effect)._Draw();
|
||||
for(std::reference_wrapper<EffectT>e:foregroundEffectsUpper){
|
||||
EFF(e.get())._Draw();
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Permanent Upper Foreground Rendering
|
||||
@ -4534,10 +4532,8 @@ void AiL::AddToSpecialMarkedTargetList(std::tuple<std::weak_ptr<Monster>,StackCo
|
||||
lockOnSpecialTargets.emplace_back(markData);
|
||||
}
|
||||
|
||||
[[nodiscard]]std::vector<std::shared_ptr<Effect>>AiL::GetAllEffects()const{
|
||||
std::vector<std::shared_ptr<Effect>>allEffects{};
|
||||
std::ranges::merge(GetForegroundEffects(),GetBackgroundEffects(),std::back_inserter(allEffects));
|
||||
return allEffects;
|
||||
[[nodiscard]]std::pair<ForegroundEffectsArr,BackgroundEffectsArr>AiL::GetAllEffects()const{
|
||||
return {EffectManager::GetForegroundEffects(),EffectManager::GetBackgroundEffects()};
|
||||
}
|
||||
|
||||
void AiL::InitializeCamera(){
|
||||
@ -4623,8 +4619,11 @@ void AiL::AddNotification(const Notification&n){
|
||||
AiL::Notification::Notification(const std::string_view message,const float time,const Pixel col)
|
||||
:message(message),time(time),col(col){}
|
||||
|
||||
const std::vector<std::shared_ptr<Effect>>AiL::GetEffect(EffectType type){
|
||||
return GetAllEffects()|std::views::filter([&type](const std::shared_ptr<Effect>effect){return effect->GetType()==type;})|std::ranges::to<std::vector>();
|
||||
const std::vector<std::reference_wrapper<EffectData>>AiL::GetEffect(EffectType type){
|
||||
std::vector<std::reference_wrapper<EffectData>>foundEffects;
|
||||
std::ranges::copy(GetAllEffects().first|std::views::filter([&type](const EffectData&effect){return EFF(*effect.effect).GetType()==type;})|std::ranges::to<std::vector>(),std::back_inserter(foundEffects));
|
||||
std::ranges::copy(GetAllEffects().second|std::views::filter([&type](const EffectData&effect){return EFF(*effect.effect).GetType()==type;})|std::ranges::to<std::vector>(),std::back_inserter(foundEffects));
|
||||
return foundEffects;
|
||||
}
|
||||
|
||||
void AiL::PrecacheNewLevels(){
|
||||
|
||||
@ -82,8 +82,9 @@ using HurtListItem=std::pair<std::variant<Monster*,Player*>,HurtReturnValue>;
|
||||
using HurtList=std::vector<HurtListItem>;
|
||||
using StackCount=uint8_t;
|
||||
using MarkTime=float;
|
||||
using ForegroundWrapper=EffectRef;
|
||||
using BackgroundWrapper=EffectRef;
|
||||
|
||||
using ForegroundEffectsArr=std::array<EffectData,EFFECT_LIMIT>;
|
||||
using BackgroundEffectsArr=std::array<EffectData,EFFECT_LIMIT>;
|
||||
|
||||
enum class KnockbackCondition{
|
||||
KNOCKBACK_HURT_TARGETS, //Knockback only targets that took damage.
|
||||
@ -200,7 +201,7 @@ public:
|
||||
void RenderHud();
|
||||
void RenderMenu();
|
||||
bool MenuClicksDeactivated()const;
|
||||
const std::vector<std::shared_ptr<Effect>>GetEffect(EffectType type);
|
||||
const std::vector<std::reference_wrapper<EffectData>>GetEffect(EffectType type);
|
||||
std::vector<Entity>GetTargetsInRange(vf2d pos,float radius,bool upperLevel,float z,const HurtType hurtTargets)const;
|
||||
const HurtList Hurt(vf2d pos,float radius,int damage,bool upperLevel,float z,const HurtType hurtTargets,HurtFlag::HurtFlag hurtFlags=HurtFlag::NONE)const;
|
||||
const HurtList HurtMonsterType(vf2d pos,float radius,int damage,bool upperLevel,float z,const std::string_view monsterName,HurtFlag::HurtFlag hurtFlags=HurtFlag::NONE)const;
|
||||
@ -337,9 +338,7 @@ public:
|
||||
|
||||
void ResetLevelStates();
|
||||
|
||||
const std::vector<std::shared_ptr<Effect>>&GetForegroundEffects()const;
|
||||
const std::vector<std::shared_ptr<Effect>>&GetBackgroundEffects()const;
|
||||
std::vector<std::shared_ptr<Effect>>GetAllEffects()const; //Foreground and background effects in one vector.
|
||||
std::pair<ForegroundEffectsArr,BackgroundEffectsArr>GetAllEffects()const; //Foreground and background effects in one vector. (Foreground,Background)
|
||||
|
||||
struct TileGroupData{
|
||||
vi2d tilePos;
|
||||
@ -352,12 +351,16 @@ public:
|
||||
void PrecacheNewLevels();
|
||||
bool savingFile=false;
|
||||
|
||||
template<typename T,typename U>
|
||||
inline std::pair<EffectRef<T>,EffectRef<U>>AddEffect(Effect&&foreground,Effect&&background){
|
||||
return std::pair<EffectRef<T>,EffectRef<U>>{AddEffect(static_cast<T>(foreground),false),AddEffect(static_cast<T>(background),false)};
|
||||
}
|
||||
//If back is true, places the effect in the background.
|
||||
template<typename T>
|
||||
inline EffectRef AddEffect(T&&effect,bool back=false){
|
||||
inline EffectRef<T>AddEffect(const T&effect,bool back=false){
|
||||
std::array<EffectData,EFFECT_LIMIT>&effectList{back?EffectManager::backgroundEffectList:EffectManager::foregroundEffectList};
|
||||
for(size_t index{};const EffectData&data:effectList|std::views::drop_while([&index=index](const EffectData&data){
|
||||
if(*data.lifetime>0.f)return true;
|
||||
if(!data.effect)return true;
|
||||
index++;
|
||||
return false;
|
||||
})|std::views::take(1)){
|
||||
@ -366,12 +369,11 @@ public:
|
||||
if(back)EffectManager::activeBackgroundEffectCount++;
|
||||
else EffectManager::activeForegroundEffectCount++;
|
||||
[[unlikely]]if(EffectManager::GetForegroundEffectCount()>EFFECT_LIMIT||EffectManager::GetBackgroundEffectCount()>EFFECT_LIMIT)ERR(std::format("WARNING! Effect count has exceeded the limit of {}! THIS SHOULD NOT BE HAPPENING",EFFECT_LIMIT))
|
||||
return EffectRef{int(index),newEffectId};
|
||||
return EffectRef<T>{int(index),newEffectId};
|
||||
}
|
||||
effectListIsFull:{
|
||||
//Find oldest effect, overwrite that slot.
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
inline std::pair<ForegroundWrapper,BackgroundWrapper>AddEffect(T&&foreground,T&&background){
|
||||
return{AddEffect(foreground,false),AddEffect(background,false)};
|
||||
}
|
||||
private:
|
||||
std::vector<TileRenderData*>tilesWithCollision,tilesWithoutCollision;
|
||||
|
||||
19
Adventures in Lestoria/BlackHole.cpp
Normal file
19
Adventures in Lestoria/BlackHole.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include"EffectTypes.h"
|
||||
#include"DEFINES.h"
|
||||
#include"config.h"
|
||||
|
||||
INCLUDE_MONSTER_LIST
|
||||
|
||||
BlackHole::BlackHole(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,float particleSpawnFreq,const std::function<Effect(const Effect&self)>&particleGenerator)
|
||||
:FadeInOutEffect(pos,img,lifetime,onUpperLevel,size,spd,col,rotation,rotationSpd,additiveBlending,particleSpawnFreq,particleGenerator){}
|
||||
|
||||
bool BlackHole::Update(float fElapsedTime){
|
||||
for(std::shared_ptr<Monster>&m:MONSTER_LIST){
|
||||
float distToMonster{util::distance(pos,m->GetPos())};
|
||||
if(!m->IsSolid()&&m->OnUpperLevel()==OnUpperLevel()&&m->GetZ()<1.f&&distToMonster<="Black Hole"_ENC["PULL IN RADIUS"]/100.f*24){
|
||||
float pullInForce{util::map_range<float>(distToMonster,0,"Black Hole"_ENC["PULL IN RADIUS"]/100.f*24,"Black Hole"_ENC["PULL IN FORCE MAX"],"Black Hole"_ENC["PULL IN FORCE MIN"])};
|
||||
m->AddAddedVelocity(util::pointTo(m->GetPos(),pos)*pullInForce);
|
||||
}
|
||||
}
|
||||
return FadeInOutEffect::Update(fElapsedTime);
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy 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 "AdventuresInLestoria.h"
|
||||
#include "util.h"
|
||||
#include "Effect.h"
|
||||
|
||||
INCLUDE_MONSTER_LIST
|
||||
|
||||
struct BlackHole:FadeInOutEffect{
|
||||
inline BlackHole(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={})
|
||||
:FadeInOutEffect(pos,img,lifetime,onUpperLevel,size,spd,col,rotation,rotationSpd,additiveBlending,particleSpawnFreq,particleGenerator){}
|
||||
|
||||
inline bool Update(float fElapsedTime){
|
||||
for(std::shared_ptr<Monster>&m:MONSTER_LIST){
|
||||
float distToMonster{util::distance(pos,m->GetPos())};
|
||||
if(!m->IsSolid()&&m->OnUpperLevel()==OnUpperLevel()&&m->GetZ()<1.f&&distToMonster<="Black Hole"_ENC["PULL IN RADIUS"]/100.f*24){
|
||||
float pullInForce{util::map_range<float>(distToMonster,0,"Black Hole"_ENC["PULL IN RADIUS"]/100.f*24,"Black Hole"_ENC["PULL IN FORCE MAX"],"Black Hole"_ENC["PULL IN FORCE MIN"])};
|
||||
m->AddAddedVelocity(util::pointTo(m->GetPos(),pos)*pullInForce);
|
||||
}
|
||||
}
|
||||
return FadeInOutEffect::Update(fElapsedTime);
|
||||
}
|
||||
};
|
||||
@ -48,6 +48,36 @@ Blizzard::Blizzard(const vf2d pos,const float radius, const float lifetime,const
|
||||
,snow(std::make_unique<BlizzardSnowEmitter>(pos,"circle.png",radius*1.25f,snowSizeRange,emitterFreq,lifetime,upperLevel)){
|
||||
for(int i:std::ranges::iota_view(0,200))snow->Emit();
|
||||
}
|
||||
Blizzard&Blizzard::operator=(const Blizzard&newEff){
|
||||
Effect::operator=(newEff);
|
||||
this->damage=newEff.damage;
|
||||
this->tickRate=newEff.tickRate;
|
||||
this->tickTimer=newEff.tickTimer;
|
||||
this->radius=newEff.radius;
|
||||
this->friendly=newEff.friendly;
|
||||
this->snow.reset(newEff.snow.get());
|
||||
this->blizzardSFX=newEff.blizzardSFX;
|
||||
return *this;
|
||||
}
|
||||
Blizzard&Blizzard::operator=(Blizzard&&newEff){
|
||||
Effect::operator=(newEff);
|
||||
this->damage=newEff.damage;
|
||||
this->tickRate=newEff.tickRate;
|
||||
this->tickTimer=newEff.tickTimer;
|
||||
this->radius=newEff.radius;
|
||||
this->friendly=newEff.friendly;
|
||||
this->snow.reset(newEff.snow.get());
|
||||
this->blizzardSFX=newEff.blizzardSFX;
|
||||
return *this;
|
||||
}
|
||||
Blizzard::Blizzard(const Blizzard&newEff)
|
||||
:Effect(dynamic_cast<Effect&>(const_cast<Blizzard&>(newEff))){
|
||||
*this=newEff;
|
||||
}
|
||||
Blizzard::Blizzard(Blizzard&&newEff)
|
||||
:Effect(dynamic_cast<Effect&>(const_cast<Blizzard&>(newEff))){
|
||||
*this=newEff;
|
||||
}
|
||||
bool Blizzard::Update(float fElapsedTime){
|
||||
if(!IsDead()){
|
||||
blizzardSFX.Update();
|
||||
@ -58,7 +88,7 @@ bool Blizzard::Update(float fElapsedTime){
|
||||
tickTimer+=tickRate;
|
||||
game->Hurt(pos,radius*0.9f,damage,OnUpperLevel(),z,friendly?HurtType::MONSTER:HurtType::PLAYER);
|
||||
}
|
||||
snow->Update(fElapsedTime);
|
||||
}
|
||||
snow->Update(fElapsedTime);
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
@ -39,7 +39,6 @@ All rights reserved.
|
||||
|
||||
#include"BlizzardSnowEmitter.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
#include"FallEffect.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -57,5 +56,5 @@ void BlizzardSnowEmitter::Emit(){
|
||||
const float colorInterpolation{util::random(1)};
|
||||
const Pixel baseCol{104,215,239};
|
||||
const uint8_t alpha{uint8_t(util::random_range(96,255))};
|
||||
game->AddEffect(FallEffect{pos+vf2d{xSpd*timeToFall,0.f}+vf2d{dist,angle}.cart(),startingZ,gravity,img_filename,upperLevel,scale*vf2d{1.f,1.f},0.5f,vf2d{xSpd,0.f},Pixel{uint8_t(util::lerp(float(baseCol.r),255.f,colorInterpolation)),uint8_t(util::lerp(float(baseCol.g),255.f,colorInterpolation)),uint8_t(util::lerp(float(baseCol.b),255.f,colorInterpolation)),alpha},util::degToRad(util::random_range(0,360)),util::degToRad(util::random_range(-1.f,1.f)),true,EffectType::BLIZZARD_SNOW});
|
||||
game->AddEffect(FallWShadowEffect{pos+vf2d{xSpd*timeToFall,0.f}+vf2d{dist,angle}.cart(),startingZ,gravity,img_filename,upperLevel,scale*vf2d{1.f,1.f},0.5f,vf2d{xSpd,0.f},Pixel{uint8_t(util::lerp(float(baseCol.r),255.f,colorInterpolation)),uint8_t(util::lerp(float(baseCol.g),255.f,colorInterpolation)),uint8_t(util::lerp(float(baseCol.b),255.f,colorInterpolation)),alpha},util::degToRad(util::random_range(0,360)),util::degToRad(util::random_range(-1.f,1.f)),true,EffectType::BLIZZARD_SNOW});
|
||||
}
|
||||
@ -39,7 +39,6 @@ All rights reserved.
|
||||
#include "Bullet.h"
|
||||
#include "Direction.h"
|
||||
#include "Effect.h"
|
||||
#include "TrailEffect.h"
|
||||
#include "Entity.h"
|
||||
#include <variant>
|
||||
#include <memory>
|
||||
@ -61,7 +60,7 @@ struct FireBolt:public Bullet{
|
||||
BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
|
||||
void ModifyOutgoingDamageData(HurtDamageInfo&data)override;
|
||||
private:
|
||||
std::weak_ptr<TrailEffect>flameTrail;
|
||||
std::optional<EffectRef<TrailEffect>>flameTrail;
|
||||
};
|
||||
|
||||
struct LightningBolt:public Bullet{
|
||||
|
||||
@ -41,7 +41,6 @@ All rights reserved.
|
||||
#include "DEFINES.h"
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
#include "TrailEffect.h"
|
||||
#include <ranges>
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -42,7 +42,6 @@ All rights reserved.
|
||||
#include "util.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
CollectCoinEffect::CollectCoinEffect(const Entity attachedTarget,float coinArcRiseZAmt,float lifetime,const std::string&imgFile,bool upperLevel,float size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
|
||||
:Effect(attachedTarget.GetPos(),lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending),attachedTarget(attachedTarget),sizeFlipper(-1.f,1.f,lifetime*2.f),zRiser(0.f,coinArcRiseZAmt,1/lifetime){
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ using BackdropName=std::string;
|
||||
using MonsterSpawnerID=int;
|
||||
|
||||
#define EFFECT_LIMIT 1000
|
||||
#define mutableconst mutable /*This type indicates our intention was for it to be const but the class requires move assignability.*/
|
||||
|
||||
#define INCLUDE_ANIMATION_DATA extern safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
|
||||
#define INCLUDE_MONSTER_LIST extern std::vector<std::shared_ptr<Monster>>MONSTER_LIST;
|
||||
|
||||
@ -37,7 +37,13 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
|
||||
#include "Monster.h"
|
||||
#include"Effect.h"
|
||||
|
||||
DEFINE_STRATEGY(DONOTHING)
|
||||
Effect a{vf2d{},0.f,"",true,1.f,2.f,vf2d{},BLACK};
|
||||
Effect b{vf2d{},0.f,"",true,1.f,2.f,vf2d{},BLACK};
|
||||
|
||||
EffectT eff{a};
|
||||
EffectT eff2=b;
|
||||
eff=eff2;
|
||||
END_STRATEGY
|
||||
@ -143,26 +143,15 @@ const bool Effect::IsDead()const{
|
||||
return lifetime<=0.f;
|
||||
}
|
||||
|
||||
|
||||
EffectData::EffectData(){}
|
||||
EffectData::EffectData(int effectId,Effect&&effect):effectId(effectId),effect(effect),lifetime(&effect.lifetime){}
|
||||
EffectRef::EffectRef(int slotId,int effectId):slotId(slotId),effectId(effectId){}
|
||||
|
||||
bool EffectRef::expired()const{
|
||||
const std::array<EffectManager::EffectData,EFFECT_LIMIT>&effectList{foregroundEffect?EffectManager::GetForegroundEffects():EffectManager::GetBackgroundEffects()};
|
||||
return effectList.at(slotId).effectId!=effectId||*(effectList.at(slotId).lifetime)<=0.f;
|
||||
};
|
||||
|
||||
bool EffectRef::operator==(const EffectRef&ref){
|
||||
return !expired();
|
||||
};
|
||||
EffectData::EffectData(int effectId,const Effect&effect):effectId(effectId),effect(effect){}
|
||||
|
||||
void EffectManager::Reset(){
|
||||
foregroundEffectList.fill({});
|
||||
backgroundEffectList.fill({});
|
||||
activeForegroundEffectCount=activeBackgroundEffectCount=0;
|
||||
for(const EffectData&effData:foregroundEffectList|std::views::drop_while([](const EffectData&effData){return *effData.lifetime<=0.f;}))ERR(std::format("WARNING! The active effect count !=0! (Reported:{})! IT SHOULD BE CLEARED!!!",GetForegroundEffectCount()));
|
||||
for(const EffectData&effData:backgroundEffectList|std::views::drop_while([](const EffectData&effData){return *effData.lifetime<=0.f;}))ERR(std::format("WARNING! The active effect count !=0! (Reported:{})! IT SHOULD BE CLEARED!!!",GetBackgroundEffectCount()));
|
||||
for(const EffectData&effData:foregroundEffectList|std::views::drop_while([](const EffectData&effData){return !effData.effect.has_value();}))ERR(std::format("WARNING! The active effect count !=0! (Reported:{})! IT SHOULD BE CLEARED!!!",GetForegroundEffectCount()));
|
||||
for(const EffectData&effData:backgroundEffectList|std::views::drop_while([](const EffectData&effData){return !effData.effect.has_value();}))ERR(std::format("WARNING! The active effect count !=0! (Reported:{})! IT SHOULD BE CLEARED!!!",GetBackgroundEffectCount()));
|
||||
}
|
||||
|
||||
size_t EffectManager::GetForegroundEffectCount(){
|
||||
@ -171,9 +160,9 @@ size_t EffectManager::GetForegroundEffectCount(){
|
||||
size_t EffectManager::GetBackgroundEffectCount(){
|
||||
return activeBackgroundEffectCount;
|
||||
}
|
||||
const std::array<EffectData,EFFECT_LIMIT>&EffectManager::GetForegroundEffects(){
|
||||
std::array<EffectData,EFFECT_LIMIT>&EffectManager::GetForegroundEffects(){
|
||||
return foregroundEffectList;
|
||||
}
|
||||
const std::array<EffectData,EFFECT_LIMIT>&EffectManager::GetBackgroundEffects(){
|
||||
std::array<EffectData,EFFECT_LIMIT>&EffectManager::GetBackgroundEffects(){
|
||||
return backgroundEffectList;
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include"EffectTypes.h"
|
||||
|
||||
#define EFF(variant) EffectManager::GetEffect(variant)
|
||||
|
||||
using EffectT=std::variant<
|
||||
Effect,
|
||||
Meteor,
|
||||
@ -17,7 +19,12 @@ using EffectT=std::variant<
|
||||
FlipCoinEffect,
|
||||
CollectCoinEffect,
|
||||
Blizzard,
|
||||
FreezeGround
|
||||
FreezeGround,
|
||||
TrailEffect,
|
||||
BlackHole,
|
||||
ExpandingRing,
|
||||
FallEffect,
|
||||
FallWShadowEffect
|
||||
>;
|
||||
|
||||
struct EffectOverloads{
|
||||
@ -31,40 +38,56 @@ struct EffectManager{
|
||||
friend class AiL;
|
||||
struct EffectData{
|
||||
EffectData();
|
||||
EffectData(int effectId,Effect&&effect);
|
||||
EffectData(int effectId,const Effect&effect);
|
||||
int effectId{};
|
||||
std::optional<EffectT>effect{};
|
||||
float*lifetime{nullptr};
|
||||
};
|
||||
static void Reset();
|
||||
static const std::array<EffectData,EFFECT_LIMIT>&GetForegroundEffects();
|
||||
static const std::array<EffectData,EFFECT_LIMIT>&GetBackgroundEffects();
|
||||
static std::array<EffectData,EFFECT_LIMIT>&GetForegroundEffects();
|
||||
static std::array<EffectData,EFFECT_LIMIT>&GetBackgroundEffects();
|
||||
static size_t GetForegroundEffectCount();
|
||||
static size_t GetBackgroundEffectCount();
|
||||
struct funcName_Overloads {
|
||||
template<typename T>
|
||||
const Effect& operator()(T&obj) {
|
||||
return obj;
|
||||
};
|
||||
};
|
||||
template<typename T>
|
||||
static Effect& GetEffect(T& eff) {
|
||||
return const_cast<Effect&>(std::visit(funcName_Overloads{},eff));
|
||||
};
|
||||
private:
|
||||
inline static int GLOBAL_EFFECT_ID{0};
|
||||
static std::array<EffectData,EFFECT_LIMIT>foregroundEffectList;
|
||||
static size_t activeForegroundEffectCount;
|
||||
static std::array<EffectData,EFFECT_LIMIT>backgroundEffectList;
|
||||
std::vector<std::shared_ptr<Effect>>d;
|
||||
static size_t activeBackgroundEffectCount;
|
||||
inline static std::array<EffectData,EFFECT_LIMIT>foregroundEffectList{};
|
||||
inline static size_t activeForegroundEffectCount{};
|
||||
inline static std::array<EffectData,EFFECT_LIMIT>backgroundEffectList{};
|
||||
inline static size_t activeBackgroundEffectCount{};
|
||||
};
|
||||
|
||||
using EffectData=EffectManager::EffectData;
|
||||
|
||||
template<typename T>
|
||||
struct EffectRef{
|
||||
public:
|
||||
EffectRef(int slotId,int effectId);
|
||||
bool expired()const;
|
||||
bool operator==(const EffectRef&ref);
|
||||
template<typename T>
|
||||
T&&get(){
|
||||
std::array<EffectManager::EffectData,1000>&effectList{foregroundEffect?EffectManager::foregroundEffectList:EffectManager::backgroundEffectList};
|
||||
inline EffectRef(int slotId,int effectId):slotId(slotId),effectId(effectId){}
|
||||
|
||||
inline bool expired()const{
|
||||
const std::array<EffectManager::EffectData,EFFECT_LIMIT>&effectList{foregroundEffect?EffectManager::GetForegroundEffects():EffectManager::GetBackgroundEffects()};
|
||||
return effectList.at(slotId).effectId!=effectId||effectList.at(slotId).effect;
|
||||
};
|
||||
|
||||
inline bool operator==(const EffectRef&ref){
|
||||
return !expired();
|
||||
};
|
||||
|
||||
T&get(){
|
||||
std::array<EffectManager::EffectData,1000>&effectList{foregroundEffect?EffectManager::GetForegroundEffects():EffectManager::GetBackgroundEffects()};
|
||||
if(expired())ERR("WARNING! This effect was not properly checked for expiration! THIS IS NOT ALLOWED!");
|
||||
return std::any_cast<T>(effectList.at(slotId).effect);
|
||||
return std::get<T>(*effectList.at(slotId).effect);
|
||||
};
|
||||
private:
|
||||
int slotId;
|
||||
int effectId;
|
||||
bool foregroundEffect{false};
|
||||
};
|
||||
};
|
||||
@ -58,18 +58,6 @@ enum class EffectType{
|
||||
BLIZZARD_SNOW,
|
||||
};
|
||||
|
||||
#define CREATE_VARIANT(funcName,funcDeclaration,returnFunc)\
|
||||
struct funcName_Overloads{\
|
||||
template<typename T>\
|
||||
returnFunc\
|
||||
};\
|
||||
template<typename T>\
|
||||
static funcDeclaration{\
|
||||
return std::visit(Effect::funcName_Overloads{},eff);\
|
||||
}
|
||||
|
||||
#define EFF(variant) Effect::GetEffect(variant)
|
||||
|
||||
struct Effect{
|
||||
friend class AiL;
|
||||
friend struct FallingBullet;
|
||||
@ -100,7 +88,6 @@ public:
|
||||
const bool&OnUpperLevel()const;
|
||||
void SetType(const EffectType type);
|
||||
const bool IsDead()const;
|
||||
CREATE_VARIANT(GetEffect,Effect&GetEffect(T&eff),Effect&operator()(T&obj)const{return obj;});
|
||||
|
||||
protected:
|
||||
float original_fadeOutTime;
|
||||
@ -139,8 +126,8 @@ private:
|
||||
float damageMult{1.f};
|
||||
float fireRingLifetime{};
|
||||
std::string meteorCrashSFX{};
|
||||
const std::pair<MeteorDamage,PulsatingFireDamage>damage{};
|
||||
const MeteorSetting setting;
|
||||
mutableconst std::pair<MeteorDamage,PulsatingFireDamage>damage{};
|
||||
mutableconst MeteorSetting setting;
|
||||
};
|
||||
|
||||
struct PulsatingFire:Effect{
|
||||
@ -154,7 +141,7 @@ struct PulsatingFire:Effect{
|
||||
float lastDamageTimer=0;
|
||||
float radius;
|
||||
int damage;
|
||||
const PulsatingFireSetting setting;
|
||||
mutableconst PulsatingFireSetting setting;
|
||||
bool Update(float fElapsedTime)override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
void Draw(const Pixel blendCol)const override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
};
|
||||
@ -164,8 +151,8 @@ struct SwordSlash:Effect{
|
||||
bool Update(float fElapsedTime)override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
private:
|
||||
HitList hitList;
|
||||
const float damageMult;
|
||||
const float swordSweepAngle;
|
||||
mutableconst float damageMult;
|
||||
mutableconst float swordSweepAngle;
|
||||
};
|
||||
|
||||
//This draws effects using screen coordinates instead of world coordinates, useful for applying effects directly on the screen.
|
||||
@ -198,7 +185,7 @@ struct ShineEffect:Effect{
|
||||
virtual bool Update(float fElapsedTime)override final; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
private:
|
||||
float fadeinTime;
|
||||
const Pixel originalCol;
|
||||
mutableconst Pixel originalCol;
|
||||
};
|
||||
|
||||
//Spawns and moves towards the player after some amount of time.
|
||||
@ -226,23 +213,23 @@ struct FadeInOutEffect:Effect{
|
||||
virtual bool Update(float fElapsedTime)override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
virtual void Draw(const Pixel blendCol)const override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
std::function<Effect(const Effect&self)>particleGenerator;
|
||||
const float particleSpawnFreq;
|
||||
mutableconst float particleSpawnFreq;
|
||||
Oscillator<vf2d>posOscillator;
|
||||
Oscillator<vf2d>sizeOscillator;
|
||||
Oscillator<Pixel>colOscillator;
|
||||
float particleSpawnTimer{};
|
||||
const float originalParticleSpawnTimer{};
|
||||
mutableconst float originalParticleSpawnTimer{};
|
||||
};
|
||||
|
||||
struct LingeringEffect:FadeInOutEffect{
|
||||
LingeringEffect(vf2d pos,const std::string&img,const std::string&soundEffect,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; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
const int damage;
|
||||
mutableconst int damage;
|
||||
float damageTimer{};
|
||||
const float originalDamageTimer{};
|
||||
const float radius;
|
||||
mutableconst float originalDamageTimer{};
|
||||
mutableconst float radius;
|
||||
HurtType friendly;
|
||||
const size_t sfxID{};
|
||||
mutableconst size_t sfxID{};
|
||||
};
|
||||
|
||||
struct Ink:Effect{
|
||||
@ -251,9 +238,9 @@ struct Ink:Effect{
|
||||
Ink(vf2d pos,float radius,float lifetime,float inkSlowdownDuration,float inkSlowdownPct,float fadeinTime,float fadeoutTime,vf2d size,Pixel col,bool onUpperLevel,float rotation);
|
||||
virtual bool Update(float fElapsedTime)override final; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
private:
|
||||
const float radius;
|
||||
const float inkSlowdownDuration;
|
||||
const float inkSlowdownAmount;
|
||||
mutableconst float radius;
|
||||
mutableconst float inkSlowdownDuration;
|
||||
mutableconst float inkSlowdownAmount;
|
||||
};
|
||||
|
||||
struct FlipCoinEffect:Effect{
|
||||
@ -271,7 +258,7 @@ struct CollectCoinEffect:Effect{
|
||||
CollectCoinEffect(const Entity attachedTarget,float coinArcRiseZAmt,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);
|
||||
virtual bool Update(float fElapsedTime)override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
virtual void Draw(const Pixel blendCol)const override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
const Entity attachedTarget;
|
||||
mutableconst Entity attachedTarget;
|
||||
Oscillator<float>sizeFlipper;
|
||||
Oscillator<float>zRiser;
|
||||
};
|
||||
@ -279,6 +266,10 @@ struct CollectCoinEffect:Effect{
|
||||
struct Blizzard:Effect{
|
||||
public:
|
||||
Blizzard(const vf2d pos,const float radius,const float lifetime,const int damage,const float tickRate,const std::pair<MinScale,MaxScale>snowSizeRange,const float emitterFreq,const bool upperLevel,const FriendlyType friendly);
|
||||
Blizzard(const Blizzard&newEff);
|
||||
Blizzard(Blizzard&&newEff);
|
||||
Blizzard&operator=(const Blizzard&newEff);
|
||||
Blizzard&operator=(Blizzard&&newEff);
|
||||
bool Update(float fElapsedTime)override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
private:
|
||||
int damage;
|
||||
@ -306,9 +297,53 @@ public:
|
||||
FreezeGround(const vf2d pos,const float lifetime,const int damage,const FreezeGroundSettings settings,const bool upperLevel,const FriendlyType friendly);
|
||||
bool Update(float fElapsedTime)override; //NOTE: In most cases, call Effect::Update() in your overwritten function!
|
||||
private:
|
||||
const int damage;
|
||||
mutableconst int damage;
|
||||
float tickTimer{};
|
||||
std::unordered_set<Entity>entitiesInside;
|
||||
const FriendlyType friendly;
|
||||
const FreezeGroundSettings settings;
|
||||
mutableconst FriendlyType friendly;
|
||||
mutableconst FreezeGroundSettings settings;
|
||||
};
|
||||
|
||||
struct TrailEffect:Effect{
|
||||
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);
|
||||
void SetEndPos(const vf2d pos);
|
||||
bool Update(float fElapsedTime);
|
||||
void Draw(const Pixel blendCol)const;
|
||||
private:
|
||||
Oscillator<Pixel>col;
|
||||
vf2d endPos{};
|
||||
float imageXSpd;
|
||||
float imageXOffset{};
|
||||
int damage;
|
||||
float damageTickFrequency;
|
||||
float hitTimer{};
|
||||
};
|
||||
|
||||
struct BlackHole:FadeInOutEffect{
|
||||
BlackHole(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={});
|
||||
bool Update(float fElapsedTime);
|
||||
};
|
||||
|
||||
|
||||
struct ExpandingRing:Effect{
|
||||
ExpandingRing(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d expandingSize,vf2d size={1.f,1.f},float fadeout=0.f,vf2d spd={},Pixel col=WHITE,float rotation=0.f,float rotationSpd=0.f,bool additiveBlending=false);
|
||||
bool Update(float fElapsedTime);
|
||||
private:
|
||||
mutableconst vf2d expandingSize;
|
||||
};
|
||||
|
||||
class FallEffect:public Effect{
|
||||
public:
|
||||
FallEffect(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);
|
||||
bool Update(float fElapsedTime)override;
|
||||
private:
|
||||
mutableconst float gravity{20};
|
||||
};
|
||||
|
||||
class FallWShadowEffect:public Effect{
|
||||
public:
|
||||
FallWShadowEffect(vf2d pos,const float z,const float gravity,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,const EffectType type=EffectType::NONE);
|
||||
bool Update(float fElapsedTime)override;
|
||||
private:
|
||||
mutableconst float gravity;
|
||||
};
|
||||
@ -42,6 +42,7 @@ All rights reserved.
|
||||
#include"Buff.h"
|
||||
#include"HurtDamageInfo.h"
|
||||
#include"FriendlyType.h"
|
||||
#include"DEFINES.h"
|
||||
|
||||
class Player;
|
||||
class Monster;
|
||||
@ -71,7 +72,7 @@ public:
|
||||
const int GetAttack()const;
|
||||
const FriendlyType IsFriendly()const;
|
||||
private:
|
||||
const std::variant<Monster*,Player*>entity;
|
||||
mutableconst std::variant<Monster*,Player*>entity;
|
||||
inline bool operator==(const Entity&rhs){return entity==rhs.entity;}
|
||||
};
|
||||
|
||||
|
||||
@ -35,22 +35,13 @@ Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "Effect.h"
|
||||
#include "DEFINES.h"
|
||||
#include "safemap.h"
|
||||
#pragma once
|
||||
|
||||
INCLUDE_GFX
|
||||
#include "EffectTypes.h"
|
||||
|
||||
class FallEffect:public Effect{
|
||||
const float gravity=20;
|
||||
public:
|
||||
inline FallEffect(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(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){
|
||||
|
||||
}
|
||||
|
||||
inline bool Update(float fElapsedTime)override{
|
||||
spd.y+=gravity*fElapsedTime;
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
};
|
||||
ExpandingRing::ExpandingRing(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d expandingSize,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
|
||||
:expandingSize(expandingSize),Effect(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){}
|
||||
bool ExpandingRing::Update(float fElapsedTime){
|
||||
size+=expandingSize*fElapsedTime;
|
||||
return true;
|
||||
}
|
||||
@ -103,8 +103,8 @@ void ExplosiveTrap::Detonate(){
|
||||
}
|
||||
}
|
||||
|
||||
std::weak_ptr<Effect>explodeEffect{game->AddEffect(Effect{pos,ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()-0.2f,"explosionframes.png",OnUpperLevel(),scale*2.f,0.2f,vf2d{0,-6.f},WHITE,util::random(2*PI),0.f})};
|
||||
explodeEffect.lock()->scaleSpd={0.125f,0.125f};
|
||||
auto explodeEffect{game->AddEffect(Effect{pos,ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()-0.2f,"explosionframes.png",OnUpperLevel(),scale*2.f,0.2f,vf2d{0,-6.f},WHITE,util::random(2*PI),0.f})};
|
||||
explodeEffect.get().scaleSpd={0.125f,0.125f};
|
||||
SoundEffect::PlaySFX("Explosion",pos);
|
||||
explosionCount--;
|
||||
if(explosionCount>0)rearmTime=0.6f;
|
||||
|
||||
@ -30,23 +30,29 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
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
|
||||
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 "EffectTypes.h"
|
||||
|
||||
#include "Effect.h"
|
||||
FallEffect::FallEffect(vf2d pos, float lifetime,const 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){}
|
||||
|
||||
bool FallEffect::Update(float fElapsedTime){
|
||||
spd.y+=gravity*fElapsedTime;
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
|
||||
struct ExpandingRing:Effect{
|
||||
inline ExpandingRing(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d expandingSize,vf2d size={1.f,1.f},float fadeout=0.f,vf2d spd={},Pixel col=WHITE,float rotation=0.f,float rotationSpd=0.f,bool additiveBlending=false)
|
||||
:expandingSize(expandingSize),Effect(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){}
|
||||
inline bool Update(float fElapsedTime){
|
||||
size+=expandingSize*fElapsedTime;
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
const vf2d expandingSize;
|
||||
};
|
||||
FallWShadowEffect::FallWShadowEffect(vf2d pos,const float z,const float gravity,const std::string&imgFile, bool upperLevel,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending,const EffectType type)
|
||||
:gravity(gravity),Effect(pos,INFINITY,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){
|
||||
this->z=z;
|
||||
this->SetType(type);
|
||||
}
|
||||
|
||||
bool FallWShadowEffect::Update(float fElapsedTime){
|
||||
z-=gravity*fElapsedTime;
|
||||
if(z<=0.f)lifetime=0.f;
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy 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
|
||||
#include "Effect.h"
|
||||
#include "DEFINES.h"
|
||||
#include "safemap.h"
|
||||
|
||||
INCLUDE_GFX
|
||||
|
||||
//This class is used when you want an effect to start in mid-air and fall down. It disappears upon hitting the ground.
|
||||
class FallEffect:public Effect{
|
||||
public:
|
||||
inline FallEffect(vf2d pos,const float z,const float gravity,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,const EffectType type=EffectType::NONE)
|
||||
:gravity(gravity),Effect(pos,INFINITY,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){
|
||||
this->z=z;
|
||||
this->SetType(type);
|
||||
}
|
||||
|
||||
inline bool Update(float fElapsedTime)override{
|
||||
z-=gravity*fElapsedTime;
|
||||
if(z<=0.f)lifetime=0.f;
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
private:
|
||||
const float gravity;
|
||||
};
|
||||
@ -41,7 +41,7 @@ All rights reserved.
|
||||
#include "DEFINES.h"
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
#include "TrailEffect.h"
|
||||
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_MONSTER_LIST
|
||||
@ -49,7 +49,7 @@ INCLUDE_MONSTER_LIST
|
||||
FireBolt::FireBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,FriendlyType friendly,Pixel col)
|
||||
:Bullet(pos,vel,radius,damage,
|
||||
"energy_bolt.png",upperLevel,false,INFINITE,true,friendly,col){
|
||||
if(game->GetPlayer()->HasEnchant("Trail of Fire")&&friendly)flameTrail=DYNAMIC_POINTER_CAST<TrailEffect>(game->AddEffect(TrailEffect{pos,"Trail of Fire"_ENC["TRAIL DURATION"],"FlamesTexture.png",int("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));
|
||||
if(game->GetPlayer()->HasEnchant("Trail of Fire")&&friendly)flameTrail=game->AddEffect(TrailEffect{pos,"Trail of Fire"_ENC["TRAIL DURATION"],"FlamesTexture.png",int("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);
|
||||
SoundEffect::PlaySFX("Wizard Fire Bolt Shoot",SoundEffect::CENTERED);
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ void FireBolt::Update(float fElapsedTime){
|
||||
SoundEffect::PlaySFX("Wizard Fire Bolt Hit",pos);
|
||||
}
|
||||
|
||||
if(!flameTrail.expired())flameTrail.lock()->SetEndPos(pos);
|
||||
if(flameTrail&&!(*flameTrail).expired())(*flameTrail).get().SetEndPos(pos);
|
||||
}
|
||||
|
||||
BulletDestroyState FireBolt::PlayerHit(Player*player)
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
INCLUDE_GFX
|
||||
INCLUDE_game
|
||||
|
||||
|
||||
FreezeGround::FreezeGround(const vf2d pos,const float lifetime,const int damage,const FreezeGroundSettings settings,const bool upperLevel,const FriendlyType friendly)
|
||||
:damage(damage),friendly(friendly),settings(settings),Effect(pos,lifetime,"freezeground.png",upperLevel,settings.radius/100.f/(GFX["freezeground.png"].Sprite()->Size().x/24.f)*2.35f,0.5f,{},{199,247,239,32},0.f,0.f,true)
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#pragma region License
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
@ -38,6 +38,9 @@ All rights reserved.
|
||||
|
||||
#include "BulletTypes.h"
|
||||
#include "Attributable.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
GhostSaber::GhostSaber(const vf2d pos,const std::weak_ptr<Monster>target,const float lifetime,const float distFromTarget,const float knockbackAmt,const float initialRot,const float radius,const float expandSpd,const int damage,const bool upperLevel,const float rotSpd,const FriendlyType friendly,const Pixel col,const vf2d scale,const float image_angle)
|
||||
:Bullet(target.lock()->GetPos()+vf2d{distFromTarget,initialRot}.cart(),{},radius,damage,"ghost_dagger.png",upperLevel,true,INFINITE,false,friendly,col,scale,image_angle),attachedMonster(target),rotSpd(rotSpd),distFromTarget(distFromTarget),rot(initialRot),aliveTime(lifetime),knockbackAmt(knockbackAmt),expandSpd(expandSpd){}
|
||||
|
||||
@ -46,6 +46,7 @@ using A=Attribute;
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_MONSTER_LIST
|
||||
INCLUDE_GFX
|
||||
|
||||
DEFINE_STRATEGY(GIANT_OCTOPUS)
|
||||
enum PhaseName{
|
||||
|
||||
@ -37,6 +37,9 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
|
||||
#include "BulletTypes.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
HomingBullet::HomingBullet(const vf2d pos,const Entity target,const float rotateTowardsSpeed,const float rotateTowardsSpeedCoveredInInk,const float lifetime,const float speed,const float radius,const int damage,const bool upperLevel,const FriendlyType friendly,const Pixel col,const vf2d scale,const float image_angle)
|
||||
:Bullet(pos,util::pointTo(pos,target.GetPos())*speed,radius,damage,upperLevel,friendly,col,scale,image_angle),target(target),rotateTowardsSpeed(rotateTowardsSpeed),rotateTowardsSpeedCoveredInInk(rotateTowardsSpeedCoveredInInk){
|
||||
|
||||
@ -37,8 +37,10 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
|
||||
#include "BulletTypes.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
|
||||
INCLUDE_ANIMATION_DATA
|
||||
INCLUDE_game
|
||||
|
||||
InkBullet::InkBullet(const vf2d pos,const vf2d targetPos,const vf2d vel,const float inkExplosionRadius,const float inkPuddleLifetime,const float inkSlowdownDuration,const float inkSlowdownPct,const float inkPuddleRadius,const bool upperLevel,const FriendlyType friendly)
|
||||
:Bullet(pos,vel,inkExplosionRadius,0,"inkbullet.png",upperLevel,friendly),targetPos(targetPos),inkExplosionRadius(inkExplosionRadius),inkSlowdownPct(inkSlowdownPct),inkSlowdownDuration(inkSlowdownDuration),inkPuddleLifetime(inkPuddleLifetime),inkPuddleRadius(inkPuddleRadius){
|
||||
|
||||
@ -38,7 +38,6 @@ All rights reserved.
|
||||
|
||||
#include "BulletTypes.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "FallingDebris.h"
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
|
||||
@ -66,6 +66,7 @@ INCLUDE_BULLET_LIST
|
||||
INCLUDE_DATA
|
||||
INCLUDE_SPAWNER_CONTROLLER
|
||||
INCLUDE_SPAWNER_LIST
|
||||
INCLUDE_GFX
|
||||
|
||||
safemap<std::string,std::function<void(Monster&,float,std::string)>>STRATEGY_DATA;
|
||||
std::unordered_map<std::string,Renderable*>MonsterData::imgs;
|
||||
@ -1245,8 +1246,8 @@ void Monster::OnDeath(){
|
||||
|
||||
float targetScale{radius/24};
|
||||
float startingScale{GetCollisionRadius()/24};
|
||||
std::weak_ptr<Effect>eff{game->AddEffect(Effect{pos,ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()-0.2f,"explosionframes.png",OnUpperLevel(),startingScale,0.2f,vf2d{0,-6.f},WHITE,util::random(2*PI),0.f})};
|
||||
eff.lock()->scaleSpd={(targetScale-startingScale)/ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration(),(targetScale-startingScale)/ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()};
|
||||
auto eff{game->AddEffect(Effect{pos,ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()-0.2f,"explosionframes.png",OnUpperLevel(),startingScale,0.2f,vf2d{0,-6.f},WHITE,util::random(2*PI),0.f})};
|
||||
eff.get().scaleSpd={(targetScale-startingScale)/ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration(),(targetScale-startingScale)/ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()};
|
||||
SoundEffect::PlaySFX("Explosion",pos);
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
@ -55,8 +55,11 @@ public:
|
||||
inline const T&get()const{
|
||||
return currentVal;
|
||||
};
|
||||
const T&first;
|
||||
const T&second;
|
||||
mutableconst std::reference_wrapper<T>first;
|
||||
|
||||
|
||||
|
||||
std::reference_wrapper<T>second;
|
||||
private:
|
||||
T val1,val2;
|
||||
T currentVal;
|
||||
|
||||
@ -43,6 +43,7 @@ All rights reserved.
|
||||
#include "BulletTypes.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
|
||||
DEFINE_STRATEGY(PIRATE_BUCCANEER)
|
||||
#pragma region Phase, Animation, and Helper function setup
|
||||
|
||||
@ -45,6 +45,7 @@ All rights reserved.
|
||||
using A=Attribute;
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
|
||||
DEFINE_STRATEGY(PIRATE_MARAUDER)
|
||||
enum PhaseName{
|
||||
|
||||
@ -496,7 +496,7 @@ void Player::Update(float fElapsedTime){
|
||||
monsterPtr->Knockback(vf2d{knockbackAmt,knockbackDir}.cart());
|
||||
}
|
||||
#pragma endregion
|
||||
game->AddEffect(Effect{GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-front.png",upperLevel,groundSlamVisualRange,"Warrior.Ability 2.EffectFadetime"_F},Effect{GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-back.png",upperLevel,groundSlamVisualRange,"Warrior.Ability 2.EffectFadetime"_F});
|
||||
game->AddEffect<Effect,Effect>({GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-front.png",upperLevel,groundSlamVisualRange,"Warrior.Ability 2.EffectFadetime"_F},{GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-back.png",upperLevel,groundSlamVisualRange,"Warrior.Ability 2.EffectFadetime"_F});
|
||||
SoundEffect::PlaySFX("Warrior Ground Slam",SoundEffect::CENTERED);
|
||||
}
|
||||
if(lastAnimationFlip>0){
|
||||
|
||||
@ -38,6 +38,10 @@ All rights reserved.
|
||||
|
||||
#include "BulletTypes.h"
|
||||
#include <ranges>
|
||||
#include"SoundEffect.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
PoisonBottle::PoisonBottle(vf2d pos,vf2d targetPos,const std::string&img,float explodeRadius,float bounceExplodeRadius,float z,float totalFallTime,float totalRiseZAmt,int damage,int additionalBounceCount,bool upperLevel,bool hitsMultiple,float lifetime,FriendlyType friendly,Pixel col,vf2d scale,float image_angle)
|
||||
:ThrownProjectile(pos,targetPos,img,explodeRadius,z,totalFallTime,totalRiseZAmt,damage,upperLevel,hitsMultiple,lifetime,friendly,col,scale,image_angle),bounceExplodeRadius(bounceExplodeRadius),additionalBounceCount(additionalBounceCount){
|
||||
|
||||
@ -93,8 +93,8 @@ BulletDestroyState PurpleEnergyBall::PlayerHit(Player*player)
|
||||
if(bounceCount<=0)fadeOutTime="Witch.Auto Attack.BulletHitFadeoutTime"_F;
|
||||
else lastHitTimer=0.1f;
|
||||
Deactivate();
|
||||
std::weak_ptr<Effect>hitEffect{game->AddEffect(Effect{player->GetPos(),0,"purpleenergyball_hit.png",upperLevel,player->GetSizeMult(),"Witch.Auto Attack.SplashEffectFadeoutTime"_F,vf2d{},WHITE,util::random(2*PI),5*PI})};
|
||||
hitEffect.lock()->scaleSpd={-0.3f,-0.3f};
|
||||
auto hitEffect{game->AddEffect(Effect{player->GetPos(),0,"purpleenergyball_hit.png",upperLevel,player->GetSizeMult(),"Witch.Auto Attack.SplashEffectFadeoutTime"_F,vf2d{},WHITE,util::random(2*PI),5*PI})};
|
||||
hitEffect.get().scaleSpd={-0.3f,-0.3f};
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ BulletDestroyState PurpleEnergyBall::MonsterHit(Monster&monster,const uint8_t ma
|
||||
if(bounceCount<=0)fadeOutTime="Witch.Auto Attack.BulletHitFadeoutTime"_F;
|
||||
else lastHitTimer=0.1f;
|
||||
Deactivate();
|
||||
std::weak_ptr<Effect>hitEffect{game->AddEffect(Effect{monster.GetPos(),0,"purpleenergyball_hit.png",upperLevel,monster.GetSizeMult(),"Witch.Auto Attack.SplashEffectFadeoutTime"_F,vf2d{},WHITE,util::random(2*PI),5*PI})};
|
||||
hitEffect.lock()->scaleSpd={-0.3f,-0.3f};
|
||||
auto hitEffect{game->AddEffect(Effect{monster.GetPos(),0,"purpleenergyball_hit.png",upperLevel,monster.GetSizeMult(),"Witch.Auto Attack.SplashEffectFadeoutTime"_F,vf2d{},WHITE,util::random(2*PI),5*PI})};
|
||||
hitEffect.get().scaleSpd={-0.3f,-0.3f};
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
@ -37,6 +37,7 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
|
||||
#include "BulletTypes.h"
|
||||
#include"Player.h"
|
||||
|
||||
|
||||
RotateBullet::RotateBullet(vf2d pos,float startingAng,float startSpeed,float acc,float headingAngleChange,float radius,int damage,bool upperLevel,FriendlyType friendly,Pixel col)
|
||||
|
||||
@ -40,7 +40,6 @@ All rights reserved.
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "MonsterStrategyHelpers.h"
|
||||
#include "util.h"
|
||||
#include "FallingDebris.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
INCLUDE_game
|
||||
@ -68,7 +67,7 @@ DEFINE_STRATEGY(RUN_TOWARDS)
|
||||
if(desiredTargetLine.length()>=ConfigInt("MaxDistance")/100.f*24){
|
||||
//Trim to max distance desired.
|
||||
m.target=desiredTargetLine.rpoint(ConfigInt("MaxDistance")/100.f*24);
|
||||
} else {
|
||||
}else{
|
||||
m.target=desiredTargetLine.upoint(1.2f);
|
||||
}
|
||||
m.SetState(State::MOVE_TOWARDS);
|
||||
|
||||
@ -42,7 +42,6 @@ All rights reserved.
|
||||
#include "util.h"
|
||||
#include "safemap.h"
|
||||
#include "Effect.h"
|
||||
#include "FallingDebris.h"
|
||||
#include "MonsterAttribute.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
|
||||
@ -44,7 +44,6 @@ All rights reserved.
|
||||
#include "BulletTypes.h"
|
||||
#include "SoundEffect.h"
|
||||
#include "StageMaskPolygon.h"
|
||||
#include "ExpandingRing.h"
|
||||
#include <ranges>
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -53,15 +53,15 @@ ThrownProjectile::ThrownProjectile(vf2d pos,vf2d targetPos,const std::string&img
|
||||
void ThrownProjectile::OnGroundLand(){
|
||||
const HurtList hurtList{game->Hurt(pos,explodeRadius,damage,OnUpperLevel(),z,HurtType::MONSTER,HurtFlag::PLAYER_ABILITY)};
|
||||
if(explodeEffect){
|
||||
std::weak_ptr<Effect>explosionEffect{game->AddEffect(Effect{explodeEffect.value()})};
|
||||
explosionEffect.lock()->pos+=pos;
|
||||
auto explosionEffect{game->AddEffect(Effect{explodeEffect.value()})};
|
||||
explosionEffect.get().pos+=pos;
|
||||
}
|
||||
if(explodeSoundEffect)SoundEffect::PlaySFX(explodeSoundEffect.value(),pos);
|
||||
if(lingeringEffect){
|
||||
std::weak_ptr<LingeringEffect>lingerEffect{DYNAMIC_POINTER_CAST<LingeringEffect>(game->AddEffect(LingeringEffect{lingeringEffect.value()}).lock())};
|
||||
lingerEffect.lock()->posOscillator.val1+=pos;
|
||||
lingerEffect.lock()->posOscillator.val2+=pos;
|
||||
lingerEffect.lock()->pos+=pos;
|
||||
auto lingerEffect{game->AddEffect(LingeringEffect{lingeringEffect.value()})};
|
||||
lingerEffect.get().posOscillator.val1+=pos;
|
||||
lingerEffect.get().posOscillator.val2+=pos;
|
||||
lingerEffect.get().pos+=pos;
|
||||
}
|
||||
|
||||
vel={};
|
||||
|
||||
93
Adventures in Lestoria/TrailEffect.cpp
Normal file
93
Adventures in Lestoria/TrailEffect.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy 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
|
||||
#include"EffectTypes.h"
|
||||
#include"DEFINES.h"
|
||||
#include"SoundEffect.h"
|
||||
#include"AdventuresInLestoria.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_MONSTER_LIST
|
||||
|
||||
TrailEffect::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,bool additiveBlending)
|
||||
: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){}
|
||||
void TrailEffect::SetEndPos(const vf2d pos){
|
||||
this->endPos=pos;
|
||||
}
|
||||
bool TrailEffect::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<=24*size.y){
|
||||
monster->Hurt(damage,OnUpperLevel(),GetZ(),HurtFlag::DOT);
|
||||
SoundEffect::PlaySFX("Burn",monster->GetPos());
|
||||
}
|
||||
}
|
||||
hitTimer+=damageTickFrequency;
|
||||
}
|
||||
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
void TrailEffect::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](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);
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy 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 "AdventuresInLestoria.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
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<=24*size.y){
|
||||
monster->Hurt(damage,OnUpperLevel(),GetZ(),HurtFlag::DOT);
|
||||
SoundEffect::PlaySFX("Burn",monster->GetPos());
|
||||
}
|
||||
}
|
||||
hitTimer+=damageTickFrequency;
|
||||
}
|
||||
|
||||
return Effect::Update(fElapsedTime);
|
||||
}
|
||||
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](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 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 13079
|
||||
#define VERSION_BUILD 13190
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -44,7 +44,6 @@ All rights reserved.
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
#include "BlackHole.h"
|
||||
|
||||
INCLUDE_MONSTER_LIST
|
||||
INCLUDE_BULLET_LIST
|
||||
@ -146,18 +145,18 @@ void Wizard::InitializeClassAbilities(){
|
||||
SoundEffect::PlaySFX("Wizard Teleport",SoundEffect::CENTERED);
|
||||
};
|
||||
|
||||
std::vector<std::shared_ptr<Effect>>portals{game->GetEffect(EffectType::BLINK_PORTAL)};
|
||||
std::vector<std::reference_wrapper<EffectData>>portals{game->GetEffect(EffectType::BLINK_PORTAL)};
|
||||
if(portals.size()>0){
|
||||
TeleportTo(portals[0]->pos);
|
||||
portals[0]->lifetime=0.f;
|
||||
portals[0]->fadeout=0.25f;
|
||||
TeleportTo(EFF(*portals[0].get().effect).pos);
|
||||
EFF(*portals[0].get().effect).lifetime=0.f;
|
||||
EFF(*portals[0].get().effect).fadeout=0.25f;
|
||||
return true;
|
||||
}else if(p->lastPathfindingCooldown==0.f){
|
||||
if(game->TestingModeEnabled()||dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,float("Wizard.Right Click Ability.TilesMax"_I))
|
||||
&&(NoTileCollisionExistsHere()||NoPlayerCollisionWithTile())){
|
||||
if(p->HasEnchant("Blink Portal")){
|
||||
std::weak_ptr<Effect>eff{game->AddEffect(FadeInOutEffect{Oscillator<vf2d>{p->GetPos(),p->GetPos()+vf2d{0,-6.f},0.5f},"portal.png","Blink Portal"_ENC["REACTIVATION TIME"],p->OnUpperLevel(),Oscillator<vf2d>{{0.9f,0.9f},{1.1f,1.1f},0.5f},vf2d{},Oscillator<Pixel>{WHITE,Pixel(0x50196f),0.5f},0.f,0.f},true)};
|
||||
eff.lock()->SetType(EffectType::BLINK_PORTAL);
|
||||
auto eff{game->AddEffect(FadeInOutEffect{Oscillator<vf2d>{p->GetPos(),p->GetPos()+vf2d{0,-6.f},0.5f},"portal.png","Blink Portal"_ENC["REACTIVATION TIME"],p->OnUpperLevel(),Oscillator<vf2d>{{0.9f,0.9f},{1.1f,1.1f},0.5f},vf2d{},Oscillator<Pixel>{WHITE,Pixel(0x50196f),0.5f},0.f,0.f},true)};
|
||||
eff.get().SetType(EffectType::BLINK_PORTAL);
|
||||
}
|
||||
TeleportTo(teleportPoint);
|
||||
p->lastPathfindingCooldown=0.1f;
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user