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.
This commit is contained in:
parent
254b4b3ea0
commit
4306f4eab8
@ -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,28 +44,32 @@ 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){
|
||||
geom2d::line<float>lineToTarget(pos,targetPos);
|
||||
vf2d drawVec=lineToTarget.vector().norm()*3;
|
||||
pos=sourceMonster.GetPos();
|
||||
|
||||
tongueLength=util::lerp(0,lineToTarget.length(),pow(sin((lifetime*PI)/duration),20.f));
|
||||
if(sourceMonster.IsAlive()){
|
||||
geom2d::line<float>lineToTarget(pos,targetPos);
|
||||
vf2d drawVec=lineToTarget.vector().norm()*3;
|
||||
|
||||
vf2d tongueEndPos=geom2d::line<float>(pos+drawVec,targetPos).upoint(pow(sin((lifetime*PI)/duration),20.f));
|
||||
geom2d::line<float>tongueLine(pos+drawVec,tongueEndPos);
|
||||
tongueLength=util::lerp(0,lineToTarget.length(),pow(sin((lifetime*PI)/duration),20.f));
|
||||
|
||||
if(!friendly&&geom2d::overlaps(game->GetPlayer()->Hitbox(),tongueLine)){
|
||||
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);
|
||||
vf2d tongueEndPos=geom2d::line<float>(pos+drawVec,targetPos).upoint(pow(sin((lifetime*PI)/duration),20.f));
|
||||
geom2d::line<float>tongueLine(pos+drawVec,tongueEndPos);
|
||||
|
||||
if(!friendly&&geom2d::overlaps(game->GetPlayer()->Hitbox(),tongueLine)){
|
||||
PlayerHit(game->GetPlayer());
|
||||
}
|
||||
if(friendly){
|
||||
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,8 +78,7 @@ 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))});
|
||||
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){
|
||||
game->SetPixelMode(Pixel::ALPHA);
|
||||
|
@ -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);
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user