Switch to storing unique pointers for the monsters list instead of objects. Added a source monster for frog tongues to remain attached to so they follow the monster that they originated from. Release Build 8734.

mac-build
sigonasr2 8 months ago
parent d85946f034
commit f9ffd026a9
  1. 68
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 8
      Adventures in Lestoria/Bear.cpp
  3. 3
      Adventures in Lestoria/BulletTypes.h
  4. 2
      Adventures in Lestoria/DEFINES.h
  5. 2
      Adventures in Lestoria/Frog.cpp
  6. 16
      Adventures in Lestoria/FrogTongue.cpp
  7. 12
      Adventures in Lestoria/LightningBolt.cpp
  8. 1
      Adventures in Lestoria/Minimap.cpp
  9. 14
      Adventures in Lestoria/Monster.cpp
  10. 24
      Adventures in Lestoria/Player.cpp
  11. 2
      Adventures in Lestoria/Version.h
  12. 18
      Adventures in Lestoria/Warrior.cpp
  13. BIN
      x64/Release/Adventures in Lestoria.exe

@ -92,7 +92,7 @@ bool _DEBUG_MAP_LOAD_INFO = false;
//360x240
vi2d WINDOW_SIZE={24*15,24*10};
safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
std::vector<Monster>MONSTER_LIST;
std::vector<std::unique_ptr<Monster>>MONSTER_LIST;
std::vector<MonsterSpawner>SPAWNER_LIST;
std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
@ -734,23 +734,23 @@ void AiL::UpdateBullets(float fElapsedTime){
b->distanceTraveled+=totalDistance/24.f*100.f;
const auto CollisionCheck=[&](){
if(b->friendly){
for(Monster&m:MONSTER_LIST){
if(geom2d::overlaps(m.Hitbox(),geom2d::circle(b->pos,b->radius))){
if(b->hitList.find(&m)==b->hitList.end()&&m.Hurt(b->damage,b->OnUpperLevel(),0)){
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(geom2d::overlaps(m->Hitbox(),geom2d::circle(b->pos,b->radius))){
if(b->hitList.find(&*m)==b->hitList.end()&&m->Hurt(b->damage,b->OnUpperLevel(),0)){
if(!b->hitsMultiple){
if(b->MonsterHit(m)){
if(b->MonsterHit(*m)){
b->dead=true;
}
return false;
}
b->hitList.insert(&m);
b->hitList.insert(&*m);
}
}
}
} else {
if(geom2d::overlaps(player->Hitbox(),geom2d::circle(b->pos,b->radius))){
if(player->Hurt(b->damage,b->OnUpperLevel(),0)){
if(b->PlayerHit(player.get())){
if(b->PlayerHit(&*player)){
b->dead=true;
}
return false;
@ -790,10 +790,10 @@ void AiL::UpdateBullets(float fElapsedTime){
}
const MonsterHurtList AiL::HurtEnemies(vf2d pos,float radius,int damage,bool upperLevel,float z)const{
MonsterHurtList hitList;
for(Monster&m:MONSTER_LIST){
if(geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m.GetPos(),12*m.GetSizeMult()))){
HurtReturnValue returnVal=m.Hurt(damage,upperLevel,z);
hitList.push_back({&m,returnVal});
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m->GetPos(),12*m->GetSizeMult()))){
HurtReturnValue returnVal=m->Hurt(damage,upperLevel,z);
hitList.push_back({&*m,returnVal});
}
}
return hitList;
@ -801,11 +801,11 @@ const MonsterHurtList AiL::HurtEnemies(vf2d pos,float radius,int damage,bool upp
const MonsterHurtList AiL::HurtEnemiesNotHit(vf2d pos,float radius,int damage,HitList&hitList,bool upperLevel,float z){
MonsterHurtList affectedList;
for(Monster&m:MONSTER_LIST){
if(!hitList.count(&m)&&geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m.GetPos(),12*m.GetSizeMult()))){
HurtReturnValue returnVal=m.Hurt(damage,upperLevel,z);
affectedList.push_back({&m,returnVal});
hitList.insert(&m);
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(!hitList.count(&*m)&&geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m->GetPos(),12*m->GetSizeMult()))){
HurtReturnValue returnVal=m->Hurt(damage,upperLevel,z);
affectedList.push_back({&*m,returnVal});
hitList.insert(&*m);
}
}
return affectedList;
@ -813,14 +813,14 @@ const MonsterHurtList AiL::HurtEnemiesNotHit(vf2d pos,float radius,int damage,Hi
const MonsterHurtList AiL::HurtEnemiesConeNotHit(vf2d pos,float radius,float angle,float sweepAngle,int damage,HitList&hitList,bool upperLevel,float z){
MonsterHurtList affectedList;
for(Monster&m:MONSTER_LIST){
if(!hitList.count(&m)&&geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m.GetPos(),12*m.GetSizeMult()))){
float angleToMonster=geom2d::line<float>{pos,m.GetPos()}.vector().polar().y;
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(!hitList.count(&*m)&&geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m->GetPos(),12*m->GetSizeMult()))){
float angleToMonster=geom2d::line<float>{pos,m->GetPos()}.vector().polar().y;
float angleDiff=util::angle_difference(angleToMonster,angle);
if(abs(angleDiff)<=sweepAngle){
HurtReturnValue returnVal=m.Hurt(damage,upperLevel,z);
affectedList.push_back({&m,returnVal});
hitList.insert(&m);
HurtReturnValue returnVal=m->Hurt(damage,upperLevel,z);
affectedList.push_back({&*m,returnVal});
hitList.insert(&*m);
}
}
}
@ -851,14 +851,14 @@ void AiL::PopulateRenderLists(){
Player*pl=GetPlayer();
pl->rendered=false;
std::sort(MONSTER_LIST.begin(),MONSTER_LIST.end(),[](Monster&m1,Monster&m2){return m1.GetPos().y<m2.GetPos().y;});
std::sort(MONSTER_LIST.begin(),MONSTER_LIST.end(),[](std::unique_ptr<Monster>&m1,std::unique_ptr<Monster>&m2){return m1->GetPos().y<m2->GetPos().y;});
std::sort(ItemDrop::drops.begin(),ItemDrop::drops.end(),[](ItemDrop&id1,ItemDrop&id2){return id1.GetPos().y<id2.GetPos().y;});
std::sort(BULLET_LIST.begin(),BULLET_LIST.end(),[](std::unique_ptr<Bullet>&b1,std::unique_ptr<Bullet>&b2){return b1->pos.y<b2->pos.y;});
std::sort(foregroundEffects.begin(),foregroundEffects.end(),[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
std::sort(backgroundEffects.begin(),backgroundEffects.end(),[](std::unique_ptr<Effect>&e1,std::unique_ptr<Effect>&e2){return e1->pos.y<e2->pos.y;});
for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){
Monster&m=*it;
Monster&m=**it;
if(m.GetPos().y<pl->GetPos().y){//This monster renders before the player does (behind the player)
if(m.OnUpperLevel()){
monstersBeforeUpper.push_back(&m);
@ -1021,8 +1021,8 @@ void AiL::RenderWorld(float fElapsedTime){
multiplierX*=(1-abs(cos(1.5f*reflectionStepTime))*"water_reflection_scale_factor"_F);
float reflectionRatioX=abs(sin(reflectionStepTime))*"water_reflection_scale_factor"_F;
RenderPlayer(player->GetPos()+vf2d{reflectionRatioX*player->GetFrame().GetSourceRect().size.x,float(player->GetFrame().GetSourceRect().size.y)-8}*player->GetSizeMult(),{multiplierX,-1});
for(Monster&m:MONSTER_LIST){
m.DrawReflection(reflectionRatioX,multiplierX);
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
m->DrawReflection(reflectionRatioX,multiplierX);
}
SetDecalMode(DecalMode::NORMAL);
}
@ -1689,8 +1689,8 @@ void AiL::RenderWorld(float fElapsedTime){
}
}
for(Monster&m:MONSTER_LIST){
m.strategyDrawOverlay(this,m,MONSTER_DATA[m.GetName()].GetAIStrategy());
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
m->strategyDrawOverlay(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy());
}
#ifdef _DEBUG
@ -2415,9 +2415,9 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
LoadingScreen::AddPhase([&](){
for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){
if(Unlock::IsUnlocked(data.unlockCondition)){
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
MONSTER_LIST.back().iframe_timer=INFINITE;
MONSTER_LIST.back().npcData=data;
MONSTER_LIST.push_back(std::make_unique<Monster>(data.spawnPos,MONSTER_DATA[data.name]));
MONSTER_LIST.back()->iframe_timer=INFINITE;
MONSTER_LIST.back()->npcData=data;
}
}
return true;
@ -3930,12 +3930,12 @@ rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filt
}
void AiL::UpdateMonsters(){
for(Monster&m:MONSTER_LIST){
m.Update(game->GetElapsedTime());
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
m->Update(game->GetElapsedTime());
}
for(Monster&m:game->monstersToBeSpawned){
size_t prevCapacity=MONSTER_LIST.capacity();
MONSTER_LIST.push_back(m);
MONSTER_LIST.push_back(std::make_unique<Monster>(m));
if(MONSTER_LIST.capacity()>prevCapacity)LOG(std::format("WARNING! The monster list has automatically reserved more space and resized to {}! This caused one potential frame where bullet/effect hitlists that stored information on what monsters were hit to potentially be hit a second time or cause monsters that should've been hit to never be hit. Consider starting with a larger default reserved size for MONSTER_LIST if your intention was to have this many monsters!",MONSTER_LIST.capacity()));
}
game->monstersToBeSpawned.clear();

@ -93,10 +93,10 @@ void Monster::STRATEGY::BEAR(Monster&m,float fElapsedTime,std::string strategy){
game->GetPlayer()->Knockback(playerDirVecNorm*ConfigFloat("Attack Knockback Amount"));
}
}
for(Monster&otherM:MONSTER_LIST){
if(!otherM.AttackAvoided(m.GetZ())&&&m!=&otherM&&geom2d::overlaps(attackCircle,otherM.Hitbox())){
otherM.Knockup(ConfigFloat("Attack Knockup Duration"));
vf2d monsterDirVecNorm=geom2d::line<float>(m.GetPos(),otherM.GetPos()).vector().norm();
for(std::unique_ptr<Monster>&otherM:MONSTER_LIST){
if(!otherM->AttackAvoided(m.GetZ())&&&m!=otherM.get()&&geom2d::overlaps(attackCircle,otherM->Hitbox())){
otherM->Knockup(ConfigFloat("Attack Knockup Duration"));
vf2d monsterDirVecNorm=geom2d::line<float>(m.GetPos(),otherM->GetPos()).vector().norm();
game->GetPlayer()->Knockback(monsterDirVecNorm*ConfigFloat("Attack Knockback Amount"));
}
}

@ -85,7 +85,8 @@ struct FrogTongue:public Bullet{
float tongueLength;
float duration;
float knockbackStrength;
FrogTongue(vf2d pos,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength=1.0f,bool friendly=false,Pixel col=WHITE);
Monster&sourceMonster;
FrogTongue(Monster&sourceMonster,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength=1.0f,bool friendly=false,Pixel col=WHITE);
void Update(float fElapsedTime)override;
bool PlayerHit(Player*player)override;
bool MonsterHit(Monster&monster)override;

@ -42,7 +42,7 @@ All rights reserved.
using BackdropName=std::string;
#define INCLUDE_ANIMATION_DATA extern safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
#define INCLUDE_MONSTER_LIST extern std::vector<Monster>MONSTER_LIST;
#define INCLUDE_MONSTER_LIST extern std::vector<std::unique_ptr<Monster>>MONSTER_LIST;
#define INCLUDE_SPAWNER_LIST extern std::vector<MonsterSpawner>SPAWNER_LIST;
#define INCLUDE_DAMAGENUMBER_LIST extern std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
#define INCLUDE_game extern AiL*game;

@ -70,7 +70,7 @@ void Monster::STRATEGY::FROG(Monster&m,float fElapsedTime,std::string strategy){
m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Duration");
vf2d tongueMaxRangePos=geom2d::line<float>(m.GetPos(),m.V(A::LOCKON_POS)).upoint(ConfigFloat("Tongue Max Range")/ConfigFloat("Range"));
SoundEffect::PlaySFX("Slime Shoot",m.pos);
CreateBullet(FrogTongue)(m.pos,tongueMaxRangePos,ConfigFloat("Attack Duration"),m.GetAttack(),m.OnUpperLevel(),ConfigFloat("Tongue Knockback Strength"),false,ConfigPixel("Tongue Color"))EndBullet;
CreateBullet(FrogTongue)(m,tongueMaxRangePos,ConfigFloat("Attack Duration"),m.GetAttack(),m.OnUpperLevel(),ConfigFloat("Tongue Knockback Strength"),false,ConfigPixel("Tongue Color"))EndBullet;
m.PerformShootAnimation();
m.I(A::PHASE)=2;
}

@ -44,12 +44,15 @@ INCLUDE_game
INCLUDE_MONSTER_LIST
INCLUDE_GFX
FrogTongue::FrogTongue(vf2d pos,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength,bool friendly,Pixel col)
:Bullet(pos,{},0,damage,upperLevel,friendly,col),targetPos(targetPos),tongueLength(0.f),knockbackStrength(knockbackStrength){
FrogTongue::FrogTongue(Monster&sourceMonster,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength,bool friendly,Pixel col)
:Bullet(sourceMonster.GetPos(),{},0,damage,upperLevel,friendly,col),targetPos(targetPos),tongueLength(0.f),knockbackStrength(knockbackStrength),sourceMonster(sourceMonster){
this->lifetime=lifetime;
duration=lifetime;
}
void FrogTongue::Update(float fElapsedTime){
pos=sourceMonster.GetPos();
if(sourceMonster.IsAlive()){
geom2d::line<float>lineToTarget(pos,targetPos);
vf2d drawVec=lineToTarget.vector().norm()*3;
@ -62,10 +65,11 @@ void FrogTongue::Update(float fElapsedTime){
PlayerHit(game->GetPlayer());
}
if(friendly){
for(Monster&m:MONSTER_LIST){
if(hitList.find(&m)==hitList.end()&&geom2d::overlaps(m.Hitbox(),tongueLine)){
MonsterHit(m);
hitList.insert(&m);
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(hitList.find(&*m)==hitList.end()&&geom2d::overlaps(m->Hitbox(),tongueLine)){
MonsterHit(*m);
hitList.insert(&*m);
}
}
}
}

@ -94,14 +94,14 @@ bool LightningBolt::MonsterHit(Monster& monster)
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));
int targetsHit=0;
for(Monster&m:MONSTER_LIST){
if(&m==&monster||monster.OnUpperLevel()!=m.OnUpperLevel())continue;
geom2d::line<float>lineToTarget=geom2d::line<float>(monster.GetPos(),m.GetPos());
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(&*m==&monster||monster.OnUpperLevel()!=m->OnUpperLevel())continue;
geom2d::line<float>lineToTarget=geom2d::line<float>(monster.GetPos(),m->GetPos());
float dist=lineToTarget.length();
if(dist<="Wizard.Ability 2.LightningChainRadius"_F/100*24){
if(m.Hurt(int(game->GetPlayer()->GetAttack()*"Wizard.Ability 2.LightningChainDamageMult"_F),OnUpperLevel(),0)){
EMITTER_LIST.push_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m.GetPos(),"Wizard.Ability 2.LightningChainFrequency"_F,"Wizard.Ability 2.LightningChainLifetime"_F,upperLevel)));
game->AddEffect(std::make_unique<Effect>(m.GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange));
if(m->Hurt(int(game->GetPlayer()->GetAttack()*"Wizard.Ability 2.LightningChainDamageMult"_F),OnUpperLevel(),0)){
EMITTER_LIST.push_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m->GetPos(),"Wizard.Ability 2.LightningChainFrequency"_F,"Wizard.Ability 2.LightningChainLifetime"_F,upperLevel)));
game->AddEffect(std::make_unique<Effect>(m->GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange));
targetsHit++;
}
}

@ -78,7 +78,6 @@ void Minimap::Initialize(){
}
}
if(tileFound&&!collision){
if(tileCol==BLANK)ERR("WARNING! A tile should not be blank as we should have handled all conditions that would've caused that in a different color! THIS SHOULD NOT BE HAPPENING!")
minimap.Sprite()->SetPixel({x,y},{uint8_t(std::min(255.f,tileCol.r*1.5f)),uint8_t(std::min(255.f,tileCol.g*1.5f)),uint8_t(std::min(255.f,tileCol.b*1.5f))});
}else
if(!tileFound){

@ -269,14 +269,14 @@ bool Monster::Update(float fElapsedTime){
}
}
if(!HasIframes()){
for(Monster&m:MONSTER_LIST){
if(&m==this)continue;
if(!m.HasIframes()&&OnUpperLevel()==m.OnUpperLevel()&&abs(m.GetZ()-GetZ())<=1&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m.GetPos(),12*m.GetSizeMult()/2))){
m.Collision(*this);
geom2d::line line(pos,m.GetPos());
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(&*m==this)continue;
if(!m->HasIframes()&&OnUpperLevel()==m->OnUpperLevel()&&abs(m->GetZ()-GetZ())<=1&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m->GetPos(),12*m->GetSizeMult()/2))){
m->Collision(*this);
geom2d::line line(pos,m->GetPos());
float dist = line.length();
m.SetPos(line.rpoint(dist*1.1f));
if(m.IsAlive()){
m->SetPos(line.rpoint(dist*1.1f));
if(m->IsAlive()){
vel=line.vector().norm()*-128;
}
}

@ -482,19 +482,19 @@ void Player::Update(float fElapsedTime){
if(item3.cooldown<0){
item3.cooldown=0;
}
for(Monster&m:MONSTER_LIST){
if(!HasIframes()&&abs(m.GetZ()-GetZ())<=1&&OnUpperLevel()==m.OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m.GetPos(),12*m.GetSizeMult()/2))){
if(m.IsAlive()){
m.Collision(this);
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(!HasIframes()&&abs(m->GetZ()-GetZ())<=1&&OnUpperLevel()==m->OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m->GetPos(),12*m->GetSizeMult()/2))){
if(m->IsAlive()){
m->Collision(this);
}
geom2d::line line(pos,m.GetPos());
geom2d::line line(pos,m->GetPos());
float dist = line.length();
if(dist<=0.001){
m.SetPos(m.GetPos()+vf2d{util::random(2)-1,util::random(2)-1});
m->SetPos(m->GetPos()+vf2d{util::random(2)-1,util::random(2)-1});
}else{
m.SetPos(line.rpoint(dist*1.1f));
m->SetPos(line.rpoint(dist*1.1f));
}
if(m.IsAlive()&&!m.IsNPC()){ //Don't set the knockback if this monster is actually an NPC. Let's just push them around.
if(m->IsAlive()&&!m->IsNPC()){ //Don't set the knockback if this monster is actually an NPC. Let's just push them around.
vel=line.vector().norm()*-128;
}
}
@ -1445,13 +1445,13 @@ const vf2d Player::GetAimingLocation(bool useWalkDir,bool invert){
}else{
//Find the closest monster target.
vf2d closestPoint={std::numeric_limits<float>::max(),std::numeric_limits<float>::max()};
for(Monster&m:MONSTER_LIST){
if(m.IsAlive()){
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),m.GetPos());
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(m->IsAlive()){
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),m->GetPos());
float distToMonster=aimingLine.length();
float distToClosestPoint=geom2d::line<float>(GetPos(),closestPoint).length();
if(distToClosestPoint>distToMonster&&distToMonster<=operator""_Pixels("Player.Auto Aim Detection Distance"_F)){
closestPoint=m.GetPos();
closestPoint=m->GetPos();
}
}
}

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

@ -70,12 +70,12 @@ bool Warrior::AutoAttack(){
bool attack=false;
Monster*closest=nullptr;
float closest_dist=999999;
for(Monster&m:MONSTER_LIST){
if(m.IsAlive()
&&geom2d::overlaps(geom2d::circle<float>(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))
&&geom2d::line<float>(GetWorldAimingLocation(),m.GetPos()).length()<closest_dist){
closest_dist=geom2d::line<float>(GetWorldAimingLocation(),m.GetPos()).length();
closest=&m;
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(m->IsAlive()&&
geom2d::overlaps(geom2d::circle<float>(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle<float>(m->GetPos(),m->GetSizeMult()*12))&&
geom2d::line<float>(GetWorldAimingLocation(),m->GetPos()).length()<closest_dist){
closest_dist=geom2d::line<float>(GetWorldAimingLocation(),m->GetPos()).length();
closest=&*m;
}
}
@ -121,9 +121,9 @@ void Warrior::InitializeClassAbilities(){
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));
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(Monster&m:MONSTER_LIST){
if(m.GetSizeMult()>="Warrior.Ability 1.AffectedSizeRange"_f[0]&&m.GetSizeMult()<="Warrior.Ability 1.AffectedSizeRange"_f[1]&&geom2d::overlaps(geom2d::circle<float>(p->GetPos(),12*"Warrior.Ability 1.Range"_I/100.f),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))){
m.AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 1.SlowdownDuration"_F,"Warrior.Ability 1.SlowdownAmt"_F);
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(m->GetSizeMult()>="Warrior.Ability 1.AffectedSizeRange"_f[0]&&m->GetSizeMult()<="Warrior.Ability 1.AffectedSizeRange"_f[1]&&geom2d::overlaps(geom2d::circle<float>(p->GetPos(),12*"Warrior.Ability 1.Range"_I/100.f),geom2d::circle<float>(m->GetPos(),m->GetSizeMult()*12))){
m->AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 1.SlowdownDuration"_F,"Warrior.Ability 1.SlowdownAmt"_F);
}
}
SoundEffect::PlaySFX("Warrior Battlecry",SoundEffect::CENTERED);

Loading…
Cancel
Save