task missiles(int num){
  if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;} //Default kill to prevent (0,0) spawning
	//{
		real[] rate, pos, ang; let laser = [];
    let aux, obj1;

    real r = 0;
    real sp = num/2 + 1/2;
    real ec = (|num|)/num;

    int timing = 30;
	//}

  async{
    PlaySFXV(SFX_CHARGE, 60); PlaySFXV(SFX_MAO00, 80); 
    loop(15){
      Concentration(bx, by, 40, 400, 5, 5, 6, BLEND_ADD_ARGB, 240, 66, 66, 1);
      wait(2);
    }
  }

  laser ~= [CreateSTLaser(bx - 18, by - 5, 270, 700, 20, SHOT_LASER_RED, [60*1 + 20, 60*99])];
  laser ~= [CreateSTLaser(bx + 18, by - 5, 270, 700, 20, SHOT_LASER_RED, [60*1 + 20, 60*99])];

  laser ~= [CreateSTLaser(bx - 18, by - 5, 270+180, 700, 20, SHOT_LASER_RED, [60*1 + 20, 60*99])];
  laser ~= [CreateSTLaser(bx + 18, by - 5, 270+180, 700, 20, SHOT_LASER_RED, [60*1 + 20, 60*99])];

  for each(let obj : laser){
    alpha_XtoY(obj, 0, 255, [0, 60]);
  }

  aux = CreateShotA1(bx, by, 0, 90, SHOT_BALL_INVERT_RED, 5); ObjRender_SetAlpha(aux, 123);
  ObjRender_SetScaleXYZ(aux, 2, 2, 0); ObjShot_SetIntersectionEnable(aux, false); 

  async{
    timing = 11; wait(30);
    ascent(int i in 0..timing){
      if(Obj_IsDeleted(objBoss)){break;}
      pos = [stx[as_int(sp)] + 20*ec, gy-40, bx, by];
      rate = Interpolate_Linear([bx, by], [pos[0], pos[1]], i/(timing-1)); 
      ConcentrationExplosion(rate[0], rate[1], 60, 120, 1, 6, 2, BLEND_ADD_ARGB, 228, 37, 37, 1);
    }
  }

  ascent(int i in 0..timing){
    if(Obj_IsDeleted(objBoss)){break;}
    pos = [stx[as_int(sp)] + 20*ec, gy-40, bx, by];
    rate = Interpolate_Linear([bx, by], [pos[0], pos[1]], i/(timing-1)); 
    setpos(aux, rate[0], rate[1]);    
    
    ang = [GetAngleFromTo(pos[0], pos[1], bx - 18, by - 5), GetAngleFromTo(pos[0], pos[1], bx + 18, by - 5)];
    rate = Interpolate_Smooth([270, 270], [ang[0], ang[1]], i/(timing-1));
    ObjStLaser_SetAngle(laser[0], NormalizeAngle(rate[0]));
    ObjStLaser_SetAngle(laser[2], NormalizeAngle(rate[0])+180);
    ObjStLaser_SetAngle(laser[1], NormalizeAngle(rate[1]));
    ObjStLaser_SetAngle(laser[3], NormalizeAngle(rate[1])+180);
    yield;
  }

  PlaySFXVDelay(SFX_LASER00, 70, 20);
  wait(20); shrinkndie(aux, 2, 15); 
  for each(let las : laser){
    size(las, 100*2, 15, 12, false);
  }
  
  ObjMove_SetDestAtFrameWeight(objBoss, pos[0], pos[1], 22); 
  wait(22);

  heartbeat([bx, by], GetAngleFromTo(pos[0], pos[1], pos[2], pos[3]));
  dream_glow([bx, by], num, r);

  wait(60*1.5);
  if(num > 0){missiles(-num);}
  else{aimed(-num);}
}

//---------------------------------------------------------------------------------------------
task aimed(int num){
  if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;} //Default kill to prevent (0,0) spawning
	//{
		real r = 0, pass = 9;
    int timer = 30;

    let aux;
	//}

  ObjMove_SetDestAtFrameWeight(objBoss, gx, gy-100, 60); 
  wait(60);

  async{
    PlaySFXV(SFX_CHARGE, 60); 
    loop(15){
      Concentration(bx, by, 40, 300, 5, 5, 6, BLEND_ADD_ARGB, 99, 3, 3, 1);
      Concentration(stx[0] - 20, sty[1], 40, 300, 5, 5, 6, BLEND_ADD_ARGB, 99, 3, 3, 1);
      wait(2);
    }

    wait(90*3 - 30);

    PlaySFXV(SFX_CHARGE, 60); 
    loop(15){
      Concentration(bx, by, 40, 300, 5, 5, 6, BLEND_ADD_ARGB, 99, 3, 3, 1);
      Concentration(stx[1] + 20, sty[1], 40, 300, 5, 5, 6, BLEND_ADD_ARGB, 99, 3, 3, 1);
      wait(2);
    }
  }

  wait(30);

  { 
    PlaySFXV(SFX_MAGIC02, 70); 
    {
      if(Obj_IsDeleted(objBoss)){return;}
      real a = r;
      
      aux = CreateMoveDuoSTLaser(bx, by, 5, a, [a, -35], 50, 28, [SHOT_BALL_RED, SHOT_DROP_BLUE], [10, 60*99]);
      penetrate(aux, pass, 90, true); 
      seigaGim(aux, [stx[0] - 20, bx - 130], [sty[1], by - 60], [-2, 2], 90, 90);
      aux = CustomCLaser(bx, by, 5, a, SHOT_DIAMOND_INVERT_DRED, [2, 3, 3, 3], BLEND_ALPHA);
      penetrate(aux, pass, 90, false); 
      seigaGim(aux, [stx[0] - 20, bx - 130], [sty[1], by - 60], [-2, 2], 90, 90);
    }

    pass *= -1;
    wait(90*3);

    PlaySFXV(SFX_MAGIC02, 70); 
    {
      if(Obj_IsDeleted(objBoss)){return;}
      real a = r;
      
      aux = CreateMoveDuoSTLaser(bx, by, 5, a, [a, -35], 50, 28, [SHOT_BALL_RED, SHOT_OVAL_BLUE], [10, 60*99]);
      penetrate(aux, pass, 90, true); 
      seigaGim(aux, [stx[1] + 20, bx + 130], [sty[1], by - 60], [-2, 2], 90, 90);
      aux = CustomCLaser(bx, by, 5, a, SHOT_DIAMOND_INVERT_DRED, [2, 3, 3, 3], BLEND_ALPHA);
      penetrate(aux, pass, 90, false); 
      seigaGim(aux, [stx[1] + 20, bx + 130], [sty[1], by - 60], [-2, 2], 90, 90);
    }

    pass *= -1;
  }

  wait(90*3);
  missiles(num);
}

task penetrate(obj, turn, frame, booltask){
  let aux; const int num = 16;
  real xpos, ypos, r = geta(obj); ObjShot_SetSpellResist(obj, true);
  loop(frame){
    if(Obj_IsDeleted(objBoss) || Obj_IsDeleted(obj)){return;}
    xpos = getx(obj); ypos = gety(obj);
    yield;
  }

  Obj_Delete(obj);
  if(!booltask || Obj_IsDeleted(objBoss)){return;}
  async{
    ascent(int i in 0..14+1){
      ConcentrationExplosion(xpos, ypos, 60, 120, 0, 6, 0.5 + i/7, BLEND_ADD_ARGB, 87, 15, 15, 1);
    }
  }

  PlaySFXV(SFX_RELEASE, 80); 
  PlaySFXV(SFX_SHOT01, 40); 
  ascent(int j in 0..num){
    ascent(int i in 0..24){
      real a = r + 360/24*i;

      aux = CScaledShotA1(xpos, ypos, 3.25, a, SHOT_DROP_ORANGE, 5, 1.25);
      ObjMove_AddPatternA3(aux, 20, NO_CHANGE, a - j*turn, -1/3, 0, 1.5 + j/5, SHOT_DIAMOND_INVERT_DRED);
    }

    if(j != num-1 && j != 0){continue;}
    ascent(int i in 0..72){
      real a = r + 360/72*i;

      aux = CScaledShotA1(xpos, ypos, 3.25, a, SHOT_BALL_ORANGE, 5, 1.25);
      ObjMove_AddPatternA3(aux, 20, NO_CHANGE, a - j*turn, -1/3, 0, 1.5 + j/5, SHOT_BALL_RED);
      ObjShot_SetSpellResist(aux, true);
    }
  }
  
}

task seigaGim(obj, real[] xVar, real[] yVar, real[] over, int frame, real an){
  let angle = geta(obj);
  ascent(i in 0..frame){
    if(Obj_IsDeleted(obj) || Obj_IsDeleted(objBoss)){break;}

    setx(obj, Interpolate_Overshoot(xVar[0], xVar[1], over[0], i/(frame-1)));
    sety(obj, Interpolate_Overshoot(yVar[0], yVar[1], over[1], i/(frame-1)));
    seta(obj, Interpolate_Decelerate(NormalizeAngle(angle), NormalizeAngle(an), i/(frame-1)));
    yield;
  }

  if(Obj_IsDeleted(obj)){return;}
}

//------------------------------------------------------------------------------------------------------
task dream_glow(real[] pos, int num, real r){
  let obj; int v = -1;

  loop(60*1.5){
    if(Obj_IsDeleted(objBoss)){break;}

    PlaySFXV(SFX_SHOT01, 30); 
    ascent(int i in 0..5){
      real a = r + 360/5*i;

      obj = CShotA1(pos[0], pos[1], 5, a, SHOT_OVAL_INVERT_RED, 5);
      ObjMove_AddPatternA3(obj, 15, 4, a + 180 + (10)*v*num, -1/20, 0, 2.53, SHOT_BALL_AURA_DGREEN);
    }

    v++; v = (v > 1) ? -1 : v;
    r += (7)*num;
    wait(2);
  }
}

task heartbeat(real[] pos, real an){
  if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;} //Default kill to prevent (0,0) spawning
	//{
		real rate; const int dn = 20;

    real r = an; let obj;
	//}

  ascent(int counter in 0..dn){
    PlaySFXV(SFX_SHOT00, 18); 

    if(Obj_IsDeleted(objBoss)){break;}
    descent(int i in 0..6){
      rate = Interpolate_Linear(r-5, r-180, counter/(dn - 1));
      obj = CShotA1(pos[0], pos[1], 2+i/2.25, rate, SHOT_KNIFE_PURPLE, 5);
      ObjShot_SetSpellResist(obj, true);

      rate = Interpolate_Linear(r+5, r+180, counter/(dn - 1));
      obj = CShotA1(pos[0], pos[1], 2+i/2.25, rate, SHOT_KNIFE_PURPLE, 5);
      ObjShot_SetSpellResist(obj, true);
    }

    wait(2);
  }
}