Update effects containers to use shared pointers instead of reference wrappers for upcoming ThunderOrb referencing code requirements with LightningBolt effects. Release Build 13018.
Some checks are pending
Emscripten Build / Build_and_Deploy_Web_Build (push) Waiting to run
Some checks are pending
Emscripten Build / Build_and_Deploy_Web_Build (push) Waiting to run
This commit is contained in:
parent
c0686783d4
commit
9d969bcca8
@ -810,22 +810,19 @@ void AiL::UpdateCamera(float fElapsedTime){
|
||||
}
|
||||
|
||||
void AiL::UpdateEffects(float fElapsedTime){
|
||||
for(auto it=EMITTER_LIST.begin();it!=EMITTER_LIST.end();++it){
|
||||
auto ptr=(*it).get();
|
||||
ptr->Update(fElapsedTime);
|
||||
}
|
||||
for(std::vector<std::unique_ptr<Effect>>::iterator it=backgroundEffects.begin();it!=backgroundEffects.end();++it){
|
||||
Effect*e=(*it).get();
|
||||
e->Update(fElapsedTime);
|
||||
}
|
||||
for(std::vector<std::unique_ptr<Effect>>::iterator it=foregroundEffects.begin();it!=foregroundEffects.end();++it){
|
||||
Effect*e=(*it).get();
|
||||
e->Update(fElapsedTime);
|
||||
}
|
||||
std::ranges::for_each(EMITTER_LIST,[&fElapsedTime](const std::unique_ptr<IEmitter>&emitter){
|
||||
emitter->Update(fElapsedTime);
|
||||
});
|
||||
std::ranges::for_each(backgroundEffects,[&fElapsedTime](const std::shared_ptr<Effect>&effect){
|
||||
effect->Update(fElapsedTime);
|
||||
});
|
||||
std::ranges::for_each(foregroundEffects,[&fElapsedTime](const std::shared_ptr<Effect>&effect){
|
||||
effect->Update(fElapsedTime);
|
||||
});
|
||||
|
||||
std::erase_if(EMITTER_LIST,[](std::unique_ptr<IEmitter>&e){return e->dead;});
|
||||
std::erase_if(backgroundEffects,[](std::unique_ptr<Effect>&e){return e->dead;});
|
||||
std::erase_if(foregroundEffects,[](std::unique_ptr<Effect>&e){return e->dead;});
|
||||
std::erase_if(backgroundEffects,[](std::shared_ptr<Effect>&e){return e->dead;});
|
||||
std::erase_if(foregroundEffects,[](std::shared_ptr<Effect>&e){return e->dead;});
|
||||
std::erase_if(DAMAGENUMBER_LIST,[](std::shared_ptr<DamageNumber>&n){return n->IsDead();});
|
||||
|
||||
for(auto it=foregroundEffectsToBeInserted.begin();it!=foregroundEffectsToBeInserted.end();++it){
|
||||
@ -989,8 +986,8 @@ void AiL::PopulateRenderLists(){
|
||||
std::ranges::sort(MONSTER_LIST,[](std::shared_ptr<Monster>&m1,std::shared_ptr<Monster>&m2){return m1->GetPos().y<m2->GetPos().y;});
|
||||
std::ranges::sort(ItemDrop::drops,[](ItemDrop&id1,ItemDrop&id2){return id1.GetPos().y<id2.GetPos().y;});
|
||||
std::ranges::sort(BULLET_LIST,[](std::unique_ptr<IBullet>&b1,std::unique_ptr<IBullet>&b2){return b1->pos.y<b2->pos.y;});
|
||||
std::ranges::sort(foregroundEffects,[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
|
||||
std::ranges::sort(backgroundEffects,[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
|
||||
std::ranges::sort(foregroundEffects,[](std::shared_ptr<Effect>&e1,std::shared_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
|
||||
std::ranges::sort(backgroundEffects,[](std::shared_ptr<Effect>&e1,std::shared_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
|
||||
}
|
||||
|
||||
void AiL::RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos){
|
||||
@ -1066,10 +1063,10 @@ 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();})};
|
||||
auto foregroundEffectsUpper{foregroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return effect->OnUpperLevel();})};
|
||||
auto foregroundEffectsLower{foregroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
|
||||
auto backgroundEffectsUpper{backgroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return effect->OnUpperLevel();})};
|
||||
auto backgroundEffectsLower{backgroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
|
||||
auto foregroundEffectsUpper{foregroundEffects|std::views::filter([](const std::shared_ptr<Effect>&effect){return effect->OnUpperLevel();})};
|
||||
auto foregroundEffectsLower{foregroundEffects|std::views::filter([](const std::shared_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
|
||||
auto backgroundEffectsUpper{backgroundEffects|std::views::filter([](const std::shared_ptr<Effect>&effect){return effect->OnUpperLevel();})};
|
||||
auto backgroundEffectsLower{backgroundEffects|std::views::filter([](const std::shared_ptr<Effect>&effect){return !effect->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
|
||||
@ -1115,8 +1112,9 @@ 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(std::make_unique<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(std::make_unique<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});
|
||||
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)});
|
||||
player->poisonArrowLastParticleTimer=0.15f;
|
||||
}
|
||||
|
||||
@ -1547,7 +1545,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
m.Draw();
|
||||
++monstersBeforeLowerIt;
|
||||
}
|
||||
for(std::unique_ptr<Effect>&e:backgroundEffectsLower){
|
||||
for(std::shared_ptr<Effect>&e:backgroundEffectsLower){
|
||||
e->_Draw();
|
||||
}
|
||||
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
|
||||
@ -1578,7 +1576,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
for(std::unique_ptr<IBullet>&b:bulletsLower){
|
||||
b->_Draw();
|
||||
}
|
||||
for(std::unique_ptr<Effect>&e:foregroundEffectsLower){
|
||||
for(std::shared_ptr<Effect>&e:foregroundEffectsLower){
|
||||
e->_Draw();
|
||||
}
|
||||
#pragma endregion
|
||||
@ -1854,7 +1852,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
m.Draw();
|
||||
++monstersBeforeUpperIt;
|
||||
}
|
||||
for(std::unique_ptr<Effect>&e:backgroundEffectsUpper){
|
||||
for(std::shared_ptr<Effect>&e:backgroundEffectsUpper){
|
||||
e->_Draw();
|
||||
}
|
||||
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
|
||||
@ -1883,7 +1881,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
for(std::unique_ptr<IBullet>&b:bulletsUpper){
|
||||
b->_Draw();
|
||||
}
|
||||
for(std::unique_ptr<Effect>&e:foregroundEffectsUpper){
|
||||
for(std::shared_ptr<Effect>&e:foregroundEffectsUpper){
|
||||
e->_Draw();
|
||||
}
|
||||
#pragma endregion
|
||||
@ -2245,22 +2243,13 @@ void AiL::RenderCooldowns(){
|
||||
drawutil::DrawAbilityTooltipAtMouseCursor(this);
|
||||
}
|
||||
|
||||
std::pair<ForegroundWrapper,BackgroundWrapper>AiL::AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect> background){
|
||||
ForegroundWrapper foregroundRef{*foreground};
|
||||
BackgroundWrapper backgroundRef{*background};
|
||||
AddEffect(std::move(background),true);
|
||||
AddEffect(std::move(foreground));
|
||||
return {foregroundRef,backgroundRef};
|
||||
std::pair<ForegroundWrapper,BackgroundWrapper>AiL::AddEffect(Effect&&foreground,Effect&&background){
|
||||
return {AddEffect(std::move(foreground)),AddEffect(std::move(background),true)};
|
||||
}
|
||||
|
||||
Effect&AiL::AddEffect(std::unique_ptr<Effect> foreground,bool back){
|
||||
ForegroundWrapper effectRef{*foreground};
|
||||
if(back){
|
||||
backgroundEffectsToBeInserted.emplace_back(std::move(foreground));
|
||||
} else {
|
||||
foregroundEffectsToBeInserted.emplace_back(std::move(foreground));
|
||||
}
|
||||
return effectRef;
|
||||
std::weak_ptr<Effect>AiL::AddEffect(Effect&&effect,bool back){
|
||||
if(back)return backgroundEffectsToBeInserted.emplace_back(std::make_shared<Effect>(effect));
|
||||
else return foregroundEffectsToBeInserted.emplace_back(std::make_shared<Effect>(effect));
|
||||
}
|
||||
|
||||
vf2d AiL::GetWorldMousePos(){
|
||||
@ -4548,23 +4537,16 @@ void AiL::AddToSpecialMarkedTargetList(std::tuple<std::weak_ptr<Monster>,StackCo
|
||||
lockOnSpecialTargets.emplace_back(markData);
|
||||
}
|
||||
|
||||
std::vector<Effect*>AiL::GetForegroundEffects()const{
|
||||
std::vector<Effect*>outputVec;
|
||||
std::for_each(foregroundEffects.begin(),foregroundEffects.end(),[&outputVec](const std::unique_ptr<Effect>&eff){outputVec.emplace_back(eff.get());});
|
||||
return outputVec;
|
||||
const std::vector<std::shared_ptr<Effect>>&AiL::GetForegroundEffects()const{
|
||||
return foregroundEffects;
|
||||
}
|
||||
std::vector<Effect*>AiL::GetBackgroundEffects()const{
|
||||
std::vector<Effect*>outputVec;
|
||||
std::for_each(backgroundEffects.begin(),backgroundEffects.end(),[&outputVec](const std::unique_ptr<Effect>&eff){outputVec.emplace_back(eff.get());});
|
||||
return outputVec;
|
||||
const std::vector<std::shared_ptr<Effect>>&AiL::GetBackgroundEffects()const{
|
||||
return backgroundEffects;
|
||||
}
|
||||
[[nodiscard]]std::vector<Effect*>AiL::GetAllEffects()const{
|
||||
std::vector<Effect*>outputVec;
|
||||
std::vector<Effect*>foregroundEffects{GetForegroundEffects()};
|
||||
std::vector<Effect*>backgroundEffects{GetBackgroundEffects()};
|
||||
std::copy(foregroundEffects.begin(),foregroundEffects.end(),std::back_inserter(outputVec));
|
||||
std::copy(backgroundEffects.begin(),backgroundEffects.end(),std::back_inserter(outputVec));
|
||||
return outputVec;
|
||||
[[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;
|
||||
}
|
||||
|
||||
void AiL::InitializeCamera(){
|
||||
@ -4631,7 +4613,6 @@ void AiL::ResetLevelStates(){
|
||||
GetPlayer()->ResetTimers();
|
||||
}
|
||||
|
||||
|
||||
void AiL::Notification::Update(const float fElapsedTime){
|
||||
time-=fElapsedTime;
|
||||
}
|
||||
@ -4652,12 +4633,10 @@ 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<Effect*>AiL::GetEffect(EffectType type){
|
||||
std::vector<Effect*>effects{GetAllEffects()};
|
||||
std::vector<Effect*>matchingEffects{};
|
||||
std::copy_if(effects.begin(),effects.end(),std::back_inserter(matchingEffects),[&type](const Effect*effect){return effect->GetType()==type;});
|
||||
return matchingEffects;
|
||||
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>();
|
||||
}
|
||||
|
||||
void AiL::PrecacheNewLevels(){
|
||||
datafile::INITIAL_SETUP_COMPLETE=false;
|
||||
datafile cacheTimestampsData;
|
||||
|
||||
@ -81,8 +81,8 @@ using HurtListItem=std::pair<std::variant<Monster*,Player*>,HurtReturnValue>;
|
||||
using HurtList=std::vector<HurtListItem>;
|
||||
using StackCount=uint8_t;
|
||||
using MarkTime=float;
|
||||
using ForegroundWrapper=std::reference_wrapper<Effect>;
|
||||
using BackgroundWrapper=std::reference_wrapper<Effect>;
|
||||
using ForegroundWrapper=std::weak_ptr<Effect>;
|
||||
using BackgroundWrapper=std::weak_ptr<Effect>;
|
||||
|
||||
enum class KnockbackCondition{
|
||||
KNOCKBACK_HURT_TARGETS, //Knockback only targets that took damage.
|
||||
@ -199,10 +199,10 @@ public:
|
||||
void RenderHud();
|
||||
void RenderMenu();
|
||||
bool MenuClicksDeactivated()const;
|
||||
std::pair<ForegroundWrapper,BackgroundWrapper>AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect>background);
|
||||
//If back is true, places the effect in the background
|
||||
Effect&AddEffect(std::unique_ptr<Effect>foreground,bool back=false);
|
||||
const std::vector<Effect*>GetEffect(EffectType type);
|
||||
std::pair<ForegroundWrapper,BackgroundWrapper>AddEffect(Effect&&foreground,Effect&&background);
|
||||
//If back is true, places the effect in the background.
|
||||
std::weak_ptr<Effect>AddEffect(Effect&&effect,bool back=false);
|
||||
const std::vector<std::shared_ptr<Effect>>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;
|
||||
@ -339,9 +339,9 @@ public:
|
||||
|
||||
void ResetLevelStates();
|
||||
|
||||
std::vector<Effect*>GetForegroundEffects()const;
|
||||
std::vector<Effect*>GetBackgroundEffects()const;
|
||||
std::vector<Effect*>GetAllEffects()const; //Foreground and background effects in one vector.
|
||||
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.
|
||||
|
||||
struct TileGroupData{
|
||||
vi2d tilePos;
|
||||
@ -354,7 +354,7 @@ public:
|
||||
void PrecacheNewLevels();
|
||||
bool savingFile=false;
|
||||
private:
|
||||
std::vector<std::unique_ptr<Effect>>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted;
|
||||
std::vector<std::shared_ptr<Effect>>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted;
|
||||
std::vector<TileRenderData*>tilesWithCollision,tilesWithoutCollision;
|
||||
std::vector<vf2d>circleCooldownPoints;
|
||||
std::vector<vf2d>squareCircleCooldownPoints;
|
||||
|
||||
@ -94,7 +94,7 @@ const vf2d Arrow::PointToBestTargetPath(const uint8_t perceptionLevel){
|
||||
BulletDestroyState Arrow::PlayerHit(Player*player)
|
||||
{
|
||||
fadeOutTime=0.2f;
|
||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25));
|
||||
game->AddEffect(Effect{player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25});
|
||||
if(poisonArrow)player->AddBuff(BuffRestorationType::OVER_TIME,BuffOverTimeType::HP_DAMAGE_OVER_TIME,"Poisonous Arrow"_ENC["POISON DURATION"],damage*("Poisonous Arrow"_ENC["POISON TICK DAMAGE"]/100.f),1.f);
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
@ -102,7 +102,7 @@ BulletDestroyState Arrow::PlayerHit(Player*player)
|
||||
BulletDestroyState Arrow::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)
|
||||
{
|
||||
fadeOutTime=0.2f;
|
||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25));
|
||||
game->AddEffect(Effect{monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25});
|
||||
if(poisonArrow)monster.AddBuff(BuffRestorationType::OVER_TIME,BuffOverTimeType::HP_DAMAGE_OVER_TIME,"Poisonous Arrow"_ENC["POISON DURATION"],damage*("Poisonous Arrow"_ENC["POISON TICK DAMAGE"]/100.f),1.f);
|
||||
if(game->GetPlayer()->HasEnchant("Burning Arrow")&&markStacksBeforeHit>0&&monster.GetBuffs(BuffType::BURNING_ARROW_BURN).size()<"Burning Arrow"_ENC["MAX BURN STACK"])monster.AddBuff(BuffType::BURNING_ARROW_BURN,BuffRestorationType::OVER_TIME,BuffOverTimeType::HP_DAMAGE_OVER_TIME,"Burning Arrow"_ENC["BURN DURATION"],game->GetPlayer()->GetAttack()*"Burning Arrow"_ENC["BURN DAMAGE"]/100.f,2.f);
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
|
||||
@ -57,5 +57,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(std::make_unique<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(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});
|
||||
}
|
||||
@ -66,7 +66,7 @@ void Bomb::Update(float fElapsedTime){
|
||||
if(fadeOutTime==0.f){
|
||||
z=0; //Force the bomb to be grounded.
|
||||
fadeOutTime=bombFadeoutTime;
|
||||
game->AddEffect(std::make_unique<BombBoom>(pos,0.f,OnUpperLevel(),vf2d{explosionRadius,explosionRadius}/12.f/1.5f/*Upscale 24x24 to 36x36*/,1.f,vf2d{},WHITE,0.f,0.f,true));
|
||||
game->AddEffect(BombBoom{pos,0.f,OnUpperLevel(),vf2d{explosionRadius,explosionRadius}/12.f/1.5f/*Upscale 24x24 to 36x36*/,1.f,vf2d{},WHITE,0.f,0.f,true});
|
||||
SoundEffect::PlaySFX("Bomb Explode",pos);
|
||||
float distToPlayer=geom2d::line<float>(pos,game->GetPlayer()->GetPos()).length();
|
||||
if(friendly){
|
||||
|
||||
@ -61,7 +61,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::optional<std::reference_wrapper<TrailEffect>>flameTrail;
|
||||
std::weak_ptr<TrailEffect>flameTrail;
|
||||
};
|
||||
|
||||
struct LightningBolt:public Bullet{
|
||||
|
||||
@ -61,7 +61,7 @@ void ChargedArrow::Update(float fElapsedTime){
|
||||
const float normalBeamRadius{12*"Ranger.Ability 2.Radius"_F/100/5};
|
||||
float laserWidth{radius/normalBeamRadius};
|
||||
|
||||
game->AddEffect(std::make_unique<Effect>(midpoint,0.1f,laserGraphic,upperLevel,vf2d{laserWidth,dist*2},0.3f,vf2d{},Pixel{192,128,238},atan2(pos.y-lastLaserPos.y,pos.x-lastLaserPos.x)+PI/2,0,true));
|
||||
game->AddEffect(Effect{midpoint,0.1f,laserGraphic,upperLevel,vf2d{laserWidth,dist*2},0.3f,vf2d{},Pixel{192,128,238},atan2(pos.y-lastLaserPos.y,pos.x-lastLaserPos.x)+PI/2,0,true});
|
||||
lastLaserPos=pos;
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,13 +87,13 @@ void DaggerSlash::Update(float fElapsedTime){
|
||||
#pragma endregion
|
||||
}
|
||||
BulletDestroyState DaggerSlash::PlayerHit(Player*player){
|
||||
game->AddEffect(std::make_unique<Effect>(pos,0,"lightning_splash_effect.png",upperLevel,player->GetSizeMult()*0.25f,0.25,vf2d{}));
|
||||
game->AddEffect(Effect{pos,0,"lightning_splash_effect.png",upperLevel,player->GetSizeMult()*0.25f,0.25,vf2d{}});
|
||||
player->Knockback(util::pointTo(sourceMonster.GetPos(),player->GetPos())*knockbackAmt);
|
||||
Deactivate();
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
BulletDestroyState DaggerSlash::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){
|
||||
game->AddEffect(std::make_unique<Effect>(pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{}));
|
||||
game->AddEffect(Effect{pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{}});
|
||||
monster.Knockback(util::pointTo(sourceMonster.GetPos(),monster.GetPos())*knockbackAmt);
|
||||
Deactivate();
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
|
||||
@ -93,13 +93,13 @@ void DaggerStab::Update(float fElapsedTime){
|
||||
#pragma endregion
|
||||
}
|
||||
BulletDestroyState DaggerStab::PlayerHit(Player*player){
|
||||
game->AddEffect(std::make_unique<Effect>(pos,0,"lightning_splash_effect.png",upperLevel,player->GetSizeMult()*0.25f,0.25,vf2d{}));
|
||||
game->AddEffect(Effect{pos,0,"lightning_splash_effect.png",upperLevel,player->GetSizeMult()*0.25f,0.25,vf2d{}});
|
||||
player->Knockback(util::pointTo(sourceMonster.GetPos(),player->GetPos())*knockbackAmt);
|
||||
Deactivate();
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
BulletDestroyState DaggerStab::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){
|
||||
game->AddEffect(std::make_unique<Effect>(pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{}));
|
||||
game->AddEffect(Effect{pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{}});
|
||||
monster.Knockback(util::pointTo(sourceMonster.GetPos(),monster.GetPos())*knockbackAmt);
|
||||
Deactivate();
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
|
||||
@ -56,8 +56,9 @@ class LightningBoltEmitter:public IEmitter{
|
||||
vf2d startPos,endPos;
|
||||
bool upperLevel;
|
||||
void DrawLightningBolt();
|
||||
void Emit()override;
|
||||
public:
|
||||
virtual ~LightningBoltEmitter()=default;
|
||||
LightningBoltEmitter(vf2d startPos,vf2d endPos,float frequency,float timer,bool upperLevel);
|
||||
void SetStartEndPos(vf2d startPos,vf2d endPos);
|
||||
void Emit()override;
|
||||
};
|
||||
@ -51,7 +51,7 @@ void EnergyBolt::Update(float fElapsedTime){
|
||||
lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime);
|
||||
if(lastParticleSpawn==0){
|
||||
lastParticleSpawn="Wizard.Auto Attack.ParticleFrequency"_F;
|
||||
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Auto Attack.ParticleLifetimeRange"_FRange,"energy_particle.png",upperLevel,"Wizard.Auto Attack.ParticleSizeRange"_FRange,"Wizard.Auto Attack.ParticleFadeoutTime"_F,vf2d{"Wizard.Auto Attack.ParticleSpeedRange"_FRange,"Wizard.Auto Attack.ParticleSpeedRange"_FRange}));
|
||||
game->AddEffect(Effect{pos,"Wizard.Auto Attack.ParticleLifetimeRange"_FRange,"energy_particle.png",upperLevel,"Wizard.Auto Attack.ParticleSizeRange"_FRange,"Wizard.Auto Attack.ParticleFadeoutTime"_F,vf2d{"Wizard.Auto Attack.ParticleSpeedRange"_FRange,"Wizard.Auto Attack.ParticleSpeedRange"_FRange}});
|
||||
}
|
||||
if(distanceTraveled>"Wizard.Auto Attack.Range"_F&&IsActivated()){
|
||||
fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F;
|
||||
@ -61,14 +61,14 @@ void EnergyBolt::Update(float fElapsedTime){
|
||||
BulletDestroyState EnergyBolt::PlayerHit(Player*player)
|
||||
{
|
||||
fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F;
|
||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F));
|
||||
game->AddEffect(Effect{player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F});
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
|
||||
BulletDestroyState EnergyBolt::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)
|
||||
{
|
||||
if(!game->GetPlayer()->HasEnchant("Piercing Bolt"))fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F;
|
||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F));
|
||||
game->AddEffect(Effect{monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F});
|
||||
if(hitList.size()==1)damage=ceil(damage*"Piercing Bolt"_ENC["MULTI TARGET DAMAGE"]/100.f);
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
|
||||
@ -103,9 +103,8 @@ void ExplosiveTrap::Detonate(){
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Effect>explodeEffect{std::make_unique<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->scaleSpd={0.125f,0.125f};
|
||||
game->AddEffect(std::move(explodeEffect));
|
||||
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};
|
||||
SoundEffect::PlaySFX("Explosion",pos);
|
||||
explosionCount--;
|
||||
if(explosionCount>0)rearmTime=0.6f;
|
||||
|
||||
@ -52,7 +52,7 @@ bool FadeInOutEffect::Update(float fElapsedTime){
|
||||
particleSpawnTimer-=fElapsedTime;
|
||||
if(particleSpawnTimer<=0.f){
|
||||
particleSpawnTimer+=originalParticleSpawnTimer;
|
||||
game->AddEffect(std::make_unique<Effect>(particleGenerator(*this)));
|
||||
game->AddEffect(Effect{particleGenerator(*this)});
|
||||
}
|
||||
}
|
||||
pos=posOscillator.Update(fElapsedTime);
|
||||
|
||||
@ -71,12 +71,12 @@ void FallingBullet::Update(float fElapsedTime){
|
||||
}
|
||||
}
|
||||
game->ProximityKnockback(pos,collisionRadius,knockbackAmt,HurtType::PLAYER|HurtType::MONSTER);
|
||||
for(int i:std::ranges::iota_view(0,30))game->AddEffect(std::make_unique<Effect>(pos-vf2d{0.f,GetZ()},util::random_range(0.05f,0.2f),"circle_outline.png",OnUpperLevel(),util::random_range(0.5f,1.f),0.2f,vf2d{util::random_range(-10.f,10.f),util::random_range(-3.f,0.f)},PixelLerp(BLACK,col,util::random(1.f)),0.f,0.f,true));
|
||||
for(int i:std::ranges::iota_view(0,30))game->AddEffect(Effect{pos-vf2d{0.f,GetZ()},util::random_range(0.05f,0.2f),"circle_outline.png",OnUpperLevel(),util::random_range(0.5f,1.f),0.2f,vf2d{util::random_range(-10.f,10.f),util::random_range(-3.f,0.f)},PixelLerp(BLACK,col,util::random(1.f)),0.f,0.f,true});
|
||||
Deactivate();
|
||||
}
|
||||
}else{
|
||||
if(lastTrailEffect<=0.f){
|
||||
game->AddEffect(std::make_unique<Effect>(pos-vf2d{0.f,GetZ()},util::random_range(0.05f,0.2f),"circle_outline.png",OnUpperLevel(),util::random_range(0.5f,1.f),0.2f,vf2d{util::random_range(-3.f,3.f),util::random_range(-3.f,3.f)},PixelLerp(BLACK,col,util::random(1.f)),0.f,0.f,true));
|
||||
game->AddEffect(Effect{pos-vf2d{0.f,GetZ()},util::random_range(0.05f,0.2f),"circle_outline.png",OnUpperLevel(),util::random_range(0.5f,1.f),0.2f,vf2d{util::random_range(-3.f,3.f),util::random_range(-3.f,3.f)},PixelLerp(BLACK,col,util::random(1.f)),0.f,0.f,true});
|
||||
}
|
||||
}
|
||||
indicator.Update(fElapsedTime);
|
||||
|
||||
@ -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_cast<TrailEffect&>(game->AddEffect(std::make_unique<TrailEffect>(pos,"Trail of Fire"_ENC["TRAIL DURATION"],"FlamesTexture.png","Trail of Fire"_ENC["TRAIL DAMAGE"]/100.f*game->GetPlayer()->GetAttack(),"Trail of Fire"_ENC["TRAIL TICK FREQUENCY"],upperLevel,1.f,vf2d{1.f,2.f},30000.f,Oscillator<Pixel>{{255,0,0,128},Pixel(0xE74F30),2.f},EffectType::TRAIL_OF_FIRE,true),true));
|
||||
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));
|
||||
SoundEffect::PlaySFX("Wizard Fire Bolt Shoot",SoundEffect::CENTERED);
|
||||
}
|
||||
|
||||
@ -57,33 +57,33 @@ void FireBolt::Update(float fElapsedTime){
|
||||
lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime);
|
||||
if(lastParticleSpawn==0){
|
||||
lastParticleSpawn="Wizard.Ability 1.ParticleFrequency"_F;
|
||||
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Ability 1.ParticleLifetimeRange"_FRange,"energy_particle.png",upperLevel,"Wizard.Ability 1.ParticleSizeRange"_FRange,"Wizard.Ability 1.ParticleFadeoutTime"_F,vf2d{"Wizard.Ability 1.ParticleXSpeedRange"_FRange,"Wizard.Ability 1.ParticleYSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.ParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.ParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.ParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.ParticleAlphaRange"_FRange)}));
|
||||
game->AddEffect(Effect{pos,"Wizard.Ability 1.ParticleLifetimeRange"_FRange,"energy_particle.png",upperLevel,"Wizard.Ability 1.ParticleSizeRange"_FRange,"Wizard.Ability 1.ParticleFadeoutTime"_F,vf2d{"Wizard.Ability 1.ParticleXSpeedRange"_FRange,"Wizard.Ability 1.ParticleYSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.ParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.ParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.ParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.ParticleAlphaRange"_FRange)}});
|
||||
}
|
||||
if(distanceTraveled>"Wizard.Ability 1.Max Range"_F&&IsActivated()){
|
||||
fadeOutTime="Wizard.Ability 1.BulletHitFadeoutTime"_F;
|
||||
for(int i=0;i<"Wizard.Ability 1.BulletHitExplosionParticleCount"_I;i++){
|
||||
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}));
|
||||
game->AddEffect(Effect{pos,"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}});
|
||||
}
|
||||
game->SetupWorldShake("Wizard.Ability 1.WorldShakeTime"_F);
|
||||
if(friendly)game->Hurt(pos,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*12,int("Wizard.Ability 1.BulletHitExplosionDamageMult"_F*game->GetPlayer()->GetAttack()),OnUpperLevel(),0,HurtType::MONSTER,HurtFlag::PLAYER_ABILITY);
|
||||
else game->Hurt(pos,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*12,damage,OnUpperLevel(),0,HurtType::PLAYER);
|
||||
|
||||
game->AddEffect(std::make_unique<Effect>(pos,0,"splash_effect.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*2,"Wizard.Ability 1.BulletHitExplosionFadeoutTime"_F,vf2d{},"Wizard.Ability 1.BulletHitExplosionColor"_Pixel));
|
||||
game->AddEffect(Effect{pos,0,"splash_effect.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*2,"Wizard.Ability 1.BulletHitExplosionFadeoutTime"_F,vf2d{},"Wizard.Ability 1.BulletHitExplosionColor"_Pixel});
|
||||
|
||||
SoundEffect::PlaySFX("Wizard Fire Bolt Hit",pos);
|
||||
}
|
||||
|
||||
if(flameTrail)flameTrail.value().get().SetEndPos(pos);
|
||||
if(!flameTrail.expired())flameTrail.lock()->SetEndPos(pos);
|
||||
}
|
||||
|
||||
BulletDestroyState FireBolt::PlayerHit(Player*player)
|
||||
{
|
||||
fadeOutTime="Wizard.Ability 1.BulletHitFadeoutTime"_F;
|
||||
for(int i=0;i<"Wizard.Ability 1.BulletHitExplosionParticleCount"_I;i++){
|
||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}));
|
||||
game->AddEffect(Effect{player->GetPos(),"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}});
|
||||
|
||||
game->SetupWorldShake("Wizard.Ability 1.WorldShakeTime"_F);}
|
||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,5,0.25,vf2d{},Pixel{240,120,60}));
|
||||
game->AddEffect(Effect{player->GetPos(),0,"splash_effect.png",upperLevel,5,0.25,vf2d{},Pixel{240,120,60}});
|
||||
|
||||
SoundEffect::PlaySFX("Wizard Fire Bolt Hit",pos);
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
@ -93,11 +93,11 @@ BulletDestroyState FireBolt::MonsterHit(Monster&monster,const uint8_t markStacks
|
||||
{
|
||||
fadeOutTime="Wizard.Ability 1.BulletHitFadeoutTime"_F;
|
||||
for(int i=0;i<"Wizard.Ability 1.BulletHitExplosionParticleCount"_I;i++){
|
||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}));
|
||||
game->AddEffect(Effect{monster.GetPos(),"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}});
|
||||
}
|
||||
game->SetupWorldShake("Wizard.Ability 1.WorldShakeTime"_F);
|
||||
game->Hurt(monster.GetPos(),"Wizard.Ability 1.BulletHitExplosionRange"_F/100*12,int("Wizard.Ability 1.BulletHitExplosionDamageMult"_F*game->GetPlayer()->GetAttack()),OnUpperLevel(),0,HurtType::MONSTER,HurtFlag::PLAYER_ABILITY);
|
||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*2,"Wizard.Ability 1.BulletHitExplosionFadeoutTime"_F,vf2d{},"Wizard.Ability 1.BulletHitExplosionColor"_Pixel));
|
||||
game->AddEffect(Effect{monster.GetPos(),0,"splash_effect.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*2,"Wizard.Ability 1.BulletHitExplosionFadeoutTime"_F,vf2d{},"Wizard.Ability 1.BulletHitExplosionColor"_Pixel});
|
||||
|
||||
SoundEffect::PlaySFX("Wizard Fire Bolt Hit",pos);
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
|
||||
@ -183,7 +183,7 @@ DEFINE_STRATEGY(GHOST_OF_PIRATE_CAPTAIN)
|
||||
m.F(A::TOSS_COIN_WAIT_TIMER)=ConfigFloat("Coin Toss Pause Time");
|
||||
m.V(A::TOSS_COIN_TARGET)=game->GetPlayer()->GetPos();
|
||||
const bool OnLastCursePhase{Config("Curse Thresholds").GetValueCount()==m.I(A::CURSE_THRESHOLD_ARRAY_IND)};
|
||||
if(!OnLastCursePhase)game->AddEffect(std::make_unique<FlipCoinEffect>(Oscillator<vf2d>{m.GetPos(),m.V(A::TOSS_COIN_TARGET),1.f/m.F(A::TOSS_COIN_WAIT_TIMER)/2.f},ConfigFloat("Coin Toss Rise Amount"),m.F(A::TOSS_COIN_WAIT_TIMER),"coin.png",m.OnUpperLevel(),3.f));
|
||||
if(!OnLastCursePhase)game->AddEffect(FlipCoinEffect{Oscillator<vf2d>{m.GetPos(),m.V(A::TOSS_COIN_TARGET),1.f/m.F(A::TOSS_COIN_WAIT_TIMER)/2.f},ConfigFloat("Coin Toss Rise Amount"),m.F(A::TOSS_COIN_WAIT_TIMER),"coin.png",m.OnUpperLevel(),3.f});
|
||||
|
||||
#pragma region Determine a hiding spot
|
||||
const auto&hidingSpots{game->GetActiveZonesForCurrentMap().at("Hiding Spot")};
|
||||
|
||||
@ -48,7 +48,7 @@ void GhostSaber::Update(float fElapsedTime){
|
||||
distFromTarget+=expandSpd*fElapsedTime;
|
||||
if(particleTimer<=0.f){
|
||||
particleTimer+=0.05f;
|
||||
game->AddEffect(std::make_unique<ShineEffect>(pos,0.1f,0.1f,"pixel.png",2.f,vf2d{},Pixel{239,215,98,192},util::random(2*PI),0.f,true));
|
||||
game->AddEffect(ShineEffect{pos,0.1f,0.1f,"pixel.png",2.f,vf2d{},Pixel{239,215,98,192},util::random(2*PI),0.f,true});
|
||||
}
|
||||
rot+=rotSpd*fElapsedTime;
|
||||
if(!attachedMonster.expired()){
|
||||
|
||||
@ -74,7 +74,7 @@ DEFINE_STRATEGY(GIANT_OCTOPUS)
|
||||
m.SetStrategyDeathFunction([](GameEvent&event,Monster&m,const StrategyName strategy){
|
||||
std::string takoyakiImgDir{"item_img_directory"_S+"Takoyaki.png"};
|
||||
if(!GFX.count(takoyakiImgDir))ERR(std::format("WARNING! Could not find item image {}",takoyakiImgDir));
|
||||
game->AddEffect(std::make_unique<Effect>(m.GetPos(),INFINITE,"item_img_directory"_S+"Takoyaki.png",m.OnUpperLevel(),1.f,0.f,vf2d{4.f,4.f},vf2d{},WHITE));
|
||||
game->AddEffect(Effect{m.GetPos(),INFINITE,"item_img_directory"_S+"Takoyaki.png",m.OnUpperLevel(),1.f,0.f,vf2d{4.f,4.f},vf2d{},WHITE});
|
||||
m.SetLifetime(4.f);
|
||||
SETPHASE(DEAD);
|
||||
return false;
|
||||
|
||||
@ -51,8 +51,8 @@ void InkBullet::Update(float fElapsedTime){
|
||||
else if(GetAliveTime()>=30.f)ERR(std::format("WARNING! An Ink Bullet did not resolve to target position {} in time! Last reported pos: {}! THE DISTANCE THRESHOLD FOR INK EXPLOSIONS IS LIKELY TOO HIGH! THIS SHOULD NOT BE HAPPENING!",targetPos.str(),pos.str())); //NOTE: THIS SHOULD NOT BE HAPPENING! If this does, then we probably just set the distance threshold WAY TOO LOW! Let's crash for now.
|
||||
}
|
||||
void InkBullet::Splat(){
|
||||
game->AddEffect(std::make_unique<Effect>(pos,ANIMATION_DATA["inkbubble_explode.png"].GetTotalAnimationDuration(),"inkbubble_explode.png",OnUpperLevel(),vf2d{1.f,1.f},0.f,vf2d{},WHITE,0.f,0.f,additiveBlending));
|
||||
game->AddEffect(std::make_unique<Ink>(pos,inkPuddleRadius,inkPuddleLifetime,inkSlowdownDuration,inkSlowdownPct,0.4f,0.4f,vf2d{1.f,1.f},WHITE,OnUpperLevel(),int(util::random_range(0,4.f))*PI/2),true);
|
||||
game->AddEffect(Effect{pos,ANIMATION_DATA["inkbubble_explode.png"].GetTotalAnimationDuration(),"inkbubble_explode.png",OnUpperLevel(),vf2d{1.f,1.f},0.f,vf2d{},WHITE,0.f,0.f,additiveBlending});
|
||||
game->AddEffect(Ink{pos,inkPuddleRadius,inkPuddleLifetime,inkSlowdownDuration,inkSlowdownPct,0.4f,0.4f,vf2d{1.f,1.f},WHITE,OnUpperLevel(),int(util::random_range(0,4.f))*PI/2},true);
|
||||
lifetime=0.f;
|
||||
}
|
||||
BulletDestroyState InkBullet::PlayerHit(Player*player){
|
||||
|
||||
@ -63,7 +63,7 @@ void LargeStone::Update(float fElapsedTime){
|
||||
for(int i=0;i<100;i++){
|
||||
const float randomDir{util::random(2*PI)};
|
||||
|
||||
game->AddEffect(std::make_unique<FallEffect>(pos+vf2d{radius,randomDir}.cart(),0.f,"circle.png",OnUpperLevel(),vf2d{1.5f,1.5f}*util::random(2.f),util::random(1.f),vf2d{vf2d{radius,randomDir}.cart().x,-util::random(30.f)-20.f},BLACK));
|
||||
game->AddEffect(FallEffect{pos+vf2d{radius,randomDir}.cart(),0.f,"circle.png",OnUpperLevel(),vf2d{1.5f,1.5f}*util::random(2.f),util::random(1.f),vf2d{vf2d{radius,randomDir}.cart().x,-util::random(30.f)-20.f},BLACK});
|
||||
}
|
||||
|
||||
const HurtList pillarList{game->HurtMonsterType(pos,radius,3,OnUpperLevel(),GetZ(),"Stone Golem Pillar")};
|
||||
|
||||
@ -60,16 +60,16 @@ void LightningBolt::Update(float fElapsedTime){
|
||||
uint8_t brightness=uint8_t("Wizard.Ability 2.ParticleColorRange"_FRange);
|
||||
switch(util::random()%4){
|
||||
case 0:{
|
||||
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part1.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
|
||||
game->AddEffect(Effect{pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part1.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}});
|
||||
}break;
|
||||
case 1:{
|
||||
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part2.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
|
||||
game->AddEffect(Effect{pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part2.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}});
|
||||
}break;
|
||||
case 2:{
|
||||
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part3.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
|
||||
game->AddEffect(Effect{pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part3.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}});
|
||||
}break;
|
||||
case 3:{
|
||||
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part4.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
|
||||
game->AddEffect(Effect{pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part4.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}});
|
||||
}break;
|
||||
}
|
||||
}
|
||||
@ -80,7 +80,7 @@ void LightningBolt::Update(float fElapsedTime){
|
||||
|
||||
BulletDestroyState LightningBolt::PlayerHit(Player*player){
|
||||
fadeOutTime="Wizard.Ability 2.BulletFadeoutTime"_F;
|
||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,player->GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange));
|
||||
game->AddEffect(Effect{player->GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,player->GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange});
|
||||
|
||||
SoundEffect::PlaySFX("Wizard Lightning Bolt Hit",pos);
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
@ -88,7 +88,7 @@ BulletDestroyState LightningBolt::PlayerHit(Player*player){
|
||||
|
||||
BulletDestroyState LightningBolt::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){
|
||||
fadeOutTime="Wizard.Ability 2.BulletFadeoutTime"_F;
|
||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange));
|
||||
game->AddEffect(Effect{monster.GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange});
|
||||
|
||||
LightningBolt::ApplyLightningShock(monster,monster.OnUpperLevel());
|
||||
|
||||
@ -111,7 +111,7 @@ void LightningBolt::ApplyLightningShock(const Monster&monster,const bool onUpper
|
||||
if(chainLightningRepeatCount>0)lightningChainDamage=int(game->GetPlayer()->GetAttack()*"Chain Lightning"_ENC["SHOCK DAMAGE"]/100.f);
|
||||
if(m->Hurt(lightningChainDamage,onUpperLevel,0,HurtFlag::PLAYER_ABILITY)){
|
||||
EMITTER_LIST.emplace_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m->GetPos(),"Wizard.Ability 2.LightningChainFrequency"_F,"Wizard.Ability 2.LightningChainLifetime"_F,onUpperLevel)));
|
||||
game->AddEffect(std::make_unique<Effect>(m->GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"lightning_splash_effect.png",onUpperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange));
|
||||
game->AddEffect(Effect{m->GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"lightning_splash_effect.png",onUpperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange});
|
||||
int chainLightningRepeat{};
|
||||
if(chainLightningRepeatCount>0)chainLightningRepeat=chainLightningRepeatCount-1;
|
||||
else if(game->GetPlayer()->HasEnchant("Chain Lightning")&&chainLightningRepeatCount==ORIGINAL_BOLT)chainLightningRepeat=int("Chain Lightning"_ENC["REPEAT COUNT"]);
|
||||
|
||||
@ -59,7 +59,7 @@ void LightningBoltEmitter::DrawLightningBolt(){
|
||||
float targetDist=lineToTarget.length()*util::random(0.5f);
|
||||
targetAngle+=util::random((PI/2))-PI/4;
|
||||
geom2d::line<float>lightningLine=geom2d::line<float>(currentPos,currentPos+vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist});
|
||||
game->AddEffect(std::make_unique<Effect>(lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},0.2f,vf2d{},WHITE,targetAngle,0,true));
|
||||
game->AddEffect(Effect{lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},0.2f,vf2d{},WHITE,targetAngle,0,true});
|
||||
int iterations=1;
|
||||
currentPos+=vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist};
|
||||
while(iterations<MAX_ITERATIONS&&geom2d::line<float>(currentPos,endPos).length()>1){
|
||||
@ -68,7 +68,7 @@ void LightningBoltEmitter::DrawLightningBolt(){
|
||||
float targetDist=lineToTarget.length()*util::random(0.5f);
|
||||
targetAngle+=util::random((PI/2))-PI/4;
|
||||
geom2d::line<float>lightningLine=geom2d::line<float>(currentPos,currentPos+vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist});
|
||||
game->AddEffect(std::make_unique<Effect>(lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},0.2f,vf2d{},WHITE,targetAngle,0,true));
|
||||
game->AddEffect(Effect{lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2f},0.2f,vf2d{},WHITE,targetAngle,0,true});
|
||||
currentPos+=vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist};
|
||||
iterations++;
|
||||
}
|
||||
|
||||
@ -127,17 +127,17 @@ bool Meteor::Update(float fElapsedTime){
|
||||
float randomAngle="Wizard.Ability 3.MeteorImpactParticleAngleRange"_FRange;
|
||||
float randomRange=100*size.x*(1-util::random("Wizard.Ability 3.MeteorImpactParticleRandomVariance"_F))*(1-util::random("Wizard.Ability 3.MeteorImpactParticleRandomVariance"_F));
|
||||
vf2d effectPos=vf2d{cos(randomAngle),sin(randomAngle)}*randomRange+meteorOffset;
|
||||
game->AddEffect(std::make_unique<Effect>(effectPos,0,"circle.png",OnUpperLevel(),vf2d{util::random(2)+1,util::random(3)+1},util::random(3)+1,vf2d{util::random(10)-5,-util::random(20)-5},Pixel{uint8_t(randomColorTintR),uint8_t(randomColorTintG),uint8_t(randomColorTintB),uint8_t("Wizard.Ability 3.MeteorImpactParticleAlphaRange"_FRange)},0,0,true),effectPos.y<meteorOffset.y);
|
||||
game->AddEffect(Effect{effectPos,0,"circle.png",OnUpperLevel(),vf2d{util::random(2)+1,util::random(3)+1},util::random(3)+1,vf2d{util::random(10)-5,-util::random(20)-5},Pixel{uint8_t(randomColorTintR),uint8_t(randomColorTintG),uint8_t(randomColorTintB),uint8_t("Wizard.Ability 3.MeteorImpactParticleAlphaRange"_FRange)},0,0,true},effectPos.y<meteorOffset.y);
|
||||
}
|
||||
#define PLAYER_CASES default
|
||||
switch(setting){
|
||||
case SKELETON_MAGE:{
|
||||
game->Hurt(pos,meteorRadius/1.25f,damage.first*damageMult,OnUpperLevel(),0,HurtType::PLAYER);
|
||||
game->AddEffect(std::make_unique<PulsatingFire>(pos,fireRingLifetime,meteorRadius/1.25f,"fire_ring1.png",OnUpperLevel(),damage.second,PulsatingFire::SKELETON_MAGE,vf2d{meteorRadius/16,meteorRadius/16},"Wizard.Ability 3.FireRingFadeoutTime"_F),true);
|
||||
game->AddEffect(PulsatingFire{pos,fireRingLifetime,meteorRadius/1.25f,"fire_ring1.png",OnUpperLevel(),damage.second,PulsatingFire::SKELETON_MAGE,vf2d{meteorRadius/16,meteorRadius/16},"Wizard.Ability 3.FireRingFadeoutTime"_F},true);
|
||||
}break;
|
||||
PLAYER_CASES:{ //Default cases are player cases. Handle all other enemy cases in their own statements.
|
||||
game->Hurt(pos,meteorRadius,damage.first*damageMult,OnUpperLevel(),0,HurtType::MONSTER,HurtFlag::PLAYER_ABILITY);
|
||||
game->AddEffect(std::make_unique<PulsatingFire>(pos,fireRingLifetime,meteorRadius,"fire_ring1.png",OnUpperLevel(),damage.second,PulsatingFire::PLAYER,vf2d{meteorRadius/12,meteorRadius/12},"Wizard.Ability 3.FireRingFadeoutTime"_F),true);
|
||||
game->AddEffect(PulsatingFire{pos,fireRingLifetime,meteorRadius,"fire_ring1.png",OnUpperLevel(),damage.second,PulsatingFire::PLAYER,vf2d{meteorRadius/12,meteorRadius/12},"Wizard.Ability 3.FireRingFadeoutTime"_F},true);
|
||||
}break;
|
||||
}
|
||||
#undef PLAYER_CASES
|
||||
|
||||
@ -1191,7 +1191,7 @@ void Monster::OnDeath(){
|
||||
|
||||
if(strategyDeathFunc)GameEvent::AddEvent(std::make_unique<MonsterStrategyGameEvent>(strategyDeathFunc,*this,MONSTER_DATA[name].GetAIStrategy()));
|
||||
|
||||
if(game->GetPlayer()->HasEnchant("Reaper of Souls"))game->AddEffect(std::make_unique<MonsterSoul>(GetPos(),0.3f,GetSizeMult(),vf2d{},WHITE,0.f,0.f,false));
|
||||
if(game->GetPlayer()->HasEnchant("Reaper of Souls"))game->AddEffect(MonsterSoul{GetPos(),0.3f,GetSizeMult(),vf2d{},WHITE,0.f,0.f,false});
|
||||
if(game->GetPlayer()->HasEnchant("Bloodlust")&&game->GetPlayer()->GetBuffs(BuffType::ADRENALINE_RUSH).size()>0){
|
||||
Buff&adrenalineRushBuff{game->GetPlayer()->EditBuff(BuffType::ADRENALINE_RUSH,0)};
|
||||
adrenalineRushBuff.lifetime+="Bloodlust"_ENC["BUFF TIMER INCREASE"];
|
||||
@ -1226,7 +1226,7 @@ void Monster::OnDeath(){
|
||||
float fadeInTime{i*0.05f};
|
||||
float fadeOutTime{0.5f+i*0.05f};
|
||||
float effectSize{util::random(0.2f)};
|
||||
game->AddEffect(std::make_unique<Effect>(geom2d::line<float>(GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{100,0,155,uint8_t(util::random_range(0,120))},0.f,0.f),true);
|
||||
game->AddEffect(Effect{geom2d::line<float>(GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{100,0,155,uint8_t(util::random_range(0,120))},0.f,0.f},true);
|
||||
}
|
||||
SoundEffect::PlaySFX("Curse of Pain",m->GetPos());
|
||||
}
|
||||
@ -1245,9 +1245,8 @@ void Monster::OnDeath(){
|
||||
|
||||
float targetScale{radius/24};
|
||||
float startingScale{GetCollisionRadius()/24};
|
||||
std::unique_ptr<Effect>explodeEffect{std::make_unique<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)};
|
||||
explodeEffect->scaleSpd={(targetScale-startingScale)/ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration(),(targetScale-startingScale)/ANIMATION_DATA["explosionframes.png"].GetTotalAnimationDuration()};
|
||||
game->AddEffect(std::move(explodeEffect));
|
||||
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()};
|
||||
SoundEffect::PlaySFX("Explosion",pos);
|
||||
#pragma endregion
|
||||
}
|
||||
@ -1792,7 +1791,7 @@ const float Monster::GetHastePct()const{
|
||||
void Monster::CastAbility(const MonsterAbilityData&data,const vf2d pos){
|
||||
currentCast=CastInfo{.name=data.name,.castTimer=data.castTime,.castTotalTime=data.castTime,.castPos=(pos==vf2d{}?game->GetPlayer()->GetPos():pos),.mpCost=data.mpCost,.castRadius=data.radius};
|
||||
PerformAnimation("CASTING");
|
||||
if(currentCast->castRadius)game->AddEffect(std::make_unique<Effect>(currentCast->castPos,currentCast->castTotalTime,"aiming_target.png",upperLevel,(*currentCast->castRadius*2/100)*vf2d{1.f,1.f},0.5f,vf2d{},Pixel{247,183,82,128},0.f,0.f,true),true);
|
||||
if(currentCast->castRadius)game->AddEffect(Effect{currentCast->castPos,currentCast->castTotalTime,"aiming_target.png",upperLevel,(*currentCast->castRadius*2/100)*vf2d{1.f,1.f},0.5f,vf2d{},Pixel{247,183,82,128},0.f,0.f,true},true);
|
||||
}
|
||||
|
||||
void Monster::PerformSpell(const CastInfo&castData){
|
||||
|
||||
@ -9,7 +9,7 @@ INCLUDE_game
|
||||
|
||||
std::unordered_map<std::string_view,std::function<MonsterAbility::SpellSucceededResult(SpellName,CastPos,CasterMonster&,const StrategyName&)>>MonsterAbility::SPELLS{
|
||||
{"Meteor",[](SpellName spellName,CastPos pos,CasterMonster&m,const StrategyName&strategy)->SpellSucceededResult{
|
||||
game->AddEffect(std::make_unique<Meteor>(pos,3.f,m.OnUpperLevel(),Meteor::SKELETON_MAGE,std::pair<MeteorDamage,PulsatingFireDamage>{int(m.GetAttack()*ConfigFloat("Meteor Damage Mult")),int(m.GetAttack()*ConfigFloat("Fire Ring Damage Mult"))},"Wizard.Ability 3.MeteorFadeoutTime"_F));
|
||||
game->AddEffect(Meteor{pos,3.f,m.OnUpperLevel(),Meteor::SKELETON_MAGE,std::pair<MeteorDamage,PulsatingFireDamage>{int(m.GetAttack()*ConfigFloat("Meteor Damage Mult")),int(m.GetAttack()*ConfigFloat("Fire Ring Damage Mult"))},"Wizard.Ability 3.MeteorFadeoutTime"_F});
|
||||
return SpellSucceededResult::SPELL_COMPLETED;
|
||||
}},
|
||||
{"Fire Bolt",[](SpellName spellName,CastPos pos,CasterMonster&m,const StrategyName&strategy)->SpellSucceededResult{
|
||||
@ -17,7 +17,7 @@ std::unordered_map<std::string_view,std::function<MonsterAbility::SpellSucceeded
|
||||
return SpellSucceededResult::SPELL_COMPLETED;
|
||||
}},
|
||||
{"Blizzard",[](SpellName spellName,CastPos pos,CasterMonster&m,const StrategyName&strategy)->SpellSucceededResult{
|
||||
game->AddEffect(std::make_unique<Blizzard>(pos,ConfigPixels("Blizzard Radius"),ConfigFloat("Blizzard Duration"),m.GetAttack()*ConfigFloat("Blizzard Tick Damage Mult"),ConfigFloat("Blizzard Tick Rate"),std::pair<MinScale,MaxScale>{1.f,2.f},0.05f,m.OnUpperLevel(),NON_FRIENDLY));
|
||||
game->AddEffect(Blizzard{pos,ConfigPixels("Blizzard Radius"),ConfigFloat("Blizzard Duration"),int(m.GetAttack()*ConfigFloat("Blizzard Tick Damage Mult")),ConfigFloat("Blizzard Tick Rate"),std::pair<MinScale,MaxScale>{1.f,2.f},0.05f,m.OnUpperLevel(),NON_FRIENDLY});
|
||||
return SpellSucceededResult::SPELL_COMPLETED;
|
||||
}},
|
||||
{"Freeze Ground",[](SpellName spellName,CastPos pos,CasterMonster&m,const StrategyName&strategy)->SpellSucceededResult{
|
||||
@ -32,7 +32,7 @@ std::unordered_map<std::string_view,std::function<MonsterAbility::SpellSucceeded
|
||||
.stackRemovalRate=ConfigFloat("Freeze Ground Stack Removal Rate"),
|
||||
.lifetime=ConfigFloat("Freeze Ground Lifetime"),
|
||||
};
|
||||
game->AddEffect(std::make_unique<FreezeGround>(pos,ConfigFloat("Freeze Ground Lifetime"),m.GetAttack(),settings,m.OnUpperLevel(),NON_FRIENDLY),true);
|
||||
game->AddEffect(FreezeGround{pos,ConfigFloat("Freeze Ground Lifetime"),m.GetAttack(),settings,m.OnUpperLevel(),NON_FRIENDLY},true);
|
||||
return SpellSucceededResult::SPELL_COMPLETED;
|
||||
}},
|
||||
{"Speed Up",[](SpellName spellName,CastPos pos,CasterMonster&m,const StrategyName&strategy)->SpellSucceededResult{
|
||||
@ -45,7 +45,7 @@ std::unordered_map<std::string_view,std::function<MonsterAbility::SpellSucceeded
|
||||
speedBoostBuff.lifetime=speedBoostBuff.originalDuration;
|
||||
for(int i:std::ranges::iota_view(0,30)){
|
||||
vf2d polarRandomCoord{util::random_range(0,24),util::degToRad(util::random(360))};
|
||||
game->AddEffect(std::make_unique<Effect>(chosenEntity.GetPos()+polarRandomCoord.cart(),util::random_range(0,3),"circle.png",chosenEntity.OnUpperLevel(),util::random_range(0.5f,1.75f)*vf2d{1,1},1.f,vf2d{0.f,-util::random_range(3.f,10.f)},PixelLerp({255,255,255,uint8_t(util::random_range(128,255))},{0,255,0,uint8_t(util::random_range(128,255))},util::random(1)),util::random(2*PI),0.f,false));
|
||||
game->AddEffect(Effect{chosenEntity.GetPos()+polarRandomCoord.cart(),util::random_range(0,3),"circle.png",chosenEntity.OnUpperLevel(),util::random_range(0.5f,1.75f)*vf2d{1,1},1.f,vf2d{0.f,-util::random_range(3.f,10.f)},PixelLerp({255,255,255,uint8_t(util::random_range(128,255))},{0,255,0,uint8_t(util::random_range(128,255))},util::random(1)),util::random(2*PI),0.f,false});
|
||||
}
|
||||
return SpellSucceededResult::SPELL_COMPLETED;
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ INCLUDE_game
|
||||
|
||||
DEFINE_STRATEGY(PIRATES_COIN)
|
||||
if(m.B(Attribute::COLLIDED_WITH_PLAYER)){
|
||||
game->AddEffect(std::make_unique<CollectCoinEffect>(game->GetPlayer(),ConfigFloat("Coin Collect Rise Amount"),ConfigFloat("Coin Rise Timer"),"coin.png",m.OnUpperLevel()),true);
|
||||
game->AddEffect(CollectCoinEffect{game->GetPlayer(),ConfigFloat("Coin Collect Rise Amount"),ConfigFloat("Coin Rise Timer"),"coin.png",m.OnUpperLevel()},true);
|
||||
game->GetPlayer()->AddBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_COIN,INFINITY,1);
|
||||
m._DealTrueDamage(m.GetHealth(),HurtFlag::NO_DAMAGE_NUMBER);
|
||||
m.SetLifetime(0.f);
|
||||
|
||||
@ -496,7 +496,7 @@ void Player::Update(float fElapsedTime){
|
||||
monsterPtr->Knockback(vf2d{knockbackAmt,knockbackDir}.cart());
|
||||
}
|
||||
#pragma endregion
|
||||
game->AddEffect(std::make_unique<Effect>(GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-front.png",upperLevel,groundSlamVisualRange,"Warrior.Ability 2.EffectFadetime"_F),std::make_unique<Effect>(GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-back.png",upperLevel,groundSlamVisualRange,"Warrior.Ability 2.EffectFadetime"_F));
|
||||
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});
|
||||
SoundEffect::PlaySFX("Warrior Ground Slam",SoundEffect::CENTERED);
|
||||
}
|
||||
if(lastAnimationFlip>0){
|
||||
|
||||
@ -55,18 +55,18 @@ void PoisonBottle::OnGroundLand(){
|
||||
float currentExplodeRadius{explodeRadius};
|
||||
if(additionalBounceCount>0)currentExplodeRadius=bounceExplodeRadius;
|
||||
|
||||
game->AddEffect(std::make_unique<Effect>(pos,0.f,"poison_pool.png",game->GetPlayer()->OnUpperLevel(),0.5f,1.2f,vf2d{poisonCircleScale,poisonCircleScale},vf2d{},WHITE,0.f,0.f,false),true);
|
||||
game->AddEffect(Effect{pos,0.f,"poison_pool.png",game->GetPlayer()->OnUpperLevel(),0.5f,1.2f,vf2d{poisonCircleScale,poisonCircleScale},vf2d{},WHITE,0.f,0.f,false},true);
|
||||
for(int i:std::ranges::iota_view(0,200)){
|
||||
float size{util::random_range(0.4f,0.8f)};
|
||||
Pixel col{PixelLerp(VERY_DARK_GREEN,DARK_GREEN,util::random(1))};
|
||||
col.a=util::random_range(60,200);
|
||||
game->AddEffect(std::make_unique<Effect>(pos+vf2d{util::random(16)*poisonCircleScale,util::random(2*PI)}.cart(),util::random_range(1.f,4.f),"circle.png",game->GetPlayer()->OnUpperLevel(),vf2d{size,size},util::random_range(0.2f,0.5f),vf2d{util::random_range(-6.f,6.f),util::random_range(-12.f,-4.f)},col));
|
||||
game->AddEffect(Effect{pos+vf2d{util::random(16)*poisonCircleScale,util::random(2*PI)}.cart(),util::random_range(1.f,4.f),"circle.png",game->GetPlayer()->OnUpperLevel(),vf2d{size,size},util::random_range(0.2f,0.5f),vf2d{util::random_range(-6.f,6.f),util::random_range(-12.f,-4.f)},col});
|
||||
}
|
||||
if(additionalBounceCount==0&&game->GetPlayer()->HasEnchant("Pooling Poison")){
|
||||
game->AddEffect(std::make_unique<LingeringEffect>(pos,"poison_pool.png","Poison Pool",bounceExplodeRadius,game->GetPlayer()->GetAttack()*"Pooling Poison"_ENC["POISON POOL DAMAGE PCT"]/100.f,"Pooling Poison"_ENC["POISON POOL DAMAGE FREQUENCY"],friendly?HurtType::MONSTER:HurtType::PLAYER,"Pooling Poison"_ENC["SPLASH LINGER TIME"],0.5f,OnUpperLevel(),poisonCircleScale,vf2d{},WHITE,0.f,0.f,false,0.05f,[pos=pos,col=col,poisonCircleScale](const Effect&self){
|
||||
game->AddEffect(LingeringEffect{pos,"poison_pool.png","Poison Pool",bounceExplodeRadius,int(game->GetPlayer()->GetAttack()*"Pooling Poison"_ENC["POISON POOL DAMAGE PCT"]/100.f),"Pooling Poison"_ENC["POISON POOL DAMAGE FREQUENCY"],friendly?HurtType::MONSTER:HurtType::PLAYER,"Pooling Poison"_ENC["SPLASH LINGER TIME"],0.5f,OnUpperLevel(),poisonCircleScale,vf2d{},WHITE,0.f,0.f,false,0.05f,[pos=pos,col=col,poisonCircleScale](const Effect&self){
|
||||
float size{util::random_range(0.4f,0.8f)};
|
||||
return Effect{pos+vf2d{util::random(16)*poisonCircleScale,util::random(2*PI)}.cart(),util::random_range(1.f,4.f),"circle.png",game->GetPlayer()->OnUpperLevel(),vf2d{size,size},util::random_range(0.2f,0.5f),vf2d{util::random_range(-6.f,6.f),util::random_range(-12.f,-4.f)},col};
|
||||
}),true);
|
||||
}},true);
|
||||
}
|
||||
|
||||
int poolDamage{damage};
|
||||
|
||||
@ -63,7 +63,7 @@ bool PulsatingFire::Update(float fElapsedTime){
|
||||
float randomRange=12*size.x*(1-util::random("Wizard.Ability 3.FireRingParticleRandomVariance"_F))*(1-util::random("Wizard.Ability 3.FireRingParticleRandomVariance"_F));
|
||||
float randomColorTintG=128*(1-util::random("Wizard.Ability 3.FireRingParticleColorGVariance"_F))*(1-util::random("Wizard.Ability 3.FireRingParticleColorGVariance"_F));
|
||||
float randomColorTint="Wizard.Ability 3.FireRingParticleColorBlueRange"_FRange;
|
||||
game->AddEffect(std::make_unique<Effect>(pos+vf2d{cos(randomAngle),sin(randomAngle)}*randomRange,0,"circle.png",OnUpperLevel(),vf2d{"Wizard.Ability 3.FireRingParticleXSizeRange"_FRange,"Wizard.Ability 3.FireRingParticleYSizeRange"_FRange},"Wizard.Ability 3.FireRingParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 3.FireRingParticleXSpeedRange"_FRange,"Wizard.Ability 3.FireRingParticleYSpeedRange"_FRange},Pixel{128,uint8_t(randomColorTintG),uint8_t(randomColorTint),uint8_t("Wizard.Ability 3.FireRingParticleAlphaRange"_FRange)}));
|
||||
game->AddEffect(Effect{pos+vf2d{cos(randomAngle),sin(randomAngle)}*randomRange,0,"circle.png",OnUpperLevel(),vf2d{"Wizard.Ability 3.FireRingParticleXSizeRange"_FRange,"Wizard.Ability 3.FireRingParticleYSizeRange"_FRange},"Wizard.Ability 3.FireRingParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 3.FireRingParticleXSpeedRange"_FRange,"Wizard.Ability 3.FireRingParticleYSpeedRange"_FRange},Pixel{128,uint8_t(randomColorTintG),uint8_t(randomColorTint),uint8_t("Wizard.Ability 3.FireRingParticleAlphaRange"_FRange)}});
|
||||
}
|
||||
lastParticleTimer="Wizard.Ability 3.FireRingParticleFreqRange"_FRange;
|
||||
}
|
||||
|
||||
@ -93,9 +93,8 @@ BulletDestroyState PurpleEnergyBall::PlayerHit(Player*player)
|
||||
if(bounceCount<=0)fadeOutTime="Witch.Auto Attack.BulletHitFadeoutTime"_F;
|
||||
else lastHitTimer=0.1f;
|
||||
Deactivate();
|
||||
std::unique_ptr<Effect>hitEffect{std::make_unique<Effect>(player->GetPos(),0,"purpleenergyball_hit.png",upperLevel,player->GetSizeMult(),"Witch.Auto Attack.SplashEffectFadeoutTime"_F,vf2d{},WHITE,util::random(2*PI),5*PI)};
|
||||
hitEffect->scaleSpd={-0.3f,-0.3f};
|
||||
game->AddEffect(std::move(hitEffect));
|
||||
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};
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
|
||||
@ -108,8 +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::unique_ptr<Effect>hitEffect{std::make_unique<Effect>(monster.GetPos(),0,"purpleenergyball_hit.png",upperLevel,monster.GetSizeMult(),"Witch.Auto Attack.SplashEffectFadeoutTime"_F,vf2d{},WHITE,util::random(2*PI),5*PI)};
|
||||
hitEffect->scaleSpd={-0.3f,-0.3f};
|
||||
game->AddEffect(std::move(hitEffect));
|
||||
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};
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
@ -157,7 +157,7 @@ DEFINE_STRATEGY(RUN_TOWARDS)
|
||||
float dist=lineToPlayer.length();
|
||||
for(int i=0;i<m.GetSizeMult()*25;i++){
|
||||
float randomDir=util::random(2*PI);
|
||||
game->AddEffect(std::make_unique<FallEffect>(m.GetPos()+vf2d{cos(randomDir),sin(randomDir)}*m.GetSizeMult()*8,util::random(1),"circle.png",m.OnUpperLevel(),vf2d{1,1},0.5,vf2d{cos(randomDir)*util::random(5),sin(randomDir)*-util::random(15)-5}*30,BLACK),true);
|
||||
game->AddEffect(FallEffect{m.GetPos()+vf2d{cos(randomDir),sin(randomDir)}*m.GetSizeMult()*8,util::random(1),"circle.png",m.OnUpperLevel(),vf2d{1,1},0.5,vf2d{cos(randomDir)*util::random(5),sin(randomDir)*-util::random(15)-5}*30,BLACK},true);
|
||||
}
|
||||
if(dist<12*m.GetSizeMult()){
|
||||
int jumpDamage=0;
|
||||
|
||||
@ -78,7 +78,7 @@ DEFINE_STRATEGY(SANDWORM)
|
||||
if(m.ReachedTargetPos()){
|
||||
m.PerformAnimation("EMERGE",game->GetPlayer()->GetPos());
|
||||
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration();
|
||||
game->AddEffect(std::make_unique<Effect>(m.GetPos(),ConfigInt("Suction Duration"),"sand_suction.png",m.OnUpperLevel(),0.25f,0.25f,ConfigFloat("Suction Animation Size")/300.f*vf2d{1.f,1.f},vf2d{},WHITE,util::random(),-PI/8),true);
|
||||
game->AddEffect(Effect{m.GetPos(),ConfigFloat("Suction Duration"),"sand_suction.png",m.OnUpperLevel(),0.25f,0.25f,ConfigFloat("Suction Animation Size")/300.f*vf2d{1.f,1.f},vf2d{},WHITE,float(util::random()),-PI/8},true);
|
||||
SETPHASE(SURFACING);
|
||||
m.F(A::SUCTION_TIMER)=ConfigFloat("Suction Duration")+0.25f;
|
||||
}
|
||||
|
||||
@ -200,7 +200,7 @@ DEFINE_STRATEGY(SLIMEKING)
|
||||
float dist=lineToPlayer.length();
|
||||
for(int i=0;i<200;i++){
|
||||
float randomDir=util::random(2*PI);
|
||||
game->AddEffect(std::make_unique<FallEffect>(m.GetPos()+vf2d{cos(randomDir),sin(randomDir)}*m.GetSizeMult()*8,util::random(1),"circle.png",m.OnUpperLevel(),vf2d{1,1},0.5,vf2d{cos(randomDir)*util::random(5),sin(randomDir)*-util::random(15)-5}*30,BLACK),true);
|
||||
game->AddEffect(FallEffect{m.GetPos()+vf2d{cos(randomDir),sin(randomDir)}*m.GetSizeMult()*8,util::random(1),"circle.png",m.OnUpperLevel(),vf2d{1,1},0.5,vf2d{cos(randomDir)*util::random(5),sin(randomDir)*-util::random(15)-5}*30,BLACK},true);
|
||||
}
|
||||
if(dist<12*m.GetSizeMult()){
|
||||
if(game->GetPlayer()->Hurt(ConfigInt("JumpAttackDamage"),m.OnUpperLevel(),m.GetZ())){
|
||||
|
||||
@ -125,7 +125,7 @@ DEFINE_STRATEGY(STONE_GOLEM)
|
||||
if(m.F(A::RESPAWN_RECOVERY_TIME)<=0.f){
|
||||
m.V(A::RESPAWN_LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||
m.SIZET(A::RESPAWN_LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
|
||||
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::RESPAWN_LOCKON_POS),ConfigFloat("Pillar Respawns.Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Pillar Respawns.Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Pillar Respawns.Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Pillar Respawns.Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Pillar Respawns.Spell Insignia Rotation Spd"))),true);
|
||||
game->AddEffect(SpellCircle{m.V(A::RESPAWN_LOCKON_POS),ConfigFloat("Pillar Respawns.Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Pillar Respawns.Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Pillar Respawns.Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Pillar Respawns.Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Pillar Respawns.Spell Insignia Rotation Spd"))},true);
|
||||
m.F(A::RESPAWN_CASTING_TIMER)=ConfigFloat("Pillar Respawns.Cast Time");
|
||||
m.I(A::RESPAWN_PHASE)=RESPAWN_PILLAR_CAST;
|
||||
}
|
||||
@ -174,7 +174,7 @@ DEFINE_STRATEGY(STONE_GOLEM)
|
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||
m.SIZET(A::LOOPING_SOUND_ID)=SoundEffect::PlayLoopingSFX("Rock Toss Cast",m.GetPos());
|
||||
m.PerformAnimation("CAST",m.GetFacingDirectionToTarget(m.V(A::LOCKON_POS)));
|
||||
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Insignia Rotation Spd"))),true);
|
||||
game->AddEffect(SpellCircle{m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Insignia Rotation Spd"))},true);
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Beginning Phase.Pillar Cast Time");
|
||||
SETPHASE(SPAWN_PILLAR_CAST);
|
||||
}
|
||||
@ -222,7 +222,7 @@ DEFINE_STRATEGY(STONE_GOLEM)
|
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||
m.PerformAnimation("TOSS ROCK CAST");
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Standard Attack.Stone Throw Cast Time");
|
||||
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Standard Attack.Stone Throw Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Insignia Rotation Spd"))),true);
|
||||
game->AddEffect(SpellCircle{m.V(A::LOCKON_POS),ConfigFloat("Standard Attack.Stone Throw Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Insignia Rotation Spd"))},true);
|
||||
|
||||
//Use acceleration equation to determine how much time it takes for the stone to land based on gravity.
|
||||
const float stoneTossTime{ConfigFloat("Standard Attack.Stone Throw Time")};
|
||||
@ -287,7 +287,7 @@ DEFINE_STRATEGY(STONE_GOLEM)
|
||||
monsterPtr->_DealTrueDamage(ConfigInt("Shockwave.Pillar Damage"));
|
||||
});
|
||||
SoundEffect::PlaySFX("Shockwave",m.GetPos());
|
||||
game->AddEffect(std::make_unique<ExpandingRing>(m.GetPos(),ConfigFloat("Shockwave.Shockwave Ring Lifetime"),"finishring.png",m.OnUpperLevel(),vf2d{ConfigFloat("Shockwave.Ring Expand Speed"),ConfigFloat("Shockwave.Ring Expand Speed")},vf2d{1.f,1.f},ConfigFloat("Shockwave.Shockwave Fadeout Time"),vf2d{},ConfigPixel("Shockwave.Shockwave Color")),true);
|
||||
game->AddEffect(ExpandingRing{m.GetPos(),ConfigFloat("Shockwave.Shockwave Ring Lifetime"),"finishring.png",m.OnUpperLevel(),vf2d{ConfigFloat("Shockwave.Ring Expand Speed"),ConfigFloat("Shockwave.Ring Expand Speed")},vf2d{1.f,1.f},ConfigFloat("Shockwave.Shockwave Fadeout Time"),vf2d{},ConfigPixel("Shockwave.Shockwave Color")},true);
|
||||
SETPHASE(STANDARD);
|
||||
game->SetWorldColor(WHITE);
|
||||
}
|
||||
@ -322,7 +322,7 @@ DEFINE_STRATEGY(STONE_GOLEM)
|
||||
|
||||
const datafile&throwPos{Config("Stone Rain.Stone Toss Initial Throw Pos")};
|
||||
|
||||
game->AddEffect(std::make_unique<RockLaunch>(m.GetPos()+vf2d{util::random_range(throwPos.GetReal(0),throwPos.GetReal(2)),util::random_range(throwPos.GetReal(1),throwPos.GetReal(3))},10.f,"rock.png",ConfigFloat("Stone Rain.Stone Toss Delay"),ConfigFloat("Stone Rain.Stone Toss Rock Size Mult"),0.1f,vf2d{0.f,-ConfigFloat("Stone Rain.Stone Toss Throw Speed")},WHITE,util::random(2*PI),0.f));
|
||||
game->AddEffect(RockLaunch{m.GetPos()+vf2d{util::random_range(throwPos.GetReal(0),throwPos.GetReal(2)),util::random_range(throwPos.GetReal(1),throwPos.GetReal(3))},10.f,"rock.png",ConfigFloat("Stone Rain.Stone Toss Delay"),ConfigFloat("Stone Rain.Stone Toss Rock Size Mult"),0.1f,vf2d{0.f,-ConfigFloat("Stone Rain.Stone Toss Throw Speed")},WHITE,util::random(2*PI),0.f});
|
||||
|
||||
if(m.I(A::STONE_TOSS_COUNT)<=0){
|
||||
SETPHASE(STONE_RAIN);
|
||||
|
||||
@ -98,7 +98,7 @@ DEFINE_STRATEGY(STONE_ELEMENTAL)
|
||||
SETPHASE(STONE_PILLAR_CAST);
|
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Stone Pillar Cast Time");
|
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Insignia Rotation Spd"))),false);
|
||||
game->AddEffect(SpellCircle{m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Insignia Rotation Spd"))},false);
|
||||
}break;
|
||||
case 1:{
|
||||
m.PerformAnimation("ROCK TOSS CAST");
|
||||
|
||||
@ -97,7 +97,7 @@ bool Thief::AutoAttack(){
|
||||
attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
|
||||
swordSwingTimer="Thief.Auto Attack.SwordAnimationSwingTime"_F;
|
||||
|
||||
game->AddEffect(std::make_unique<SwordSlash>(0.125f,"swordslash.png"s,"Thief.Auto Attack.DamageMult"_F,"Thief.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*"Thief.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection));
|
||||
game->AddEffect(SwordSlash{0.125f,"swordslash.png"s,"Thief.Auto Attack.DamageMult"_F,"Thief.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*"Thief.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection});
|
||||
|
||||
SetState(State::SWING_SWORD);
|
||||
SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED);
|
||||
@ -157,7 +157,7 @@ void Thief::InitializeClassAbilities(){
|
||||
#pragma region Thief Ability 2 (Deadly Dash)
|
||||
Thief::ability2.action=
|
||||
[](Player*p,vf2d pos={}){
|
||||
game->AddEffect(std::make_unique<ShineEffect>(p->GetPos()+vf2d{4.f,4.f},0.5f,0.5f,"shine.png",1.5f,vf2d{},WHITE,util::random(2*PI),PI/2,true));
|
||||
game->AddEffect(ShineEffect{p->GetPos()+vf2d{4.f,4.f},0.5f,0.5f,"shine.png",1.5f,vf2d{},WHITE,util::random(2*PI),PI/2,true});
|
||||
p->ApplyIframes("Thief.Ability 2.Initial Wait"_F+"Thief.Ability 2.Ending Wait"_F+"Thief.Ability 2.Completed Dash Extra Iframe Time"_F);
|
||||
SoundEffect::PlaySFX("Charge Up",p->GetPos());
|
||||
p->SetState(State::DEADLYDASH);
|
||||
@ -189,7 +189,7 @@ void Thief::InitializeClassAbilities(){
|
||||
|
||||
for(int i:std::ranges::iota_view(0,50)){
|
||||
float size{util::random_range(0.4f,0.8f)};
|
||||
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{8,util::random(2*PI)}.cart(),util::random_range(0.1f,0.4f),"circle.png",p->OnUpperLevel(),vf2d{size,size},0.3f,vf2d{util::random_range(-6.f,6.f),util::random_range(-8.f,-1.f)},PixelLerp(WHITE,GREEN,util::random(1))));
|
||||
game->AddEffect(Effect{p->GetPos()+vf2d{8,util::random(2*PI)}.cart(),util::random_range(0.1f,0.4f),"circle.png",p->OnUpperLevel(),vf2d{size,size},0.3f,vf2d{util::random_range(-6.f,6.f),util::random_range(-8.f,-1.f)},PixelLerp(WHITE,GREEN,util::random(1))});
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -41,6 +41,7 @@ All rights reserved.
|
||||
#include <ranges>
|
||||
#include "util.h"
|
||||
#include "SoundEffect.h"
|
||||
#include<memory>
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -52,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){
|
||||
Effect&explosionEffect{game->AddEffect(std::make_unique<Effect>(explodeEffect.value()))};
|
||||
explosionEffect.pos+=pos;
|
||||
std::weak_ptr<Effect>explosionEffect{game->AddEffect(Effect{explodeEffect.value()})};
|
||||
explosionEffect.lock()->pos+=pos;
|
||||
}
|
||||
if(explodeSoundEffect)SoundEffect::PlaySFX(explodeSoundEffect.value(),pos);
|
||||
if(lingeringEffect){
|
||||
LingeringEffect&lingerEffect{dynamic_cast<LingeringEffect&>(game->AddEffect(std::make_unique<LingeringEffect>(lingeringEffect.value())))};
|
||||
lingerEffect.posOscillator.val1+=pos;
|
||||
lingerEffect.posOscillator.val2+=pos;
|
||||
lingerEffect.pos+=pos;
|
||||
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;
|
||||
}
|
||||
|
||||
vel={};
|
||||
|
||||
@ -48,7 +48,13 @@ void ThunderOrb::Update(float fElapsedTime){
|
||||
lightning.SetStartEndPos(pos,lightningBoltRandomPos);
|
||||
|
||||
if((damageTickTimer-=fElapsedTime)<=0.f){
|
||||
game->Hurt(pos,settings.range/100.f*24,damage*settings.attackMult,OnUpperLevel(),GetZ(),friendly?HurtType::MONSTER:HurtType::PLAYER);
|
||||
const HurtList&hurtTargets{game->Hurt(pos,settings.range/100.f*24,damage*settings.attackMult,OnUpperLevel(),GetZ(),friendly?HurtType::MONSTER:HurtType::PLAYER)};
|
||||
|
||||
std::ranges::for_each(hurtTargets,[&lightning=lightning,&pos=pos](const auto&pair){
|
||||
Entity target{pair.first};
|
||||
lightning.SetStartEndPos(pos,target.GetPos());
|
||||
lightning.Emit();
|
||||
});
|
||||
|
||||
damageTickTimer+=settings.tickRate;
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ void Trapper::InitializeClassAbilities(){
|
||||
p->AddBuff(BuffType::SPEEDBOOST,"Trapper.Right Click Ability.Movement Speed Buff"_f[1],"Trapper.Right Click Ability.Movement Speed Buff"_f[0]/100.f);
|
||||
for(int i:std::ranges::iota_view(0,50)){
|
||||
float size{util::random_range(0.4f,0.8f)};
|
||||
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{8,util::random(2*PI)}.cart(),util::random_range(0.1f,0.4f),"circle.png",p->OnUpperLevel(),vf2d{size,size},0.3f,vf2d{util::random_range(-6.f,6.f),util::random_range(-8.f,-1.f)},PixelLerp(BLACK,RED,util::random(1))));
|
||||
game->AddEffect(Effect{p->GetPos()+vf2d{8,util::random(2*PI)}.cart(),util::random_range(0.1f,0.4f),"circle.png",p->OnUpperLevel(),vf2d{size,size},0.3f,vf2d{util::random_range(-6.f,6.f),util::random_range(-8.f,-1.f)},PixelLerp(BLACK,RED,util::random(1))});
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@ -107,7 +107,7 @@ void Trapper::InitializeClassAbilities(){
|
||||
float fadeInTime{i*0.05f};
|
||||
float fadeOutTime{0.5f+i*0.05f};
|
||||
float effectSize{util::random(0.4f)};
|
||||
game->AddEffect(std::make_unique<Effect>(geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{255,255,255,uint8_t(util::random_range(60,150))},0.f,0.f,true),true);
|
||||
game->AddEffect(Effect{geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{255,255,255,uint8_t(util::random_range(60,150))},0.f,0.f,true},true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 12989
|
||||
#define VERSION_BUILD 13018
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -94,7 +94,7 @@ bool Warrior::AutoAttack(){
|
||||
attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
|
||||
swordSwingTimer="Warrior.Auto Attack.SwordAnimationSwingTime"_F;
|
||||
|
||||
game->AddEffect(std::make_unique<SwordSlash>(0.125f,"swordslash.png"s,"Warrior.Auto Attack.DamageMult"_F,"Warrior.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*GetAttackRange()/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection));
|
||||
game->AddEffect(SwordSlash{0.125f,"swordslash.png"s,"Warrior.Auto Attack.DamageMult"_F,"Warrior.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*GetAttackRange()/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection});
|
||||
|
||||
SetState(State::SWING_SWORD);
|
||||
SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED);
|
||||
@ -124,7 +124,7 @@ void Warrior::InitializeClassAbilities(){
|
||||
#pragma region Warrior Ability 1 (Battlecry)
|
||||
Warrior::ability1.action=
|
||||
[](Player*p,vf2d pos={}){
|
||||
game->AddEffect(std::make_unique<Effect>(p->GetPos(),"Warrior.Ability 1.EffectLifetime"_F,"battlecry_effect.png",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F));
|
||||
game->AddEffect(Effect{p->GetPos(),"Warrior.Ability 1.EffectLifetime"_F,"battlecry_effect.png",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F});
|
||||
p->AddBuff(BuffType::STAT_UP,"Warrior.Ability 1.AttackUpDuration"_F,"Warrior.Ability 1.AttackIncrease"_F,{"Attack %"});
|
||||
p->AddBuff(BuffType::DAMAGE_REDUCTION,"Warrior.Ability 1.DamageReductionDuration"_F,"Warrior.Ability 1.DamageReduction"_F);
|
||||
for(std::shared_ptr<Monster>&m:MONSTER_LIST){
|
||||
|
||||
@ -50,13 +50,13 @@ void Wisp::Update(float fElapsedTime){
|
||||
}
|
||||
BulletDestroyState Wisp::PlayerHit(Player*player){
|
||||
SoundEffect::PlaySFX("Wisp Hit",player->GetPos());
|
||||
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25,vf2d{},"MonsterStrategy.Ursule.Phase 2.Wisp Color"_Pixel));
|
||||
game->AddEffect(Effect{player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25,vf2d{},"MonsterStrategy.Ursule.Phase 2.Wisp Color"_Pixel});
|
||||
fadeOutTime="MonsterStrategy.Ursule.Phase 2.Wisp Fadeout Time"_F;
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
BulletDestroyState Wisp::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){
|
||||
SoundEffect::PlaySFX("Wisp Hit",monster.GetPos());
|
||||
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25,vf2d{},"MonsterStrategy.Ursule.Phase 2.Wisp Color"_Pixel));
|
||||
game->AddEffect(Effect{monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25,vf2d{},"MonsterStrategy.Ursule.Phase 2.Wisp Color"_Pixel});
|
||||
fadeOutTime="MonsterStrategy.Ursule.Phase 2.Wisp Fadeout Time"_F;
|
||||
return BulletDestroyState::KEEP_ALIVE;
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ void Witch::InitializeClassAbilities(){
|
||||
float fadeInTime{i*0.05f};
|
||||
float fadeOutTime{0.5f+i*0.05f};
|
||||
float effectSize{util::random(0.2f)};
|
||||
game->AddEffect(std::make_unique<Effect>(geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{100,0,155,uint8_t(util::random_range(0,120))},0.f,0.f),true);
|
||||
game->AddEffect(Effect{geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{100,0,155,uint8_t(util::random_range(0,120))},0.f,0.f},true);
|
||||
}
|
||||
SoundEffect::PlaySFX("Curse of Pain",curseTarget.value().lock()->GetPos());
|
||||
return true;
|
||||
@ -189,7 +189,7 @@ void Witch::InitializeClassAbilities(){
|
||||
float fadeInTime{i*0.05f};
|
||||
float fadeOutTime{0.5f+i*0.05f};
|
||||
float effectSize{util::random_range(0.6f,1.2f)};
|
||||
game->AddEffect(std::make_unique<Effect>(geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{162,0,0,uint8_t(util::random_range(150,255))},0.f,0.f),true);
|
||||
game->AddEffect(Effect{geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{162,0,0,uint8_t(util::random_range(150,255))},0.f,0.f},true);
|
||||
}
|
||||
SoundEffect::PlaySFX("Curse of Death",curseTarget.value().lock()->GetPos());
|
||||
return true;
|
||||
|
||||
@ -141,12 +141,12 @@ void Wizard::InitializeClassAbilities(){
|
||||
p->teleportStartPosition=p->GetPos();
|
||||
p->ApplyIframes("Wizard.Right Click Ability.IframeTime"_F);
|
||||
for(int i=0;i<"Wizard.Right Click Ability.ParticleCount"_I;i++){
|
||||
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12},util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+"Wizard.Right Click Ability.ParticleLifetimeMin"_F,"circle.png",p->upperLevel,"Wizard.Right Click Ability.ParticleSize"_F,"Wizard.Right Click Ability.ParticleFadetime"_F,vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F,util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F},"Wizard.Right Click Ability.ParticleColor"_Pixel));
|
||||
game->AddEffect(Effect{p->GetPos()+vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12},util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+"Wizard.Right Click Ability.ParticleLifetimeMin"_F,"circle.png",p->upperLevel,"Wizard.Right Click Ability.ParticleSize"_F,"Wizard.Right Click Ability.ParticleFadetime"_F,vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F,util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F},"Wizard.Right Click Ability.ParticleColor"_Pixel});
|
||||
}
|
||||
SoundEffect::PlaySFX("Wizard Teleport",SoundEffect::CENTERED);
|
||||
};
|
||||
|
||||
std::vector<Effect*>portals{game->GetEffect(EffectType::BLINK_PORTAL)};
|
||||
std::vector<std::shared_ptr<Effect>>portals{game->GetEffect(EffectType::BLINK_PORTAL)};
|
||||
if(portals.size()>0){
|
||||
TeleportTo(portals[0]->pos);
|
||||
portals[0]->lifetime=0.f;
|
||||
@ -156,17 +156,17 @@ void Wizard::InitializeClassAbilities(){
|
||||
if(game->TestingModeEnabled()||dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,float("Wizard.Right Click Ability.TilesMax"_I))
|
||||
&&(NoTileCollisionExistsHere()||NoPlayerCollisionWithTile())){
|
||||
if(p->HasEnchant("Blink Portal")){
|
||||
Effect&eff{game->AddEffect(std::make_unique<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.SetType(EffectType::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);
|
||||
}
|
||||
TeleportTo(teleportPoint);
|
||||
p->lastPathfindingCooldown=0.1f;
|
||||
|
||||
if(p->HasEnchant("Black Hole")){
|
||||
Effect&blackHoleEff{game->AddEffect(std::make_unique<BlackHole>(Oscillator<vf2d>{p->GetPos(),p->GetPos()+vf2d{0,-6.f},0.75f},"blackhole.png","Black Hole"_ENC["BLACK HOLE DURATION"],p->OnUpperLevel(),Oscillator<vf2d>{{3.4f,3.4f},{3.7f,3.7f},0.75f},vf2d{},Oscillator<Pixel>{WHITE,WHITE,0.75f},util::random(2*PI),PI/3,false,0.03f,[](const Effect&self){
|
||||
game->AddEffect(BlackHole{Oscillator<vf2d>{p->GetPos(),p->GetPos()+vf2d{0,-6.f},0.75f},"blackhole.png","Black Hole"_ENC["BLACK HOLE DURATION"],p->OnUpperLevel(),Oscillator<vf2d>{{3.4f,3.4f},{3.7f,3.7f},0.75f},vf2d{},Oscillator<Pixel>{WHITE,WHITE,0.75f},util::random(2*PI),PI/3,false,0.03f,[](const Effect&self){
|
||||
vf2d particlePos{self.pos+vf2d{"Black Hole"_ENC["PULL IN RADIUS"]/100.f*24,util::random(2*PI)}.cart()};
|
||||
return Effect{particlePos,util::random_range(0.3f,0.5f),"pixel.png",self.OnUpperLevel(),util::random(2.f),0.1f,util::pointTo(particlePos,self.pos)*util::random_range(700,1000),PixelLerp(BLACK,Pixel(0x9859de),util::random(1.f)),0.f,0.f,false};
|
||||
}),true)};
|
||||
}},true);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -202,7 +202,7 @@ void Wizard::InitializeClassAbilities(){
|
||||
if(p->HasEnchant("Summon Comet")&&p->HasEnchant("Solar Flare"))meteorType=Meteor::COMET_FLARE;
|
||||
else if(p->HasEnchant("Summon Comet"))meteorType=Meteor::COMET;
|
||||
else if(p->HasEnchant("Solar Flare"))meteorType=Meteor::SOLAR_FLARE;
|
||||
game->AddEffect(std::make_unique<Meteor>(pos,3,p->OnUpperLevel(),meteorType,std::pair<MeteorDamage,PulsatingFireDamage>{p->GetAttack(),int(p->GetAttack()*"Wizard.Ability 3.FireRingDamageMult"_F)},"Wizard.Ability 3.MeteorFadeoutTime"_F));
|
||||
game->AddEffect(Meteor{pos,3,p->OnUpperLevel(),meteorType,std::pair<MeteorDamage,PulsatingFireDamage>{p->GetAttack(),int(p->GetAttack()*"Wizard.Ability 3.FireRingDamageMult"_F)},"Wizard.Ability 3.MeteorFadeoutTime"_F});
|
||||
return true;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
@ -288,7 +288,7 @@ DEFINE_STRATEGY(ZEPHY)
|
||||
float windRotationSpd=util::random(util::degToRad(15.f));
|
||||
if(!positiveWindRotation)windRotationSpd*=-1;
|
||||
|
||||
game->AddEffect(std::make_unique<ForegroundEffect>(randomScreenOffset,randomLifetime,windImageChoice,m.OnUpperLevel(),vf2d{1.f,1.f}*(util::random_range(0.25f,1.f)),1.f,randomSpeed,Pixel{randomColAmt,randomColAmt,randomColAmt,randomAlpha},util::random(2*PI),windRotationSpd,true));
|
||||
game->AddEffect(ForegroundEffect{randomScreenOffset,randomLifetime,windImageChoice,m.OnUpperLevel(),vf2d{1.f,1.f}*(util::random_range(0.25f,1.f)),1.f,randomSpeed,Pixel{randomColAmt,randomColAmt,randomColAmt,randomAlpha},util::random(2*PI),windRotationSpd,true});
|
||||
|
||||
m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Wind Attack.Wind Streak Spawn Rate");
|
||||
}
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user