public override void AI() { Lighting.AddLight(npc.Center, new Vector3(1, 1, 0.8f)); /* AI fields: * 0: phase * 1: timer * 2: attack phase * 3: attack timer */ npc.ai[1]++; //tick our timer up constantly npc.ai[3]++; //tick up our attack timer if (npc.ai[0] == (int)OvergrowBossPhase.Struggle) { if (spawnPoint == Vector2.Zero) { spawnPoint = npc.Center; //sets the boss' home } npc.velocity.Y = (float)Math.Sin((npc.ai[1] % 120) / 120f * 6.28f) * 0.6f; if (!Main.npc.Any(n => n.active && n.type == ModContent.NPCType <OvergrowBossAnchor>())) //once the chains are broken { npc.velocity *= 0; npc.Center = spawnPoint; npc.ai[1] = 0; StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.ScreenMoveTime = 320; mp.ScreenMoveTarget = npc.Center; StarlightRiver.Instance.abilitytext.Display("[PH] Overgrow Boss", "[PH] Boss of the Overgrow", null, 200); LegendWorld.OvergrowBossFree = true; npc.ai[0] = (int)OvergrowBossPhase.spawnAnimation; } } if (npc.ai[0] == (int)OvergrowBossPhase.spawnAnimation) { if (npc.ai[1] >= 500) { npc.ai[0] = (int)OvergrowBossPhase.Setup; } } if (npc.ai[0] == (int)OvergrowBossPhase.Setup) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/GlassBoss"); int index = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, ModContent.NPCType <OvergrowBossFlail>()); //spawn the flail after intro (Main.npc[index].modNPC as OvergrowBossFlail).parent = this; //set the flail's parent flail = Main.npc[index].modNPC as OvergrowBossFlail; //tells the boss what flail it owns npc.ai[0] = (int)OvergrowBossPhase.FirstAttack; //move on to the first attack phase npc.ai[1] = 0; //reset our timer npc.ai[3] = 0; //reset our attack timer } if (flail == null) { return; //at this point, our boss should have her flail. if for some reason she dosent, this is a safety check } Main.NewText(npc.ai[0] + "/" + npc.ai[1] + "/" + npc.ai[2] + "/" + npc.ai[3] + "/" + usedBolts + "/" + usedPendulum + "/" + Vector2.Distance(spawnPoint, Main.player[npc.target].Center)); if (npc.ai[0] == (int)OvergrowBossPhase.FirstAttack) { //attacks here if (npc.ai[2] == 0) { RandomTarget(); //pendulum attack is based on a RANDOM target's position if ((Math.Abs(spawnPoint.X - Main.player[npc.target].Center.X) > 500 || Main.rand.Next(3) == 0) && !usedPendulum) { npc.ai[2] = 5; //if the player is near the edge or randomly } if (npc.ai[2] == 0) //if the random checks fail to pick an attack { npc.TargetClosest(); if (usedBolts && Vector2.Distance(spawnPoint, Main.player[npc.target].Center) < 500) { npc.ai[2] = 1; //if the player is near the center, use a swing if bolts has been used, else move on } else if (!usedBolts && Main.rand.Next(2) == 0) { npc.ai[2] = 2; //otherwise use another attack, even though bolts takes a random target, the logic dictating the chance of this attack does not } else if (Main.rand.Next(2) == 0) { npc.ai[2] = 3; } else { npc.ai[2] = 4; } } if (npc.ai[2] != 2) { usedBolts = false; //reset bolt restriction } if (npc.ai[2] == 1) { usedPendulum = false; //reset pendulum restriction after being spun } } switch (npc.ai[2]) { case 1: Phase1Spin(); break; //I should make an enum for this too case 2: Phase1Bolts(); usedBolts = true; break; //Bolts! make sure to set usedBolts to true! case 3: Phase1Toss(); break; case 4: Phase1Trap(); break; case 5: Phase1Pendulum(); usedPendulum = true; break; } if (flail.npc.life <= 1) { npc.ai[0] = (int)OvergrowBossPhase.FirstToss; //move to next phase once the flail is depleated ResetAttack(); foreach (Projectile proj in Main.projectile.Where(p => p.type == ModContent.ProjectileType <Projectiles.Dummies.OvergrowBossPitDummy>())) { proj.ai[1] = 1; //opens the pits } } } if (npc.ai[0] == (int)OvergrowBossPhase.FirstToss) { RapidToss(); } if (npc.ai[0] == (int)OvergrowBossPhase.FirstStun) { foreach (Player player in Main.player) { if (Abilities.AbilityHelper.CheckDash(player, npc.Hitbox)) { npc.ai[0] = (int)OvergrowBossPhase.FirstGuard; npc.ai[1] = 0; flail.npc.ai[0] = 1; //turn the flail into a pick-upable thing flail.npc.noGravity = false; //obey the laws of physics! } } } if (npc.ai[0] == (int)OvergrowBossPhase.FirstBurn) { } if (npc.ai[0] == (int)OvergrowBossPhase.FirstGuard) { if (npc.ai[1] == 0) //at the start of the phase, spawn in our mechanics! { npc.position = spawnPoint; music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/GlassPassive"); //spawn moving platforms NPC.NewNPC((int)npc.Center.X + 500, (int)npc.Center.Y + 200, ModContent.NPCType <OvergrowBossVerticalPlatform>()); NPC.NewNPC((int)npc.Center.X - 500, (int)npc.Center.Y + 200, ModContent.NPCType <OvergrowBossVerticalPlatform>()); NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y - 100, ModContent.NPCType <OvergrowBossCircularPlatform>()); //spawn guardians NPC.NewNPC((int)npc.Center.X + 600, (int)npc.Center.Y - 300, ModContent.NPCType <OvergrowBossGuardian>()); NPC.NewNPC((int)npc.Center.X - 600, (int)npc.Center.Y - 300, ModContent.NPCType <OvergrowBossGuardian>()); NPC.NewNPC((int)npc.Center.X + 600, (int)npc.Center.Y + 300, ModContent.NPCType <OvergrowBossGuardian>()); NPC.NewNPC((int)npc.Center.X - 600, (int)npc.Center.Y + 300, ModContent.NPCType <OvergrowBossGuardian>()); //make platforms appear for (int x = (int)npc.Center.X / 16 - 100; x <= (int)npc.Center.X / 16 + 100; x++) { for (int y = (int)npc.Center.Y / 16 - 100; y <= (int)npc.Center.Y / 16 + 100; y++) { if (Main.tile[x, y].type == ModContent.TileType <Tiles.Overgrow.AppearingBrick>() && Main.tile[x, y].frameX == 0) { Main.tile[x, y].frameX = 20; } } } } else if (!Main.npc.Any(n => n.active && n.type == ModContent.NPCType <OvergrowBossGuardian>())) { npc.ai[0] = 7; ResetIntermission(); } } }
public override void AI() { Lighting.AddLight(npc.Center, new Vector3(1, 1, 0.8f)); GlobalTimer++; //tick our timer up constantly AttackTimer++; //tick up our attack timer if (npc.ai[0] == (int)OvergrowBossPhase.Struggle) //when the boss is trapped before spawning the first time { if (spawnPoint == Vector2.Zero) { spawnPoint = npc.Center; //sets the boss' home } npc.velocity.Y = (float)Math.Sin((GlobalTimer % 120) / 120f * 6.28f) * 0.6f; if (!Main.npc.Any(n => n.active && n.type == NPCType <OvergrowBossAnchor>())) //once the chains are broken { npc.velocity *= 0; npc.Center = spawnPoint; GlobalTimer = 0; StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.ScreenMoveTime = 860; mp.ScreenMoveTarget = npc.Center; mp.ScreenMovePan = npc.Center + new Vector2(0, -100); Phase = (int)OvergrowBossPhase.spawnAnimation; } } if (Phase == (int)OvergrowBossPhase.spawnAnimation) //the boss' spawn animation. { if (GlobalTimer == 1) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/OvergrowBoss"); } if (GlobalTimer <= 120) { npc.position.Y--; } if (GlobalTimer == 120) { StarlightWorld.Flag(WorldFlags.OvergrowBossFree); } if (GlobalTimer == 500) { string message = "Faerie Guardian"; if (Main.rand.Next(10000) == 0) { message = "Titty Elongator"; // Yep } StarlightRiver.Instance.textcard.Display("Eggshells", message, null, 220); } if (GlobalTimer >= 860) { Phase = (int)OvergrowBossPhase.Setup; } } if (Phase == (int)OvergrowBossPhase.Setup) { npc.boss = true; int index = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCType <OvergrowBossFlail>()); //spawn the flail after intro (Main.npc[index].modNPC as OvergrowBossFlail).parent = this; //set the flail's parent flail = Main.npc[index].modNPC as OvergrowBossFlail; //tells the boss what flail it owns Phase = (int)OvergrowBossPhase.FirstAttack; //move on to the first attack phase GlobalTimer = 0; //reset our timer npc.ai[3] = 0; //reset our attack timer } if (flail == null) { return; //at this point, our boss should have her flail. if for some reason she dosent, this is a safety check } if (Phase == (int)OvergrowBossPhase.FirstAttack) //the first attacking phase { //attack pattern advancement logic if (AttackTimer == 1) { RandomizeTarget(); if (AttackPhase == 1) { AttackPhase++; //tick up an additional time so that we dont use 2 alternate attacks in a row. TODO: Should make a cleaner way to do this. } AttackPhase++; if (AttackPhase == 1 && Main.rand.Next(2) == 0) { AttackPhase++; } if (AttackPhase > 6) { AttackPhase = 0; } if (flail.npc.life <= 1) //move to next phase once the flail is depleated { Phase = (int)OvergrowBossPhase.FirstToss; AttackPhase = 0; ResetAttack(); foreach (Projectile proj in Main.projectile.Where(p => p.type == ProjectileType <Projectiles.Dummies.OvergrowBossPitDummy>())) { proj.ai[1] = 1; //opens the pits } } } switch (AttackPhase) //attack pattern { case 0: Phase1Spin(); break; case 1: Phase1Bolts(); break; //______randonly picks between these two case 2: Phase1Trap(); break; //___| case 3: Phase1Toss(); break; case 4: Phase1Toss(); break; case 5: Phase1Bolts(); break; case 6: Phase1Toss(); break; } } if (Phase == (int)OvergrowBossPhase.FirstToss) { RapidToss(); //toss rapidly till thrown into a pit } if (Phase == (int)OvergrowBossPhase.Stun) { if (GlobalTimer == 1) { npc.alpha = 255; for (int k = 0; k < 100; k++) { Dust d = Dust.NewDustPerfect(npc.Center, 1 /*DustType<>()*/, Vector2.One.RotatedByRandom(Math.PI) * Main.rand.NextFloat(5)); d.customData = npc.Center; } npc.Center = spawnPoint + new Vector2(0, 320); flail.npc.ai[0] = 1; } if (GlobalTimer >= 120) { npc.alpha = 0; if (npc.Hitbox.Intersects(flail.npc.Hitbox)) { flail.npc.ai[0] = 0; flail.npc.ai[3] = 1; flail.npc.velocity *= 0; flail.npc.life = flail.npc.lifeMax; flail.npc.dontTakeDamage = false; flail.npc.friendly = false; npc.life -= 20000; Phase = (int)OvergrowBossPhase.SecondAttack; ResetAttack(); CombatText.NewText(npc.Hitbox, Color.Red, 20000, true); Main.PlaySound(SoundID.DD2_BetsyScream, npc.Center); Main.LocalPlayer.GetModPlayer <StarlightPlayer>().Shake += 30; for (int k = 0; k < 100; k++) { Dust d = Dust.NewDustPerfect(flail.npc.Center, DustType <Dusts.Stone>(), Vector2.One.RotatedByRandom(Math.PI) * Main.rand.NextFloat(5)); } } } } }