Add rotation parameter and hit iframe time to bullets. Iframe timers now compares current iframes to the new duration and keeps only the larger amount. Fix bug allowing monsters with jump attacks to still cause knockback and iframes even when the hit does not land. Fly Across attack implemented for second bonus boss. Release Build 9447.
booldead=false;//When marked as dead it wil be removed by the next frame.
boolsimulated=false;//A simulated bullet cannot interact / damage things in the world. It's simply used for simulating the trajectory and potential path of the bullet
//Used by special bullets to control custom despawning behavior! Return true when the bullet should be destroyed. Return false to handle it otherwise (like deactivating it instead). You become responsible for getting rid of the bullet.
//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!!
virtualboolPlayerHit(Player*player);
//Used by special bullets to control custom despawning behavior! Return true when the bullet should be destroyed. Return false to handle it otherwise (like deactivating it instead). You become responsible for getting rid of the bullet.
//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
//NOTE: Marking a monster for deletion does not trigger any death events. It just simply removes the monster from the field!!
// The way this works is that monsters marked for deletion will cause the monster update loop to detect there's at least one or more monsters that must be deleted and will call erase_if on the list at the end of the iteration loop.
//We're choosing the opposite side of the field to direct the boss towards for this attack.
if(RightDirectionChosen)m.target=ConfigVec("Fly Across Attack.Left Edge Start Pos");
elsem.target=ConfigVec("Fly Across Attack.Right Edge Start Pos");
m.phase=FLY_ACROSS;
m.AddBuff(BuffType::SPEEDBOOST,INFINITY,ConfigFloat("Fly Across Attack.Move Speed Multiplier")-1.f);
}
}break;
caseFLY_ACROSS:{
m.targetAcquireTimer=20.f;
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
m.F(A::SHOOT_TIMER)-=fElapsedTime;
if(m.F(A::SHOOT_TIMER)<=0.f){
CreateBullet(Bullet)(m.GetPos(),vf2d{0.f,ConfigFloat("Fly Across Attack.Attack Y Speed")},4,ConfigInt("Fly Across Attack.Poop Damage"),"birdpoop.png",m.OnUpperLevel(),false,INFINITY,false,false,WHITE,vf2d{1.f,1.25f})
.SetIframeTimeOnHit(0.25f)EndBullet;
constintextraPoopBitsCount=util::random()%6;
for(inti=0;i<extraPoopBitsCount;i++){
constboolRightDirection=util::random()%2;
floatxOffset{0.f};
if(RightDirection)xOffset=1.f;
elsexOffset=-1.f;
xOffset*=9.f;
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.Attack Frequency");