diff --git a/Adventures in Lestoria/Bomb.cpp b/Adventures in Lestoria/Bomb.cpp index e2303fce..7ad86d64 100644 --- a/Adventures in Lestoria/Bomb.cpp +++ b/Adventures in Lestoria/Bomb.cpp @@ -104,5 +104,5 @@ bool Bomb::MonsterHit(Monster&monster){ void Bomb::Draw()const{ Bullet::Draw(); - game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},bomb_animation.GetFrame(animation).GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,bomb_animation.GetFrame(animation).GetSourceRect().size/2,bomb_animation.GetFrame(animation).GetSourceRect().pos,bomb_animation.GetFrame(animation).GetSourceRect().size,scale,fadeOutTime==0?col:Pixel{col.r,col.g,col.b,uint8_t(util::lerp(col.a,0,1-((fadeOutTime-fadeOutTimer)/fadeOutTime)))}); + game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},bomb_animation.GetFrame(animation).GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,bomb_animation.GetFrame(animation).GetSourceRect().size/2,bomb_animation.GetFrame(animation).GetSourceRect().pos,bomb_animation.GetFrame(animation).GetSourceRect().size,scale,fadeOutTime==0?col:Pixel{col.r,col.g,col.b,uint8_t(util::lerp(col.a,0,1-((fadeOutTime-GetFadeoutTimer())/fadeOutTime)))}); } \ No newline at end of file diff --git a/Adventures in Lestoria/Bullet.cpp b/Adventures in Lestoria/Bullet.cpp index eccf4ab4..a8583af0 100644 --- a/Adventures in Lestoria/Bullet.cpp +++ b/Adventures in Lestoria/Bullet.cpp @@ -47,11 +47,11 @@ INCLUDE_GFX INCLUDE_MONSTER_LIST INCLUDE_WINDOW_SIZE -Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col,vf2d scale,float rot) - :pos(pos),vel(vel),radius(radius),damage(damage),col(col),friendly(friendly),upperLevel(upperLevel),scale(scale),rot(rot){}; +Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col,vf2d scale,float image_angle) + :pos(pos),vel(vel),radius(radius),damage(damage),col(col),friendly(friendly),upperLevel(upperLevel),scale(scale),image_angle(image_angle){}; -Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,std::string animation,bool upperLevel,bool hitsMultiple,float lifetime,bool rotatesWithAngle,bool friendly,Pixel col,vf2d scale,float rot) - :pos(pos),vel(vel),radius(radius),damage(damage),col(col),animated(true),rotates(rotatesWithAngle),lifetime(lifetime),hitsMultiple(hitsMultiple),friendly(friendly),upperLevel(upperLevel),scale(scale),rot(rot){ +Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,std::string animation,bool upperLevel,bool hitsMultiple,float lifetime,bool rotatesWithAngle,bool friendly,Pixel col,vf2d scale,float image_angle) + :pos(pos),vel(vel),radius(radius),damage(damage),col(col),animated(true),rotates(rotatesWithAngle),lifetime(lifetime),hitsMultiple(hitsMultiple),friendly(friendly),upperLevel(upperLevel),scale(scale),image_angle(image_angle){ this->animation.AddState(animation,ANIMATION_DATA[animation]); this->animation.ChangeState(internal_animState,animation); }; @@ -104,18 +104,21 @@ void Bullet::_Update(const float fElapsedTime){ dead=true; } return false; - } + }else _MonsterHit(*m); hitList.insert(&*m); } } } } else { if(geom2d::overlaps(game->GetPlayer()->Hitbox(),geom2d::circle(pos,radius))){ - if(game->GetPlayer()->Hurt(damage,OnUpperLevel(),z)){ - if(_PlayerHit(&*game->GetPlayer())){ - dead=true; - } - return false; + if(hitList.find(game->GetPlayer())==hitList.end()&&game->GetPlayer()->Hurt(damage,OnUpperLevel(),z)){ + if(!hitsMultiple){ + if(_PlayerHit(&*game->GetPlayer())){ + dead=true; + } + return false; + }else _PlayerHit(&*game->GetPlayer()); + hitList.insert(game->GetPlayer()); } } } @@ -169,22 +172,22 @@ void Bullet::Draw()const{ } if(animated){ - game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2+rot:rot,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,blendCol); + game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2+image_angle:image_angle,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,blendCol); }else{ - game->view.DrawRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY-GFX["circle.png"].Sprite()->Size()*scale/2,GFX["circle.png"].Decal(),rot,GFX["circle.png"].Sprite()->Size()/2,scale,blendCol); - game->view.DrawRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY-GFX["circle.png"].Sprite()->Size()*scale/2,GFX["circle_outline.png"].Decal(),rot,GFX["circle.png"].Sprite()->Size()/2,scale,Pixel{WHITE.r,WHITE.g,WHITE.b,blendCol.a}); + game->view.DrawRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY-GFX["circle.png"].Sprite()->Size()*scale/2,GFX["circle.png"].Decal(),image_angle,GFX["circle.png"].Sprite()->Size()/2,scale,blendCol); + game->view.DrawRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY-GFX["circle.png"].Sprite()->Size()*scale/2,GFX["circle_outline.png"].Decal(),image_angle,GFX["circle.png"].Sprite()->Size()/2,scale,Pixel{WHITE.r,WHITE.g,WHITE.b,blendCol.a}); } } bool Bullet::_PlayerHit(Player*player){ - const bool hitOccurred=PlayerHit(player); + const bool destroyBullet=PlayerHit(player); if(iframeTimerOnHit>0.f)player->ApplyIframes(iframeTimerOnHit); - return hitOccurred; + return destroyBullet; } bool Bullet::_MonsterHit(Monster&monster){ - const bool hitOccurred=MonsterHit(monster); + const bool destroyBullet=MonsterHit(monster); if(iframeTimerOnHit>0.f)monster.ApplyIframes(iframeTimerOnHit); - return hitOccurred; + return destroyBullet; } bool Bullet::PlayerHit(Player*player){return true;} bool Bullet::MonsterHit(Monster&monster){return true;} @@ -208,4 +211,8 @@ Bullet&Bullet::SetFadeinTime(float fadeInTime){ lifetime+=durationDiff; deactivated=true; return *this; +} + +const float&Bullet::GetFadeoutTimer()const{ + return fadeOutTimer; } \ No newline at end of file diff --git a/Adventures in Lestoria/Bullet.h b/Adventures in Lestoria/Bullet.h index 2663fabe..55b1ec29 100644 --- a/Adventures in Lestoria/Bullet.h +++ b/Adventures in Lestoria/Bullet.h @@ -57,12 +57,12 @@ struct Bullet{ bool upperLevel=false; bool alwaysOnTop=false; float z=0.f; - float rot=0.f; + float image_angle=0.f; protected: - float fadeOutTimer=0; float distanceTraveled=0.f; vf2d scale={1,1}; private: + float fadeOutTimer=0; float fadeInTime=0; //Setting the fade in time causes the bullet to be disabled and the bullet's alpha will fade in from zero to the actual alpha of the bullet. When the fade in timer reaches the fade in time automatically, the bullet will be enabled. float fadeInTimer=0; void UpdateFadeTime(float fElapsedTime); @@ -74,14 +74,15 @@ protected: float drawOffsetY{}; bool _PlayerHit(Player*player); bool _MonsterHit(Monster&monster); + const float&GetFadeoutTimer()const; public: Animate2D::Animationanimation; Animate2D::AnimationState internal_animState; - std::sethitList; + std::set>hitList; virtual ~Bullet()=default; - Bullet(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float rot=0.f); + Bullet(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f); //Initializes a bullet with an animation. - Bullet(vf2d pos,vf2d vel,float radius,int damage,std::string animation,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool rotatesWithAngle=false,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float rot=0.f); + Bullet(vf2d pos,vf2d vel,float radius,int damage,std::string animation,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool rotatesWithAngle=false,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f); public: void SimulateUpdate(const float fElapsedTime); diff --git a/Adventures in Lestoria/BulletTypes.h b/Adventures in Lestoria/BulletTypes.h index 55c74120..088816a1 100644 --- a/Adventures in Lestoria/BulletTypes.h +++ b/Adventures in Lestoria/BulletTypes.h @@ -192,6 +192,8 @@ struct Tornado:public Bullet{ float knockupDuration{}; float knockbackAmt{}; float fadeInDuration{}; + float rot{0.f}; + bool fadeOut{false}; Tornado(vf2d centerPoint,float distance,float initialRot,float rotSpd,int damage,const float knockupAmt,const float knockbackAmt,const float lifetime,bool upperLevel,bool friendly=false,Pixel col=WHITE,const vf2d scale={1,1}); void Update(float fElapsedTime)override; bool PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! diff --git a/Adventures in Lestoria/Tornado.cpp b/Adventures in Lestoria/Tornado.cpp index 58e73b82..57e02f62 100644 --- a/Adventures in Lestoria/Tornado.cpp +++ b/Adventures in Lestoria/Tornado.cpp @@ -41,14 +41,21 @@ All rights reserved. #include "util.h" Tornado::Tornado(vf2d centerPoint,float distance,float initialRot,float rotSpd,int damage,const float knockupDuration,const float knockbackAmt,const float lifetime,bool upperLevel,bool friendly,Pixel col,const vf2d scale) - :polarAngle({distance,initialRot}),rotatingSpd(rotSpd),knockupDuration(knockupDuration),knockbackAmt(knockbackAmt),Bullet(centerPoint+polarAngle.cart(),vf2d{},6.f,damage,"tornado2.png",upperLevel,true,lifetime,false,friendly,col,scale){} + :polarAngle({distance,initialRot}),rot(initialRot),rotatingSpd(rotSpd),knockupDuration(knockupDuration),knockbackAmt(knockbackAmt),centerPoint(centerPoint),Bullet(centerPoint+polarAngle.cart(),vf2d{},6.f,damage,"tornado2.png",upperLevel,true,lifetime+0.5f,false,friendly,col,scale){} void Tornado::Update(float fElapsedTime){ - rot+=rotatingSpd; + rot+=rotatingSpd*fElapsedTime; polarAngle={polarAngle.x,rot}; pos=centerPoint+polarAngle.cart(); + + if(lifetime<=0.5f&&!fadeOut){ + fadeOut=true; + fadeOutTime=0.5f; + } + + hitList.clear(); //This is a slight hack to make it so these tornados will always hit things multiple times. } bool Tornado::PlayerHit(Player*player){ @@ -57,7 +64,7 @@ bool Tornado::PlayerHit(Player*player){ player->ApplyIframes(knockupDuration); - return true; + return false; } bool Tornado::MonsterHit(Monster&monster){ @@ -66,5 +73,7 @@ bool Tornado::MonsterHit(Monster&monster){ monster.Knockback(util::pointTo(centerPoint,monster.GetPos())*knockbackAmt); monster.Knockup(knockupDuration); - return true; + monster.ApplyIframes(knockupDuration); + + return false; } \ No newline at end of file diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 33b2724f..5649b0b2 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_PATCH 3 -#define VERSION_BUILD 9455 +#define VERSION_BUILD 9473 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/Zephy.cpp b/Adventures in Lestoria/Zephy.cpp index 9c6455b0..2bf7e179 100644 --- a/Adventures in Lestoria/Zephy.cpp +++ b/Adventures in Lestoria/Zephy.cpp @@ -91,7 +91,7 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy) }break; case 1:{ m.phase=TORNADO_ATTACK_PREPARE; - m.target=ConfigVec("Tornado Attack.Arena Center"); + m.target=ConfigVec("Tornado Attack.Landing Area"); }break; case 2:{ m.phase=WIND_ATTACK; @@ -132,7 +132,7 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy) CreateBullet(Bullet)(m.GetPos()+vf2d{xOffset+util::random_range(-3.f,3.f),-util::random(10.f)-4.f},vf2d{0.f,ConfigFloat("Fly Across Attack.Attack Y Speed")},1,ConfigInt("Fly Across Attack.Poop Damage"),"birdpoop.png",m.OnUpperLevel(),false,INFINITY,false,false,WHITE,vf2d{util::random_range(0.2f,0.3f),util::random_range(0.2f,0.3f)},util::random(2*PI)) .SetIframeTimeOnHit(0.25f)EndBullet; } - m.F(A::SHOOT_TIMER)=ConfigFloat("Fly Across Attack.Landing Area"); + m.F(A::SHOOT_TIMER)=ConfigFloat("Fly Across Attack.Attack Frequency"); } if(m.ReachedTargetPos()){ m.phase=IDLE; @@ -154,19 +154,24 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy) //From strategy documentation: //# For each Ring: Distance from Boss in Units, # of tornados, Rotation Speed (degrees/sec). - const float tornadoDistance=ConfigPixelsArr(std::format("Tornado Attack.Tornados.Ring{}",tornadoRingId),0); - const int tornadoCount=ConfigIntArr(std::format("Tornado Attack.Tornados.Ring{}",tornadoRingId),1); - const float tornadoRotSpd=util::degToRad(ConfigFloatArr(std::format("Tornado Attack.Tornados.Ring{}",tornadoRingId),2)); //It's in degrees, let's convert it to radians now. + const float tornadoDistance=ConfigPixelsArr(std::format("Tornado Attack.Tornados.Ring {}",tornadoRingId),0); + const int tornadoCount=ConfigIntArr(std::format("Tornado Attack.Tornados.Ring {}",tornadoRingId),1); + const float tornadoRotSpd=util::degToRad(ConfigFloatArr(std::format("Tornado Attack.Tornados.Ring {}",tornadoRingId),2)); //It's in degrees, let's convert it to radians now. const float randomRotDir=util::random(2*PI); - CreateBullet(Tornado)(m.GetPos(),tornadoDistance,randomRotDir,tornadoRotSpd,m.GetAttack(),ConfigFloat("Tornado Attack.Knockup Duration"),ConfigFloat("Tornado Attack.Knockback Amount"),ConfigFloat("Tornado Attack.Attack Duration"),m.OnUpperLevel(),false,WHITE)EndBullet; - BULLET_LIST.back()->SetFadeinTime(ConfigFloat("Tornado Fade-In Time")); + for(int tornadoCounter=0;tornadoCounterSetFadeinTime(ConfigFloat("Tornado Attack.Tornado Fade-In Time")); + } } } }break; case TORNADO_ATTACK:{ - + m.F(A::CASTING_TIMER)-=fElapsedTime; + if(m.F(A::CASTING_TIMER)<=0.f)m.phase=IDLE; }break; case WIND_ATTACK:{ diff --git a/Adventures in Lestoria/assets/config/MonsterStrategies.txt b/Adventures in Lestoria/assets/config/MonsterStrategies.txt index 03d43f8b..d5e7ff1d 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -811,10 +811,12 @@ MonsterStrategy { # For each Ring: Distance from Boss in Units, # of tornados, Rotation Speed (degrees/sec). # Freely add/subtract rings to create or remove more tornados. - Ring 1 = 100, 2, 120 - Ring 2 = 200, 3, -75 - Ring 3 = 300, 5, 60 - Ring 4 = 400, 8, -40 + Ring 1 = 100, 2, 90 + Ring 2 = 235, 3, -60 + Ring 3 = 370, 5, 40 + Ring 4 = 505, 8, -20 + Ring 5 = 640, 12, 10 + Ring 6 = 775, 18, -7 } } } diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index eb735ad0..a6392c87 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ