public override void OnFirstTick(NPC npc) { for (int i = 0; i < 9; i++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.Zombie, velocity: Main.rand.NextVector2Circular(8, 8)); } }
public override void HitEffect(int hitDirection, double damage) { if (NPC.life <= 0) { for (int i = 3; i <= 10; i++) { Vector2 pos = NPC.position + new Vector2(Main.rand.NextFloat(NPC.width), Main.rand.NextFloat(NPC.height)); if (!Main.dedServ) { Gore.NewGore(NPC.GetSource_FromThis(), pos, NPC.velocity, ModContent.Find <ModGore>(Mod.Name, $"TimberGore{i}").Type, NPC.scale); } } if (spawnPhase2) { FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromAI(), NPC.Center, ModContent.NPCType <TimberChampionHead>(), NPC.whoAmI, target: NPC.target); } FargoSoulsUtil.GrossVanillaDodgeDust(NPC); for (int i = 0; i < 6; i++) { ExplodeDust(NPC.position + new Vector2(Main.rand.Next(NPC.width), Main.rand.Next(NPC.height))); } } }
public override void OnFirstTick(NPC npc) { base.OnFirstTick(npc); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center + 100 * Vector2.UnitX, NPCID.MothronSpawn); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center - 100 * Vector2.UnitX, NPCID.MothronSpawn); }
public override void Kill(int timeLeft) { if (FargoSoulsWorld.EternityMode) { FargoSoulsUtil.NewNPCEasy(Terraria.Entity.InheritSource(Projectile), Projectile.Top - 20 * Vector2.UnitY, ModContent.NPCType <LesserSquirrel>(), velocity: new Vector2(Main.rand.NextFloat(-10, 10), Main.rand.NextFloat(-20, -10))); } if (Main.netMode != NetmodeID.MultiplayerClient) { Player player = FargoSoulsUtil.PlayerExists(Projectile.ai[0]); if (player != null) { for (int i = 0; i < 10; i++) { Vector2 spawnPos = Projectile.position; spawnPos.X += Projectile.width / 2f + Main.rand.NextFloat(-40, 40); spawnPos.Y += 40 + Main.rand.NextFloat(-40, 40); const float gravity = 0.2f; float time = 30f; Vector2 distance = player.Center - spawnPos; distance.X = Main.rand.NextFloat(-1.5f, 1.5f); distance.Y = distance.Y / time - 0.5f * gravity * time; float minimumY = Main.rand.NextFloat(-12f, -9f); if (distance.Y > minimumY) { distance.Y = minimumY; } distance += Main.rand.NextVector2Square(-0.5f, 0.5f); Projectile.NewProjectile(Terraria.Entity.InheritSource(Projectile), spawnPos, distance, ModContent.ProjectileType <TimberAcorn>(), Projectile.damage, Projectile.knockBack, Projectile.owner); } } } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (Main.netMode != NetmodeID.MultiplayerClient) { if (Main.rand.NextBool(5)) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.CursedSkull); } for (int i = 0; i < 15; i++) { Vector2 speed = new Vector2(Main.rand.Next(-50, 51), Main.rand.Next(-100, 1)); speed.Normalize(); speed *= Main.rand.NextFloat(3f, 6f); speed.Y -= Math.Abs(speed.X) * 0.2f; speed.Y -= 3f; if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, speed, ProjectileID.SkeletonBone, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer); } } } }
public override bool PreAI(NPC npc) { bool result = base.PreAI(npc); if (FargoSoulsWorld.SwarmActive) { return(result); } NPC head = FargoSoulsUtil.NPCExists(npc.ai[1], NPCID.SkeletronHead); if (head != null && (head.ai[1] == 1f || head.ai[1] == 2f)) //spinning or DG mode { if (AttackTimer > 0 && head.life >= head.lifeMax * .75) //for a short period { if (--AttackTimer < 65) { Vector2 centerPoint = head.Center - 10 * 16 * Vector2.UnitY; if (!npc.HasValidTarget || npc.Distance(centerPoint) > 15 * 16) { AttackTimer++; //pause here, dont begin guardians attack until in range } else if (AttackTimer % 10 == 0 && Main.netMode != NetmodeID.MultiplayerClient) //periodic below 50% { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, npc.DirectionTo(Main.player[npc.target].Center), ModContent.ProjectileType <SkeletronGuardian2>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer); } } } } else { if (AttackTimer != 65 + 150) { AttackTimer = 65 + 150; if (Main.netMode != NetmodeID.MultiplayerClient && npc.HasPlayerTarget) //throw undead miner { float gravity = 0.4f; //shoot down const float time = 60f; Vector2 distance = Main.player[npc.target].Top - npc.Center + Main.rand.NextVector2Circular(80, 80); distance.X = distance.X / time; distance.Y = distance.Y / time - 0.5f * gravity * time; FargoSoulsUtil.NewNPCEasy( npc.GetSource_FromAI(), npc.Center, Main.rand.Next(new int[] { NPCID.BoneThrowingSkeleton, NPCID.BoneThrowingSkeleton2, NPCID.BoneThrowingSkeleton3, NPCID.BoneThrowingSkeleton4 }), velocity: distance); } } } return(result); }
public override void OnKill() { NPC.SetEventFlagCleared(ref FargoSoulsWorld.downedBoss[(int)FargoSoulsWorld.Downed.TrojanSquirrel], -1); if (ModContent.TryFind("Fargowiltas", "Squirrel", out ModNPC squrrl) && !NPC.AnyNPCs(squrrl.Type)) { FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromThis(), NPC.Center, squrrl.Type); } }
public override void OnFirstTick(NPC npc) { base.OnFirstTick(npc); for (int i = 0; i < 6; i++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromThis(), npc.Center, NPCID.DarkCaster, velocity: Main.rand.NextVector2Circular(8, 8)); } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (Main.rand.NextBool()) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.Ghost); } }
public void BeCompanionCube() { Player player = Main.player[Projectile.owner]; Color color; color = Lighting.GetColor((int)Projectile.Center.X / 16, (int)Projectile.Center.Y / 16); Vector3 vector3_1 = color.ToVector3(); color = Lighting.GetColor((int)player.Center.X / 16, (int)player.Center.Y / 16); Vector3 vector3_2 = color.ToVector3(); if (vector3_1.Length() < 0.15f && vector3_2.Length() < 0.15) { notlocalai1 += 1; } else if (notlocalai1 > 0) { notlocalai1 -= 1; } notlocalai1 = MathHelper.Clamp(notlocalai1, -3600f, 600); if (notlocalai1 > Main.rand.Next(300, 600) && !player.immune) { notlocalai1 = Main.rand.Next(30) * -10 - 300; switch (Main.rand.Next(3)) { case 0: //stab if (Projectile.owner == Main.myPlayer) { SoundEngine.PlaySound(SoundID.Item1, Projectile.Center); player.Hurt(Terraria.DataStructures.PlayerDeathReason.ByOther(6), 777, 0, false, false, false, -1); player.immune = false; player.immuneTime = 0; } break; case 1: //spawn mutant if (Main.netMode != NetmodeID.MultiplayerClient) { FargoSoulsUtil.NewNPCEasy(Projectile.GetSource_FromThis(), Projectile.Center, ModContent.NPCType <NPCs.MutantBoss.MutantBoss>()); FargoSoulsUtil.PrintLocalization($"Mods.{Mod.Name}.Message.{Name}MutantBoss", 175, 75, 255); } break; default: if (Projectile.owner == Main.myPlayer) { CombatText.NewText(Projectile.Hitbox, Color.LimeGreen, Language.GetTextValue($"Mods.{Mod.Name}.Message.{Name}NotSafe")); } break; } } }
public override void AI(NPC npc) { base.AI(npc); if (++AttackTimer > 420) { AttackTimer = 0; FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.ChaosBall); } }
private void ManualSpawn(NPC npc, int type) { if (Main.netMode != NetmodeID.MultiplayerClient) { int n = FargoSoulsUtil.NewNPCEasy(Terraria.Entity.InheritSource(Projectile), npc.Center, type); if (n != Main.maxNPCs) { FargoSoulsUtil.PrintText(Main.npc[n].FullName + " has awoken!", 175, 75, 255); } } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (Main.rand.NextBool(5)) { for (int i = 0; i < 4; i++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.WallCreeper, velocity: new Vector2(Main.rand.NextFloat(-5f, 5f), -Main.rand.NextFloat(10f))); } } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (npc.type == NPCID.BlueSlime) { void SplitIntoSlimes(int type, int amount) { if (Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < amount; i++) { if (Main.rand.Next(3) != 0) { continue; } int n = FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, type, velocity: new Vector2(npc.velocity.X * 2, npc.velocity.Y)); if (n != Main.maxNPCs) { Main.npc[n].velocity.X += Main.rand.Next(-20, 20) * 0.1f + i * npc.direction * 0.3f; Main.npc[n].velocity.Y -= Main.rand.Next(0, 10) * 0.1f + i; } } } } switch (npc.netID) { case NPCID.YellowSlime: SplitIntoSlimes(NPCID.PurpleSlime, 2); break; case NPCID.PurpleSlime: SplitIntoSlimes(NPCID.RedSlime, 2); break; case NPCID.RedSlime: SplitIntoSlimes(NPCID.GreenSlime, 2); break; case NPCID.Pinky: SplitIntoSlimes(NPCID.YellowSlime, 2); SplitIntoSlimes(NPCID.MotherSlime, 1); break; default: break; } } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (NPC.downedPlantBoss && Main.netMode != NetmodeID.MultiplayerClient) { int n = FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.Paladin, velocity: new Vector2(Main.rand.NextFloat(-10, 10), Main.rand.NextFloat(-10, 0))); if (n != Main.maxNPCs) { Main.npc[n].GetEModeNPCMod <Paladin>().IsSmallPaladin = true; } } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (Main.rand.NextBool(3) && Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < 4; i++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.DemonEye, velocity: new Vector2(Main.rand.NextFloat(-3, 3), Main.rand.NextFloat(-3, 3))); } } }
public override void OnFirstTick(NPC npc) { base.OnFirstTick(npc); if (npc.type == NPCID.CultistDragonHead) { if (FargoSoulsWorld.MasochistModeReal && FargoSoulsUtil.BossIsAlive(ref EModeGlobalNPC.cultBoss, NPCID.CultistBoss)) { npc.Center = Main.npc[EModeGlobalNPC.cultBoss].Center; } if (NPC.CountNPCS(NPCID.AncientCultistSquidhead) < 4 && Main.netMode != NetmodeID.MultiplayerClient) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.AncientCultistSquidhead); } } }
public override void AI(NPC npc) { base.AI(npc); Counter++; if (IsFakeBat) { if (Main.netMode == NetmodeID.Server && Counter <= 65 && Counter % 15 == 5) //mp sync { npc.netUpdate = true; NetSync(npc); } if (npc.alpha > 200) { npc.alpha = 200; } if (npc.lifeMax > 100) { npc.lifeMax = 100; } if (npc.life > npc.lifeMax) { npc.life = npc.lifeMax; } } else if (Counter > 600) { Counter = 0; if (npc.HasPlayerTarget && npc.Distance(Main.player[npc.target].Center) < 1000 && Main.netMode != NetmodeID.MultiplayerClient && NPC.CountNPCS(NPCID.IlluminantBat) < 10) { int bat = FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, npc.type, velocity: new Vector2(Main.rand.NextFloat(-5, 5), Main.rand.NextFloat(-5, 5))); if (bat != Main.maxNPCs) { Main.npc[bat].GetEModeNPCMod <IlluminantBat>().IsFakeBat = true; } } } }
public override void HitEffect(NPC npc, int hitDirection, double damage) { base.HitEffect(npc, hitDirection, damage); if (!FargoSoulsWorld.SwarmActive) { NPC cultist = FargoSoulsUtil.NPCExists(npc.ai[3], NPCID.CultistBoss); //yes, this spawns two clones without the check if (cultist != null && NPC.CountNPCS(npc.type) < (FargoSoulsWorld.MasochistModeReal ? Math.Min(TotalCultistCount + 1, 12) : TotalCultistCount)) { if (Main.netMode != NetmodeID.MultiplayerClient) { FargoSoulsUtil.NewNPCEasy(cultist.GetSource_FromAI(), npc.Center, NPCID.CultistBossClone, 0, npc.ai[0], npc.ai[1], npc.ai[2], npc.ai[3], npc.target); } } } }
public override void AI(NPC npc) { base.AI(npc); if (++Counter >= 300 && Counter % 20 == 0) { int t = npc.HasPlayerTarget ? npc.target : npc.FindClosestPlayer(); if (t != -1 && npc.Distance(Main.player[t].Center) < 800 && Main.netMode != NetmodeID.MultiplayerClient) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.BurningSphere); } } if (Counter > 420) { Counter = 0; } }
public override void OnKill(NPC npc) { base.OnKill(npc); switch (npc.type) { case NPCID.SmallSlimedZombie: case NPCID.SlimedZombie: case NPCID.BigSlimedZombie: case NPCID.ArmedZombieSlimed: if (Main.rand.NextBool() && Main.netMode != NetmodeID.MultiplayerClient) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.BlueSlime); } break; default: break; } }
public override void OnKill(NPC npc) { base.OnKill(npc); if (Main.netMode != NetmodeID.MultiplayerClient && Main.hardMode && Main.rand.NextBool()) { if (NPC.CountNPCS(NPCID.FungiSpore) < 24) { for (int i = 0; i < 8; i++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_Death(), npc.Center, NPCID.FungiSpore, velocity: 0.5f * new Vector2(Main.rand.NextFloat(-5, 5), Main.rand.NextFloat(-5, 5))); } } else if (npc.type != NPCID.SporeBat) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_Death(), npc.Center, NPCID.SporeBat, velocity: 0.5f * new Vector2(Main.rand.NextFloat(-5, 5), Main.rand.NextFloat(-5, 5))); } } }
public override bool PreAI(NPC npc) { bool result = base.PreAI(npc); EModeGlobalNPC.skeleBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(result); } if (!SpawnedArms && npc.life < npc.lifeMax * .25) { SpawnedArms = true; FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.SkeletronHand, npc.whoAmI, 1f, npc.whoAmI, 0f, 0f, npc.target); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.SkeletronHand, npc.whoAmI, -1f, npc.whoAmI, 0f, 0f, npc.target); string text = Language.GetTextValue($"Mods.{mod.Name}.Message.SkeletronRegrow"); FargoSoulsUtil.PrintLocalization($"{npc.FullName} {text}", new Color(175, 75, 255)); } if (npc.ai[1] == 0f) { if (npc.ai[2] == 800 - 90) //telegraph spin { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <TargetingReticle>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type); } } if (npc.ai[2] < 800 - 5) { ReticleTarget = npc.target; } } if (npc.ai[1] == 1f || npc.ai[1] == 2f) //spinning or DG mode { //force targeted player back to the one i telegraphed with reticle (otherwise, may target another player when spin starts) if (ReticleTarget > -1 && ReticleTarget < Main.maxPlayers) { npc.target = ReticleTarget; ReticleTarget = -1; npc.netUpdate = true; NetSync(npc); if (!npc.HasValidTarget) { npc.TargetClosest(false); } if (npc.ai[1] == 1) //do cross guardian attack { if (!FargoSoulsWorld.MasochistModeReal) { for (int i = 0; i < Main.maxProjectiles; i++) //also clear leftover babies { if (Main.projectile[i].active && Main.projectile[i].hostile && Main.projectile[i].type == ModContent.ProjectileType <SkeletronGuardian2>()) { Main.projectile[i].Kill(); } } } if ((npc.life >= npc.lifeMax * .75 || FargoSoulsWorld.MasochistModeReal) && Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < 4; i++) { for (int j = -2; j <= 2; j++) { Vector2 spawnPos = new Vector2(1200, 80 * j); Vector2 vel = -8 * Vector2.UnitX; spawnPos = Main.player[npc.target].Center + spawnPos.RotatedBy(Math.PI / 2 * (i + 0.5)); vel = vel.RotatedBy(Math.PI / 2 * (i + 0.5)); int p = Projectile.NewProjectile(npc.GetSource_FromThis(), spawnPos, vel, ModContent.ProjectileType <Projectiles.Champions.ShadowGuardian>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer); if (p != Main.maxProjectiles) { Main.projectile[p].timeLeft = 1200 / 8 + 1; } } } } } } float ratio = (float)npc.life / npc.lifeMax; float cooldown = 20f; if (!FargoSoulsWorld.MasochistModeReal) { cooldown += 100f * ratio; } if (++npc.localAI[2] >= cooldown) //spray bones { npc.localAI[2] = 0f; if (cooldown > 0 && npc.HasPlayerTarget && Main.netMode != NetmodeID.MultiplayerClient) { Vector2 speed = Vector2.Normalize(Main.player[npc.target].Center - npc.Center) * 6f; for (int i = 0; i < 8; i++) { Vector2 vel = speed.RotatedBy(Math.PI * 2 / 8 * i); vel += npc.velocity * (1f - ratio); vel.Y -= Math.Abs(vel.X) * 0.2f; Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, vel, ModContent.ProjectileType <SkeletronBone>(), npc.defDamage / 9 * 2, 0f, Main.myPlayer); } } } if (BabyGuardianTimer > 180) { BabyGuardianTimer = 180; } if (npc.life < npc.lifeMax * .75 && npc.ai[1] == 1f && --BabyGuardianTimer < 0) { BabyGuardianTimer = 180; SoundEngine.PlaySound(SoundID.ForceRoarPitched, npc.Center); if (Main.netMode != NetmodeID.MultiplayerClient) //spray of baby guardian missiles { const int max = 30; float modifier = 1f - (float)npc.life / npc.lifeMax; modifier *= 4f / 3f; //scaling maxes at 25% life if (modifier > 1f || FargoSoulsWorld.MasochistModeReal) //cap it, or force it to cap in emode { modifier = 1f; } int actualNumberToSpawn = (int)(max * modifier); for (int i = 0; i < actualNumberToSpawn; i++) { float speed = Main.rand.NextFloat(3f, 9f); Vector2 velocity = speed * npc.DirectionFrom(Main.player[npc.target].Center).RotatedBy(Math.PI * (Main.rand.NextDouble() - 0.5)); float ai1 = speed / (60f + Main.rand.NextFloat(actualNumberToSpawn * 2)); Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, velocity, ModContent.ProjectileType <SkeletronGuardian>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 0.8f), 0f, Main.myPlayer, 0f, ai1); } } } } else { if (npc.ai[2] == 0) { //compensate for not changing targets when beginning spin npc.TargetClosest(false); //prevent skeletron from firing his stupid tick 1 no telegraph skull right after finishing spin if (!FargoSoulsWorld.MasochistModeReal) { npc.ai[2] = 1; } } if (npc.life < npc.lifeMax * .75) //phase 2 { if (npc.ai[2] <= 60 && npc.ai[2] % 10 == 0) //vomit skeletons { int[] skeletons = { NPCID.BoneThrowingSkeleton, NPCID.BoneThrowingSkeleton2, NPCID.BoneThrowingSkeleton3, NPCID.BoneThrowingSkeleton4 }; if (Main.npc.Count(n => n.active && skeletons.Contains(n.type)) < 12) { float gravity = 0.4f; //shoot down const float time = 60f; Vector2 distance = Main.player[npc.target].Top - npc.Center + Main.rand.NextVector2Circular(80, 80); distance.X = distance.X / time; distance.Y = distance.Y / time - 0.5f * gravity * time; FargoSoulsUtil.NewNPCEasy( npc.GetSource_FromAI(), npc.Center, Main.rand.Next(skeletons), velocity: distance); SoundEngine.PlaySound(SoundID.NPCDeath13, npc.Center); } } if (--BabyGuardianTimer < 0) { BabyGuardianTimer = FargoSoulsWorld.MasochistModeReal ? 180 : 240; SoundEngine.PlaySound(SoundID.ForceRoarPitched, npc.Center); for (int j = -1; j <= 1; j++) //to both sides { if (j == 0) { continue; } const int gap = 40; const int max = 14; float modifier = 1f - (float)npc.life / npc.lifeMax; modifier *= 4f / 3f; //scaling maxes at 25% life if (modifier > 1f || FargoSoulsWorld.MasochistModeReal) //cap it, or force it to cap in emode { modifier = 1f; } int actualNumberToSpawn = (int)(max * modifier); Vector2 baseVel = npc.DirectionTo(Main.player[npc.target].Center).RotatedBy(MathHelper.ToRadians(gap) * j); for (int k = 0; k < actualNumberToSpawn; k++) //a fan of skulls { if (Main.netMode != NetmodeID.MultiplayerClient) { float velModifier = 1f + 9f * k / max; Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, velModifier * baseVel.RotatedBy(MathHelper.ToRadians(10) * j * k), ModContent.ProjectileType <SkeletronGuardian2>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 0.8f), 0f, Main.myPlayer); } } } if (Main.netMode != NetmodeID.MultiplayerClient) //one more shot straight behind skeletron { float velModifier = 10f; Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, velModifier * npc.DirectionFrom(Main.player[npc.target].Center), ModContent.ProjectileType <SkeletronGuardian2>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 0.8f), 0f, Main.myPlayer); } } } } if (npc.ai[1] == 2f) { npc.defense = 9999; npc.damage = npc.defDamage * 15; if (!Main.dayTime && !FargoSoulsWorld.MasochistModeReal) { if (++DGSpeedRampup < 120) { npc.position -= npc.velocity * (120 - DGSpeedRampup) / 120; } } } EModeUtils.DropSummon(npc, "SuspiciousSkull", NPC.downedBoss3, ref DroppedSummon); return(result); }
public override bool PreAI(NPC npc) { bool result = base.PreAI(npc); EModeGlobalNPC.moonBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(result); } if (!SpawnedRituals) { SpawnedRituals = true; VulnerabilityState = 0; if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <LunarRitual>(), 25, 0f, Main.myPlayer, 0f, npc.whoAmI); Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <FragmentRitual>(), 0, 0f, Main.myPlayer, 0f, npc.whoAmI); } } if (Main.LocalPlayer.active && !Main.LocalPlayer.dead && !Main.LocalPlayer.ghost && VulnerabilityState >= 0 && VulnerabilityState <= 3) { Main.LocalPlayer.AddBuff(ModContent.BuffType <NullificationCurse>(), 2); } npc.position -= npc.velocity * 2f / 3f; //SLOW DOWN if (npc.dontTakeDamage) { if (AttackTimer == 370 && Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; if (bodyPart.active) { Projectile.NewProjectile(npc.GetSource_FromThis(), bodyPart.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, bodyPart.whoAmI, bodyPart.type); } } } if (AttackTimer > 400) { AttackTimer = 0; npc.netUpdate = true; NetSync(npc); switch (VulnerabilityState) { case 0: //melee for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; if (bodyPart.active) { int damage = 30; for (int j = -2; j <= 2; j++) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), bodyPart.Center, 6f * bodyPart.DirectionFrom(Main.player[npc.target].Center).RotatedBy(Math.PI / 2 / 4 * j), ModContent.ProjectileType <MoonLordFireball>(), damage, 0f, Main.myPlayer, 20, 20 + 60); } } } } break; case 1: //ranged for (int j = 0; j < 6; j++) { Vector2 spawn = Main.player[npc.target].Center + 500 * npc.DirectionFrom(Main.player[npc.target].Center).RotatedBy(MathHelper.TwoPi / 6 * (j + 0.5f)); if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, Vector2.Zero, ModContent.ProjectileType <LightningVortexHostile>(), 30, 0f, Main.myPlayer, 1, Main.player[npc.target].DirectionFrom(spawn).ToRotation()); } } break; case 2: //magic for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; if (bodyPart.active && ((i == 2 && bodyPart.type == NPCID.MoonLordHead) || bodyPart.type == NPCID.MoonLordHand)) { int damage = 35; const int max = 6; for (int j = 0; j < max; j++) { if (Main.netMode != NetmodeID.MultiplayerClient) { int p = Projectile.NewProjectile(npc.GetSource_FromThis(), bodyPart.Center, 2.5f * bodyPart.DirectionFrom(Main.player[npc.target].Center).RotatedBy(Math.PI * 2 / max * (j + 0.5)), ModContent.ProjectileType <MoonLordNebulaBlaze>(), damage, 0f, Main.myPlayer); if (p != Main.maxProjectiles) { Main.projectile[p].timeLeft = 1200; } } } } } break; case 3: //summoner for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; if (bodyPart.active && ((i == 2 && bodyPart.type == NPCID.MoonLordHead) || bodyPart.type == NPCID.MoonLordHand)) { Vector2 speed = Main.player[npc.target].Center - bodyPart.Center; speed.Normalize(); speed *= 5f; for (int j = -1; j <= 1; j++) { Vector2 vel = speed.RotatedBy(MathHelper.ToRadians(15) * j); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), bodyPart.Center, NPCID.AncientLight, 0, 0f, (Main.rand.NextFloat() - 0.5f) * 0.3f * 6.28318548202515f / 60f, vel.X, vel.Y, velocity: vel); } } } break; default: //phantasmal eye rings if (Main.netMode != NetmodeID.MultiplayerClient) { const int max = 4; const int speed = 8; const float rotationModifier = 0.5f; int damage = 40; float rotation = 2f * (float)Math.PI / max; Vector2 vel = Vector2.UnitY * speed; int type = ModContent.ProjectileType <Projectiles.MutantBoss.MutantSphereRing>(); for (int i = 0; i < max; i++) { vel = vel.RotatedBy(rotation); if (Main.netMode != NetmodeID.MultiplayerClient) { int p = Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, vel, type, damage, 0f, Main.myPlayer, rotationModifier, speed); if (p != Main.maxProjectiles) { Main.projectile[p].timeLeft = 1800 - VulnerabilityTimer; } p = Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, vel, type, damage, 0f, Main.myPlayer, -rotationModifier, speed); if (p != Main.maxProjectiles) { Main.projectile[p].timeLeft = 1800 - VulnerabilityTimer; } } } SoundEngine.PlaySound(SoundID.Item84, npc.Center); } break; } } } else //only when vulnerable { if (!EnteredPhase2) { EnteredPhase2 = true; AttackTimer = 0; SoundEngine.PlaySound(SoundID.Roar, Main.LocalPlayer.Center); npc.netUpdate = true; NetSync(npc); } Player player = Main.player[npc.target]; switch (VulnerabilityState) { case 0: //melee { if (AttackTimer > 30) { AttackTimer -= 300; AttackMemory = AttackMemory == 0 ? 1 : 0; float handToAttackWith = npc.localAI[AttackMemory]; if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[(int)handToAttackWith].Center, Vector2.Zero, ModContent.ProjectileType <MoonLordSun>(), 60, 0f, Main.myPlayer, npc.whoAmI, handToAttackWith); } } } break; case 1: //vortex { if (AttackMemory == 0) //spawn the vortex { AttackMemory = 1; for (int i = -1; i <= 1; i += 2) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <MoonLordVortex>(), 40, 0f, Main.myPlayer, i, npc.whoAmI); } } } } break; case 2: //nebula { if (AttackTimer > 30) { AttackTimer -= 360; for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; int damage = 35; for (int j = -2; j <= 2; j++) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), bodyPart.Center, 2.5f * bodyPart.DirectionFrom(Main.player[npc.target].Center).RotatedBy(Math.PI / 2 / 2 * (j + Main.rand.NextFloat(-0.25f, 0.25f))), ModContent.ProjectileType <MoonLordNebulaBlaze2>(), damage, 0f, Main.myPlayer, npc.whoAmI); } } } } } break; case 3: //stardust { if (AttackTimer > 360) { AttackTimer -= 360; AttackMemory = 0; } float baseRotation = MathHelper.ToRadians(50); if (++AttackMemory == 10) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[(int)npc.localAI[0]].Center, Main.npc[(int)npc.localAI[0]].DirectionTo(player.Center), ModContent.ProjectileType <PhantasmalDeathrayMLSmall>(), 60, 0f, Main.myPlayer, baseRotation * Main.rand.NextFloat(0.9f, 1.1f), npc.localAI[0]); } } else if (AttackMemory == 20) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[(int)npc.localAI[1]].Center, Main.npc[(int)npc.localAI[2]].DirectionTo(player.Center), ModContent.ProjectileType <PhantasmalDeathrayMLSmall>(), 60, 0f, Main.myPlayer, -baseRotation * Main.rand.NextFloat(0.9f, 1.1f), npc.localAI[1]); } } else if (AttackMemory == 30) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[(int)npc.localAI[2]].Center, Main.npc[(int)npc.localAI[1]].DirectionTo(player.Center), ModContent.ProjectileType <PhantasmalDeathrayMLSmall>(), 60, 0f, Main.myPlayer, baseRotation * Main.rand.NextFloat(0.9f, 1.1f), npc.localAI[2]); } } else if (AttackMemory == 40) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, npc.DirectionTo(player.Center), ModContent.ProjectileType <PhantasmalDeathrayMLSmall>(), 60, 0f, Main.myPlayer, -baseRotation * Main.rand.NextFloat(0.9f, 1.1f), npc.whoAmI); } } } break; default: //any { if (AttackMemory == 0) //spawn the moons { AttackMemory = 1; foreach (Projectile p in Main.projectile.Where(p => p.active && p.hostile)) { if (p.type == ModContent.ProjectileType <LunarRitual>() && p.ai[1] == npc.whoAmI) //find my arena { if (Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < 4; i++) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, p.DirectionTo(Main.player[npc.target].Center).RotatedBy(MathHelper.TwoPi / 4 * i), ModContent.ProjectileType <MoonLordMoon>(), 60, 0f, Main.myPlayer, p.identity, 1450); } for (int i = 0; i < 4; i++) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, p.DirectionTo(Main.player[npc.target].Center).RotatedBy(MathHelper.TwoPi / 4 * (i + 0.5f)), ModContent.ProjectileType <MoonLordMoon>(), 60, 0f, Main.myPlayer, p.identity, -950); } } break; } } } } break; } } if (npc.ai[0] == 2f) //moon lord is dead { VulnerabilityState = 4; VulnerabilityTimer = 0; AttackTimer = 0; } else //moon lord isn't dead { int increment = (int)Math.Max(1, (1f - (float)npc.life / npc.lifeMax) * 4); if (FargoSoulsWorld.MasochistModeReal) { increment++; } VulnerabilityTimer += increment; AttackTimer += increment; if (VulnerabilityTimer > 1800) //next vuln phase { VulnerabilityState = ++VulnerabilityState % 5; VulnerabilityTimer = 0; AttackTimer = 0; AttackMemory = 0; npc.netUpdate = true; NetSync(npc); if (FargoSoulsWorld.MasochistModeReal) { switch (VulnerabilityState) { case 0: //melee for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; if (bodyPart.active && bodyPart.type == NPCID.MoonLordHead) { for (int j = -3; j <= 3; j++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), bodyPart.Center, NPCID.SolarGoop, target: npc.target, velocity: -10f * Vector2.UnitY.RotatedBy(MathHelper.ToRadians(20 * j))); } } } break; case 1: //ranged if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile( npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <MoonLordVortexOld>(), 40, 0f, Main.myPlayer, 0, npc.whoAmI); } break; case 2: //magic if (Main.netMode != NetmodeID.MultiplayerClient) { for (int i = -1; i <= 1; i++) { int p = Projectile.NewProjectile( npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowLine>(), 0, 0f, Main.myPlayer, 17f, npc.whoAmI); if (p != Main.maxProjectiles) { Main.projectile[p].localAI[0] = 950f * i; if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncProjectile, number: p); } } } } break; case 3: //summon for (int i = 0; i < 3; i++) { NPC bodyPart = Main.npc[(int)npc.localAI[i]]; if (bodyPart.active) { for (int j = -2; j <= 2; j++) { Vector2 vel = 9f * bodyPart.DirectionTo(Main.player[npc.target].Center).RotatedBy(MathHelper.Pi / 5 * j); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), bodyPart.Center, NPCID.AncientLight, 0, 0f, (Main.rand.NextFloat() - 0.5f) * 0.3f * 6.28318548202515f / 60f, vel.X, vel.Y, npc.target, vel); } } } break; default: if (Main.netMode != NetmodeID.MultiplayerClient) { const int max = 8; const int speed = 8; const float rotationModifier = 0.5f; int damage = 40; float rotation = 2f * (float)Math.PI / max; Vector2 vel = Vector2.UnitY * speed; int type = ModContent.ProjectileType <Projectiles.MutantBoss.MutantSphereRing>(); for (int i = 0; i < max; i++) { vel = vel.RotatedBy(rotation); Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, vel, type, damage, 0f, Main.myPlayer, rotationModifier, speed); Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, vel, type, damage, 0f, Main.myPlayer, -rotationModifier, speed); } SoundEngine.PlaySound(SoundID.Item84, npc.Center); } break; } } } } //because 1.4 is f*****g stupid and time freeze prevents custom skies from working I HATE 1.4 if (Main.GameModeInfo.IsJourneyMode && CreativePowerManager.Instance.GetPower <CreativePowers.FreezeTime>().Enabled) { CreativePowerManager.Instance.GetPower <CreativePowers.FreezeTime>().SetPowerInfo(false); } if (!Main.dedServ && VulnerabilityTimer % 30 == 0 && NPC.FindFirstNPC(npc.type) == npc.whoAmI) { if (!SkyManager.Instance["FargowiltasSouls:MoonLordSky"].IsActive()) { SkyManager.Instance.Activate("FargowiltasSouls:MoonLordSky"); } void HandleScene(string name) { if (!Filters.Scene[$"FargowiltasSouls:{name}"].IsActive()) { Filters.Scene.Activate($"FargowiltasSouls:{name}"); } } switch (VulnerabilityState) { case 0: HandleScene("Solar"); break; case 1: HandleScene("Vortex"); break; case 2: HandleScene("Nebula"); break; case 3: HandleScene("Stardust"); if (VulnerabilityTimer < 120) //so that player isn't punished for using weapons during prior phase { Main.LocalPlayer.GetModPlayer <EModePlayer>().MasomodeMinionNerfTimer = 0; } break; default: break; } } EModeUtils.DropSummon(npc, "CelestialSigil2", NPC.downedMoonlord, ref DroppedSummon, NPC.downedAncientCultist); return(result); }
public override bool PreAI(NPC npc) { EModeGlobalNPC.betsyBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(true); } if (FargoSoulsWorld.MasochistModeReal) { for (int i = 0; i < 3; i++) { Rectangle rectangle = new Rectangle((int)Main.screenPosition.X + Main.screenWidth / 3, (int)Main.screenPosition.Y + Main.screenHeight / 3, Main.screenWidth / 3, Main.screenHeight / 3); CombatText.NewText(rectangle, new Color(100 + Main.rand.Next(150), 100 + Main.rand.Next(150), 100 + Main.rand.Next(150)), Main.rand.Next(new List <string> { "CRINGE", "NOT POGGERS", "MONKAS", "SHOW WINGS", "AERIAL BANE POG", "REAL BOSS WHEN?", "#NOTMYMASOMODE", "OOA BAD ANYWAY", "COPE MALD SEETHE", "GET REAL", "GET FAKE", "POGGERS", "ResidentSleeper", "If you can read this say 22", "GuraSit", "play calamity", "play thorium", "hardcore 1hp challenge when?", "now do it with a copper shortsword", "Zenith Yoyo?", "guys how do i beat moon lord", "GUYS I GOT TERRAPRISMA", "how do i install this update", "Hi YouTube!", "<Message was deleted by staff>", $"<User {Main.rand.Next(10)}{Main.rand.Next(10)}{Main.rand.Next(10)}{Main.rand.Next(10)}{Main.rand.Next(10)} was banned>", $"<User {Main.rand.Next(10)}{Main.rand.Next(10)}{Main.rand.Next(10)}{Main.rand.Next(10)}{Main.rand.Next(10)} was muted>", }), Main.rand.NextBool(), Main.rand.NextBool()); } if (Main.rand.NextBool(30) && npc.HasPlayerTarget) { switch (Main.rand.Next(12)) { case 0: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Thunder"), Main.player[npc.target].Center); } break; case 1: SoundEngine.PlaySound(SoundID.ScaryScream, Main.player[npc.target].Center); //arte scream break; case 2: SoundEngine.PlaySound(SoundID.Roar, Main.player[npc.target].Center); break; case 3: SoundEngine.PlaySound(SoundID.ForceRoarPitched, Main.player[npc.target].Center); //eoc roar break; case 4: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Monster94"), Main.player[npc.target].Center); } break; case 5: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Monster5") { Volume = 1.5f }, Main.player[npc.target].Center); } break; case 6: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Thunder") { Volume = 1.5f, Pitch = 1.5f }, Main.player[npc.target].Center); } break; case 7: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Zombie_104"), Main.player[npc.target].Center); } break; case 8: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Monster70"), Main.player[npc.target].Center); } break; case 9: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Railgun"), Main.player[npc.target].Center); } break; case 10: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/Navi"), Main.player[npc.target].Center); } break; case 11: if (!Main.dedServ) { SoundEngine.PlaySound(new SoundStyle("FargowiltasSouls/Sounds/ZaWarudo") { Volume = 1.5f }, Main.player[npc.target].Center); } break; default: SoundEngine.PlaySound(SoundID.NPCDeath10, Main.player[npc.target].Center); break; } } } if (!InPhase2 && npc.life < npc.lifeMax / 2) { InPhase2 = true; SoundEngine.PlaySound(SoundID.Roar, npc.Center); } if (npc.ai[0] == 6f) //when approaching for roar { if (npc.ai[1] == 0f) { npc.position += npc.velocity; } else if (npc.ai[1] == 1f) { DoFuryRingAttack = true; } } if (DoFuryRingAttack) { npc.velocity = Vector2.Zero; if (FuryRingTimer == 0) { if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRingHollow>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 4f / 3), 0f, Main.myPlayer, 4); } if (FargoSoulsWorld.MasochistModeReal) { if (NPC.CountNPCS(NPCID.DD2DarkMageT3) < 3) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, NPCID.DD2DarkMageT3, target: npc.target); } } } FuryRingTimer++; if (FuryRingTimer % 2 == 0) { if (Main.netMode != NetmodeID.MultiplayerClient) { float rotation = FuryRingShotRotationCounter; if (FargoSoulsWorld.MasochistModeReal && FuryRingTimer >= 30 && FuryRingTimer <= 60) { rotation += 1; //staggers each wave instead of lining them up behind each other } Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, -Vector2.UnitY.RotatedBy(2 * Math.PI / 30 * rotation), ModContent.ProjectileType <BetsyFury>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 4f / 3), 0f, Main.myPlayer, npc.target); Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, -Vector2.UnitY.RotatedBy(2 * Math.PI / 30 * -rotation), ModContent.ProjectileType <BetsyFury>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 4f / 3), 0f, Main.myPlayer, npc.target); } FuryRingShotRotationCounter++; } if (FuryRingTimer > (InPhase2 ? 90 : 30) + 2) { DoFuryRingAttack = false; InFuryRingAttackCooldown = true; FuryRingTimer = 0; FuryRingShotRotationCounter = 0; } EModeGlobalNPC.Aura(npc, 1200, BuffID.WitheredWeapon, true, 226); EModeGlobalNPC.Aura(npc, 1200, BuffID.WitheredArmor, true, 226); } if (InFuryRingAttackCooldown) { EModeGlobalNPC.Aura(npc, 1200, BuffID.WitheredWeapon, true, 226); EModeGlobalNPC.Aura(npc, 1200, BuffID.WitheredArmor, true, 226); if (++FuryRingShotRotationCounter > 90) { InFuryRingAttackCooldown = false; FuryRingTimer = 0; FuryRingShotRotationCounter = 0; } npc.position -= npc.velocity * 0.5f; if (FuryRingTimer % 2 == 0) { return(false); } } if (!DD2Event.Ongoing && npc.HasPlayerTarget && (!Main.player[npc.target].active || Main.player[npc.target].dead || npc.Distance(Main.player[npc.target].Center) > 3000)) { int p = Player.FindClosest(npc.Center, 0, 0); //extra despawn code for when summoned outside event if (p < 0 || !Main.player[p].active || Main.player[p].dead || npc.Distance(Main.player[p].Center) > 3000) { npc.active = false; } } EModeUtils.DropSummon(npc, "BetsyEgg", FargoSoulsWorld.downedBetsy, ref DroppedSummon, NPC.downedGolemBoss); return(true); }
public override void AI() { if (!spawned) { spawned = true; NPC.TargetClosest(false); if (Main.netMode != NetmodeID.MultiplayerClient) { head = FargoSoulsUtil.NPCExists(FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromThis(), NPC.Center, ModContent.NPCType <TrojanSquirrelHead>(), NPC.whoAmI, target: NPC.target)); arms = FargoSoulsUtil.NPCExists(FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromThis(), NPC.Center, ModContent.NPCType <TrojanSquirrelArms>(), NPC.whoAmI, target: NPC.target)); } //drop summon if (FargoSoulsWorld.EternityMode && !FargoSoulsWorld.downedBoss[(int)FargoSoulsWorld.Downed.TrojanSquirrel] && Main.netMode != NetmodeID.MultiplayerClient) { Item.NewItem(NPC.GetSource_Loot(), Main.player[NPC.target].Hitbox, ModContent.ItemType <SquirrelCoatofArms>()); } //start by jumping NPC.ai[0] = 1f; NPC.ai[3] = 1f; for (int i = 0; i < 80; i++) { int d = Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 4f); Main.dust[d].velocity.Y -= 1.5f; Main.dust[d].velocity *= 1.5f; Main.dust[d].noGravity = true; } FargoSoulsUtil.GrossVanillaDodgeDust(NPC); SoundEngine.PlaySound(SoundID.Roar, Main.player[NPC.target].Center); } Player player = Main.player[NPC.target]; NPC.direction = NPC.spriteDirection = NPC.Center.X < player.Center.X ? 1 : -1; bool despawn = false; switch ((int)NPC.ai[0]) { case 0: //mourning wood movement { Vector2 target = player.Bottom - Vector2.UnitY; if (NPC.localAI[0] > 0) //doing running attack { NPC.localAI[0] -= 1f; float distance = NPC.Center.X - target.X; bool passedTarget = Math.Sign(distance) == NPC.localAI[1]; if (passedTarget && Math.Abs(distance) > 160) { NPC.localAI[0] = 0f; } target = new Vector2(NPC.Center.X + 256f * NPC.localAI[1], target.Y); if (NPC.localAI[0] == 0f) { NPC.TargetClosest(false); } if (FargoSoulsWorld.EternityMode && head == null && NPC.localAI[0] % 3 == 0 && Main.netMode != NetmodeID.MultiplayerClient) { int p = Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Top.X, NPC.Top.Y, Main.rand.NextFloat(-5, 5), Main.rand.NextFloat(-5), Main.rand.Next(326, 329), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer); if (p != Main.maxProjectiles) { Main.projectile[p].timeLeft = 90; } } } else if (!NPC.HasValidTarget || NPC.Distance(player.Center) > (FargoSoulsWorld.EternityMode ? 1600 : 2400)) { target = NPC.Center + new Vector2(256f * Math.Sign(NPC.Center.X - player.Center.X), -128); NPC.TargetClosest(false); despawn = true; } if (Math.Abs(NPC.velocity.Y) < 0.05f && NPC.localAI[3] >= 2) { if (NPC.localAI[3] == 2) { NPC.localAI[3] = 0f; } else { NPC.localAI[3] -= 1; NPC.ai[0] = 1f; NPC.ai[3] = 1f; } SoundEngine.PlaySound(SoundID.Item14, NPC.Center); ExplodeAttack(); } bool goFast = despawn || NPC.localAI[0] > 0; Movement(target, goFast); if (arms != null && (NPC.localAI[3] == -1 || NPC.localAI[3] == 1)) //from arms { NPC.direction = NPC.spriteDirection = (int)NPC.localAI[3]; } bool canDoAttacks = FargoSoulsWorld.EternityMode && !goFast; if (canDoAttacks) //decide next action { float increment = 1f; if (head == null) { increment += 0.5f; } if (arms == null) { increment += 0.5f; } if (FargoSoulsWorld.MasochistModeReal) { increment += 1f; } if (NPC.dontTakeDamage) { increment /= 2; } if (target.Y > NPC.Top.Y) { NPC.ai[1] += increment; } else { NPC.ai[2] += increment; } if (Math.Abs(NPC.velocity.Y) < 0.05f) { //its structured like this to ensure body picks the right attack for the situation after being delayed by head/arms bool canProceed = !(head != null && head.ai[0] != 0) && !(arms != null && arms.ai[0] != 0); int threshold = 300; if (NPC.ai[1] > threshold) { if (canProceed) { NPC.ai[0] = 1f; NPC.ai[1] = 0f; //NPC.ai[2] = 0f; NPC.ai[3] = 0f; NPC.localAI[0] = 0f; NPC.netUpdate = true; } else { NPC.ai[1] -= 10f; } } if (NPC.ai[2] > threshold) { if (canProceed) { NPC.ai[0] = 1f; //NPC.ai[1] = 0f; NPC.ai[2] = 0f; NPC.ai[3] = 1f; NPC.localAI[0] = 0f; NPC.netUpdate = true; } else { NPC.ai[2] -= 10f; } } } } } break; case 1: //telegraph something { NPC.velocity.X *= 0.9f; TileCollision(player.Bottom.Y - 1 > NPC.Bottom.Y, Math.Abs(player.Center.X - NPC.Center.X) < NPC.width / 2 && NPC.Bottom.Y < player.Bottom.Y - 1); int threshold = 120; if (FargoSoulsWorld.EternityMode) { if (head == null) { threshold -= 20; } if (arms == null) { threshold -= 20; } if (head == null && arms == null) { threshold -= 30; } if (NPC.localAI[3] >= 2) { threshold -= 20; } } if (FargoSoulsWorld.MasochistModeReal) { threshold -= 20; } if (++NPC.localAI[0] > threshold) { NPC.localAI[0] = 0f; NPC.netUpdate = true; if (NPC.ai[3] == 0f) { NPC.ai[0] = 0f; NPC.localAI[0] = 300f; NPC.localAI[1] = Math.Sign(player.Center.X - NPC.Center.X); NPC.localAI[2] = player.Center.X; } else { NPC.ai[0] = 2f; } } } break; case 2: //jump { const float gravity = 0.4f; float time = FargoSoulsWorld.EternityMode && arms == null ? 60f : 90f; if (NPC.localAI[0]++ == 0) { Vector2 distance = player.Top - NPC.Bottom; if (FargoSoulsWorld.EternityMode && arms == null) { distance.X += NPC.width * Math.Sign(player.Center.X - NPC.Center.X); if (NPC.localAI[3] < 2) { NPC.localAI[3] = 2; //flag to stomp again on landing if (head == null) { NPC.localAI[3] += 2; //flag to do more stomps } } ExplodeAttack(); } distance.X = distance.X / time; distance.Y = distance.Y / time - 0.5f * gravity * time; NPC.velocity = distance; NPC.netUpdate = true; SoundEngine.PlaySound(SoundID.Item14, NPC.Center); } else { NPC.velocity.Y += gravity; } if (NPC.localAI[0] > time) { NPC.TargetClosest(false); NPC.velocity.X = Utils.Clamp(NPC.velocity.X, -20, 20); NPC.velocity.Y = Utils.Clamp(NPC.velocity.Y, -10, 10); NPC.ai[0] = 0f; NPC.localAI[0] = 0f; NPC.netUpdate = true; } } break; default: NPC.ai[0] = 0; goto case 0; } if (despawn) { if (NPC.timeLeft > 60) { NPC.timeLeft = 60; } } else { if (NPC.timeLeft < 600) { NPC.timeLeft = 600; } } if (head == null) { Vector2 pos = NPC.Top; pos.X += 2f * 16f * NPC.direction; pos.Y -= 8f; int width = 4 * 16; int height = 2 * 16; pos.X -= width / 2f; pos.Y -= height / 2f; for (int i = 0; i < 3; i++) { int d = Dust.NewDust(pos, width, height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 2.5f); Main.dust[d].velocity.Y -= 1.5f; Main.dust[d].velocity *= 1.5f; Main.dust[d].noGravity = true; } if (Main.rand.NextBool(3)) { int d = Dust.NewDust(pos, width, height, DustID.Torch, NPC.velocity.X * 0.4f, NPC.velocity.Y * 0.4f, 100, default(Color), 2.5f); Main.dust[d].noGravity = true; Main.dust[d].velocity.Y -= 3f; Main.dust[d].velocity *= 1.5f; } } else { lifeMaxHead = head.lifeMax; head = FargoSoulsUtil.NPCExists(head.whoAmI, ModContent.NPCType <TrojanSquirrelHead>()); } if (arms == null) { Vector2 pos = NPC.Center; pos.X -= 16f * NPC.direction; pos.Y -= 3f * 16f; int width = 2 * 16; int height = 2 * 16; pos.X -= width / 2f; pos.Y -= height / 2f; for (int i = 0; i < 2; i++) { int d = Dust.NewDust(pos, width, height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 1.5f); Main.dust[d].noGravity = true; } if (Main.rand.NextBool()) { int d2 = Dust.NewDust(pos, width, height, DustID.Torch, NPC.velocity.X * 0.4f, NPC.velocity.Y * 0.4f, 100, default(Color), 3f); Main.dust[d2].noGravity = true; } } else { lifeMaxArms = arms.lifeMax; arms = FargoSoulsUtil.NPCExists(arms.whoAmI, ModContent.NPCType <TrojanSquirrelArms>()); } if (NPC.life < NPC.lifeMax / 2 && Main.rand.NextBool(3)) { int d = Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 4f); Main.dust[d].velocity.Y -= 1.5f; Main.dust[d].velocity *= 1.5f; Main.dust[d].noGravity = true; } if (FargoSoulsWorld.EternityMode) { bool wasImmune = NPC.dontTakeDamage; NPC.dontTakeDamage = NPC.life < NPC.lifeMax / 2 && (head != null || arms != null); if (wasImmune != NPC.dontTakeDamage) { for (int i = 0; i < 6; i++) { ExplodeDust(NPC.position + new Vector2(Main.rand.Next(NPC.width), Main.rand.Next(NPC.height))); } } } else { NPC.dontTakeDamage = false; } }
public override bool PreAI(NPC npc) { EModeGlobalNPC.queenSlimeBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(true); } void TrySpawnMinions(ref bool check, double threshold) { if (!check && npc.life < npc.lifeMax * threshold) { check = true; FargoSoulsUtil.PrintLocalization($"Mods.{mod.Name}.Message.GelatinSubjects", new Color(175, 75, 255)); for (int i = 0; i < 6; i++) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, ModContent.NPCType <GelatinSubject>(), npc.whoAmI, target: npc.target, velocity: Main.rand.NextFloat(8f) * npc.DirectionFrom(Main.player[npc.target].Center).RotatedByRandom(MathHelper.PiOver2)); } if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type); } } } TrySpawnMinions(ref SpawnedMinions1, 0.75); TrySpawnMinions(ref SpawnedMinions2, 0.25); GelatinSubjectDR = NPC.AnyNPCs(ModContent.NPCType <GelatinSubject>()); npc.HitSound = GelatinSubjectDR ? SoundID.Item27 : SoundID.NPCHit1; //ai0 //0 = default //3 = chase? //4 = stomp //5 = shooty gels if (npc.ai[0] == 5) //when shooting, p1 and p2 { if (NPC.AnyNPCs(ModContent.NPCType <GelatinSubject>())) { npc.ai[1] -= 0.5f; } if (npc.ai[1] == 45 && --SpikeCounter < 0) //every few shots { SpikeCounter = 4; NetSync(npc); SoundEngine.PlaySound(SoundID.Roar, npc.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { Vector2 focus = Main.player[npc.target].Center; for (int i = 0; i < 50; i++) { Tile tile = Framing.GetTileSafely(focus); if (tile.HasUnactuatedTile && (Main.tileSolid[tile.TileType] || Main.tileSolidTop[tile.TileType])) { break; } focus.Y += 16f; } focus.Y -= Player.defaultHeight / 2f; for (int i = -5; i <= 5; i++) { Vector2 targetPos = focus; targetPos.X += 330 * i; float minionTravelTime = StompTravelTime + Main.rand.Next(30); float minionGravity = 0.4f; Vector2 vel = targetPos - npc.Center; vel.X = vel.X / minionTravelTime; vel.Y = vel.Y / minionTravelTime - 0.5f * minionGravity * minionTravelTime; FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, ModContent.NPCType <GelatinSlime>(), npc.whoAmI, minionTravelTime, minionGravity, vel.X, vel.Y, target: npc.target); } } } } if (npc.life > npc.lifeMax / 2) //phase 1 { if (StompTimer > 0 || (npc.ai[0] == 0 && npc.velocity.Y == 0)) { if (StompTimer < 0) { StompTimer++; } else { npc.ai[0] = 4; //activates trail visual } if (!Stompy(npc)) { return(false); } } } else //phase 2 { npc.defense = npc.defDefense / 2; if (RainTimer < 0) { RainTimer++; } if (RainTimer <= 0 && StompTimer < 0) //dont run timer during rain attack { StompTimer++; } if (npc.ai[0] == 0) //basic flying ai { if (RainTimer == 0) { if (npc.velocity.Y < 0) { npc.position.Y += npc.velocity.Y; } npc.ai[1] -= 1; //dont progress to next ai if (npc.HasValidTarget && Math.Abs(npc.Center.Y - (Main.player[npc.target].Center.Y - 250)) < 32) { RainTimer = 1; //begin attack NetSync(npc); npc.netUpdate = true; SoundEngine.PlaySound(SoundID.Roar, npc.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, npc.whoAmI, -16); } } } else if (RainTimer > 0) //actually doing rain { npc.velocity.X *= 0.9f; npc.ai[1] -= 1f; //dont progress ai RainTimer++; const int delay = 45; const int timeBeforeStreamsMove = 45; const int maxAttackTime = 480; int attackTimer = RainTimer - delay - timeBeforeStreamsMove; if (attackTimer < 0) { attackTimer = 0; } if (RainTimer == delay) { RainDirection = Math.Sign(Main.player[npc.target].Center.X - npc.Center.X); } if (RainTimer > delay && RainTimer < delay + maxAttackTime && RainTimer % 5 == 0) { const float maxWavy = 200; Vector2 focusPoint = new Vector2(npc.Center.X, Math.Min(npc.Center.Y, Main.player[npc.target].Center.Y)); focusPoint.X += maxWavy * RainDirection * (float)Math.Sin(Math.PI * 2f / maxAttackTime * attackTimer * 1.5f); focusPoint.Y -= 500; for (int i = -4; i <= 4; i++) { Vector2 spawnPos = focusPoint + Main.rand.NextVector2Circular(32, 32); spawnPos.X += 330 * i; if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), spawnPos, 8f * Vector2.UnitY, ProjectileID.QueenSlimeMinionBlueSpike, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer); } } } bool endAttack = RainTimer > delay + maxAttackTime + 90; if (npc.Distance(Main.player[npc.target].Center) > 1200) { endAttack = true; StompTimer = 0; StompCounter = -3; //enraged super stomps } if (!npc.HasValidTarget) { npc.TargetClosest(false); if (!npc.HasValidTarget) { endAttack = true; } } if (endAttack) { RainTimer = -1000; npc.netUpdate = true; NetSync(npc); if (StompTimer == 0) //transition directly to stompy if ready { npc.ai[0] = 4f; npc.ai[1] = 0f; } } } else { npc.ai[1] += 1; //proceed to next ais faster } } else if (npc.ai[0] == 4) //stompy { if (!Stompy(npc)) { return(false); } } else if (npc.ai[0] == 5) //when shooting { //be careful to stay above player if (npc.HasValidTarget && npc.Bottom.Y > Main.player[npc.target].Top.Y - 80 && npc.velocity.Y > -8f) { npc.velocity.Y -= 0.8f; } } } //FargoSoulsUtil.PrintAI(npc); EModeUtils.DropSummon(npc, "JellyCrystal", NPC.downedQueenSlime, ref DroppedSummon, Main.hardMode); return(true); }
public override bool PreAI(NPC npc) { EModeGlobalNPC.retiBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(true); } NPC spazmatism = FargoSoulsUtil.NPCExists(EModeGlobalNPC.spazBoss, NPCID.Spazmatism); if (FargoSoulsWorld.MasochistModeReal && spazmatism == null && npc.HasValidTarget && ++RespawnTimer > 600) { RespawnTimer = 0; if (Main.netMode != NetmodeID.MultiplayerClient) { int n = FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromThis(), npc.Center + new Vector2(Main.rand.NextFloat(-1000, 1000), Main.rand.NextFloat(-800, -600)), NPCID.Spazmatism, target: npc.target); if (n != Main.maxNPCs) { Main.npc[n].life = Main.npc[n].lifeMax / 4; if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, number: n); } string text = Language.GetTextValue($"Mods.{mod.Name}.Message.TwinsRevive"); FargoSoulsUtil.PrintText($"{Main.npc[n].FullName} {text}", new Color(175, 75, 255)); } } } if (!ForcedPhase2OnSpawn) //start phase 2 { ForcedPhase2OnSpawn = true; npc.ai[0] = 1f; npc.ai[1] = 0.0f; npc.ai[2] = 0.0f; npc.ai[3] = 0.0f; npc.netUpdate = true; } if (npc.life <= npc.lifeMax / 2 || npc.dontTakeDamage) { npc.dontTakeDamage = npc.life == 1 || !npc.HasValidTarget; if (npc.life != 1 && npc.HasValidTarget) { npc.dontTakeDamage = false; } //become vulnerable again when both twins at low life if (npc.dontTakeDamage && npc.HasValidTarget && (spazmatism == null || spazmatism.life == 1)) { npc.dontTakeDamage = false; } } if (Main.dayTime) { if (npc.velocity.Y > 0) { npc.velocity.Y = 0; } npc.velocity.Y -= 0.5f; npc.dontTakeDamage = true; if (spazmatism != null) { if (npc.timeLeft < 60) { npc.timeLeft = 60; } if (spazmatism.timeLeft < 60) { spazmatism.timeLeft = 60; } npc.TargetClosest(false); spazmatism.TargetClosest(false); if (npc.Distance(Main.player[npc.target].Center) > 2000 && spazmatism.Distance(Main.player[spazmatism.target].Center) > 2000) { if (Main.netMode != NetmodeID.MultiplayerClient) { npc.active = false; if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, npc.whoAmI); } spazmatism.active = false; if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, EModeGlobalNPC.spazBoss); } } } } return(true); } if (npc.ai[0] < 4f) //going to phase 3 { if (npc.life <= npc.lifeMax / 2) { //npc.ai[0] = 4f; npc.ai[0] = 604f; //initiate spin immediately npc.netUpdate = true; SoundEngine.PlaySound(SoundID.Roar, npc.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRingHollow>(), 0, 0f, Main.myPlayer, 11, npc.whoAmI); } } } else //in phase 3 { if (FargoSoulsWorld.MasochistModeReal && npc.life == 1 && --DarkStarTimer < 0) //when brought to 1hp, begin shooting dark stars { DarkStarTimer = 240; if (Main.netMode != NetmodeID.MultiplayerClient && npc.HasPlayerTarget) { Vector2 distance = Main.player[npc.target].Center - npc.Center; distance.Normalize(); distance *= 10f; for (int i = 0; i < 12; i++) { Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, distance.RotatedBy(2 * Math.PI / 12 * i), ModContent.ProjectileType <DarkStar>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 0.8f), 0f, Main.myPlayer); } } } //dust code if (Main.rand.Next(4) < 3) { int dust = Dust.NewDust(npc.position - new Vector2(2f, 2f), npc.width + 4, npc.height + 4, 90, npc.velocity.X * 0.4f, npc.velocity.Y * 0.4f, 100, default(Color), 3.5f); Main.dust[dust].noGravity = true; Main.dust[dust].velocity *= 1.8f; Main.dust[dust].velocity.Y -= 0.5f; if (Main.rand.NextBool(4)) { Main.dust[dust].noGravity = false; Main.dust[dust].scale *= 0.5f; } } if (npc.localAI[1] >= (npc.ai[1] == 0 ? 175 : 55)) //hijacking vanilla laser code { npc.localAI[1] = 0; Vector2 vel = npc.DirectionTo(Main.player[npc.target].Center); Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center + (npc.width - 24) * vel, vel, ModContent.ProjectileType <DarkStarTwins>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer, npc.target); } if (DeathrayState == 0 || DeathrayState == 3) //not doing deathray, grow arena { AuraRadiusCounter--; if (AuraRadiusCounter < 0) { AuraRadiusCounter = 0; } } else //doing deathray, shrink arena { AuraRadiusCounter++; if (AuraRadiusCounter > 180) { AuraRadiusCounter = 180; } } float auraDistance = 2000 - 1200 * AuraRadiusCounter / 180f; if (FargoSoulsWorld.MasochistModeReal) { auraDistance *= 0.75f; } if (auraDistance < 2000) { EModeGlobalNPC.Aura(npc, auraDistance, true, DustID.Torch, default, ModContent.BuffType <Oiled>(), BuffID.OnFire, BuffID.Burning);
public override bool PreAI(NPC npc) { EModeGlobalNPC.brainBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(base.PreAI(npc)); } if (!npc.HasValidTarget || npc.Distance(Main.player[npc.target].Center) > 3000) { npc.velocity.Y += 0.75f; if (npc.timeLeft > 120) { npc.timeLeft = 120; } } if (npc.alpha > 0 && (npc.ai[0] == 2 || npc.ai[0] == -3) && npc.HasValidTarget) //stay at a minimum distance { const float safeRange = 360; /*Vector2 stayAwayFromHere = Main.player[npc.target].Center + Main.player[npc.target].velocity * 30f; * if (npc.Distance(stayAwayFromHere) < safeRange) * npc.Center = stayAwayFromHere + npc.DirectionFrom(stayAwayFromHere) * safeRange;*/ Vector2 stayAwayFromHere = Main.player[npc.target].Center; if (npc.Distance(stayAwayFromHere) < safeRange) { npc.Center = stayAwayFromHere + npc.DirectionFrom(stayAwayFromHere) * safeRange; } } if (EnteredPhase2) { if (npc.buffType[0] != 0) //constant debuff cleanse { npc.buffImmune[npc.buffType[0]] = true; npc.DelBuff(0); } void TelegraphConfusion(Vector2 spawn) { Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, Vector2.Zero, ModContent.ProjectileType <GlowRingHollow>(), 0, 0f, Main.myPlayer, 8, 180); Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, Vector2.Zero, ModContent.ProjectileType <GlowRingHollow>(), 0, 0f, Main.myPlayer, 8, 200); Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, Vector2.Zero, ModContent.ProjectileType <GlowRingHollow>(), 0, 0f, Main.myPlayer, 8, 220); }; void LaserSpread(Vector2 spawn) { if (npc.HasValidTarget && Main.netMode != NetmodeID.MultiplayerClient) //laser spreads from each illusion { int max = FargoSoulsWorld.MasochistModeReal ? 7 : 3; int degree = FargoSoulsWorld.MasochistModeReal ? 2 : 3; int laserDamage = FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 4f / 3); Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, new Vector2(0, -4), ModContent.ProjectileType <BrainofConfusion>(), 0, 0, Main.myPlayer); for (int i = -max; i <= max; i++) { Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, 0.2f * Main.player[npc.target].DirectionFrom(spawn).RotatedBy(MathHelper.ToRadians(degree) * i), ModContent.ProjectileType <DestroyerLaser>(), laserDamage, 0f, Main.myPlayer); } } }; int confusionThreshold = FargoSoulsWorld.MasochistModeReal ? 240 : 300; if (--ConfusionTimer < 0) { ConfusionTimer = confusionThreshold; if (Main.player[npc.target].HasBuff(BuffID.Confused)) { SoundEngine.PlaySound(SoundID.ForceRoarPitched, npc.Center); TelegraphConfusion(npc.Center); IllusionTimer = 120 + 90; if (Main.netMode != NetmodeID.MultiplayerClient) { int type = ModContent.ProjectileType <BrainIllusionProj>(); //make illusions attack int alpha = (int)(255f * npc.life / npc.lifeMax); void SpawnClone(Vector2 center) { int n = NPC.NewNPC(npc.GetSource_FromAI(), (int)center.X, (int)center.Y, ModContent.NPCType <BrainIllusionAttack>(), npc.whoAmI, npc.whoAmI, alpha); if (n != Main.maxNPCs) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } foreach (Projectile p in Main.projectile.Where(p => p.active && p.type == type && p.ai[0] == npc.whoAmI && p.ai[1] == 0f)) { if (p.Distance(Main.player[npc.target].Center) < 1000) { //p.ai[1] = 1f; //p.netUpdate = true; SpawnClone(p.Center); } p.Kill(); } Vector2 offset = npc.Center - Main.player[npc.target].Center; Vector2 spawnPos = Main.player[npc.target].Center; SpawnClone(new Vector2(spawnPos.X + offset.X, spawnPos.Y + offset.Y)); SpawnClone(new Vector2(spawnPos.X + offset.X, spawnPos.Y - offset.Y)); SpawnClone(new Vector2(spawnPos.X - offset.X, spawnPos.Y + offset.Y)); SpawnClone(new Vector2(spawnPos.X - offset.X, spawnPos.Y - offset.Y)); } } else { SoundEngine.PlaySound(SoundID.Roar, npc.Center); Vector2 offset = npc.Center - Main.player[npc.target].Center; Vector2 spawnPos = Main.player[npc.target].Center; TelegraphConfusion(new Vector2(spawnPos.X + offset.X, spawnPos.Y + offset.Y)); TelegraphConfusion(new Vector2(spawnPos.X + offset.X, spawnPos.Y - offset.Y)); TelegraphConfusion(new Vector2(spawnPos.X - offset.X, spawnPos.Y + offset.Y)); TelegraphConfusion(new Vector2(spawnPos.X - offset.X, spawnPos.Y - offset.Y)); } npc.netUpdate = true; NetSync(npc); } else if (ConfusionTimer == confusionThreshold - 60) { //npc.netUpdate = true; //disabled because might be causing mp issues??? //NetSync(npc); if (!Main.player[npc.target].HasBuff(BuffID.Confused)) { Vector2 offset = npc.Center - Main.player[npc.target].Center; Vector2 spawnPos = Main.player[npc.target].Center; LaserSpread(new Vector2(spawnPos.X + offset.X, spawnPos.Y + offset.Y)); LaserSpread(new Vector2(spawnPos.X + offset.X, spawnPos.Y - offset.Y)); LaserSpread(new Vector2(spawnPos.X - offset.X, spawnPos.Y + offset.Y)); LaserSpread(new Vector2(spawnPos.X - offset.X, spawnPos.Y - offset.Y)); } if (npc.Distance(Main.LocalPlayer.Center) < 3000 && !Main.LocalPlayer.HasBuff(BuffID.Confused)) //inflict confusion { FargoSoulsUtil.AddDebuffFixedDuration(Main.LocalPlayer, BuffID.Confused, confusionThreshold + 5); } } if (--IllusionTimer < 0) //spawn illusions { IllusionTimer = Main.rand.Next(5, 11); if (npc.life > npc.lifeMax / 2) { IllusionTimer += 5; } if (npc.life < npc.lifeMax / 10) { IllusionTimer -= 2; } if (FargoSoulsWorld.MasochistModeReal) { IllusionTimer -= 2; } if (Main.netMode != NetmodeID.MultiplayerClient) { Vector2 spawn = Main.player[npc.target].Center + Main.rand.NextVector2CircularEdge(1200f, 1200f); Vector2 speed = Main.player[npc.target].Center + Main.player[npc.target].velocity * 45f + Main.rand.NextVector2Circular(-600f, 600f) - spawn; speed = Vector2.Normalize(speed) * Main.rand.NextFloat(12f, 48f); Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, speed, ModContent.ProjectileType <BrainIllusionProj>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 4f / 3), 0f, Main.myPlayer, npc.whoAmI); } } if (IllusionTimer > 60) { if (npc.ai[0] == -1f && npc.localAI[1] < 80) //force a tp { npc.localAI[1] = 80f; } if (npc.ai[0] == -3f && npc.ai[3] > 200) //stay invis { npc.dontTakeDamage = true; npc.ai[0] = -3f; npc.ai[3] = 255; npc.alpha = 255; return(false); } } } else if (!npc.dontTakeDamage) { EnteredPhase2 = true; if (Main.netMode != NetmodeID.MultiplayerClient) //spawn illusions { bool recolor = SoulConfig.Instance.BossRecolors && FargoSoulsWorld.EternityMode; int type = recolor ? ModContent.NPCType <BrainIllusion2>() : ModContent.NPCType <BrainIllusion>(); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, type, npc.whoAmI, npc.whoAmI, -1, 1); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, type, npc.whoAmI, npc.whoAmI, 1, -1); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, type, npc.whoAmI, npc.whoAmI, 1, 1); FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), npc.Center, ModContent.NPCType <BrainClone>(), npc.whoAmI); for (int i = 0; i < Main.maxProjectiles; i++) //clear old golden showers { if (Main.projectile[i].active && Main.projectile[i].type == ModContent.ProjectileType <GoldenShowerHoming>()) { Main.projectile[i].Kill(); } } } } EModeUtils.DropSummon(npc, "GoreySpine", NPC.downedBoss2, ref DroppedSummon); npc.defense = 0; npc.defDefense = 0; return(base.PreAI(npc)); }
public override bool PreAI(NPC npc) { bool result = base.PreAI(npc); EModeGlobalNPC.cultBoss = npc.whoAmI; if (FargoSoulsWorld.SwarmActive) { return(result); } if (npc.ai[3] == -1f) { //if (Fargowiltas.Instance.MasomodeEXLoaded && npc.ai[1] >= 120f && npc.ai[1] < 419f) //skip summoning ritual LMAO //{ // npc.ai[1] = 419f; // npc.netUpdate = true; //} if (npc.ai[0] == 5) { if (npc.ai[1] == 1f) { RitualRotation = Main.rand.Next(360); npc.netUpdate = true; NetSync(npc); } if (npc.ai[1] > 30f && npc.ai[1] < 330f) { RitualRotation += 2f - Math.Min(1f, 2f * npc.life / npc.lifeMax); //always at least 1, begins scaling below 50% life npc.Center = Main.player[npc.target].Center + 180f * Vector2.UnitX.RotatedBy(MathHelper.ToRadians(RitualRotation)); } /*if (npc.ai[1] > 275f && npc.ai[1] < 330f) //dust that reveals the real cultist at last second * { * float modifier = 0; * int repeats = (int)npc.ai[1] - 275; * for (int i = 0; i < repeats; i++) * modifier = MathHelper.Lerp(modifier, 1f, 0.08f); * float distance = npc.height * 2 * modifier; * float rotation = MathHelper.TwoPi * modifier; * for (int i = 0; i < 4; i++) * { * int d = Dust.NewDust(npc.Center + distance * Vector2.UnitX.RotatedBy(rotation + MathHelper.TwoPi / 4 * i), 0, 0, 88, newColor: Color.White); * Main.dust[d].noGravity = true; * Main.dust[d].velocity *= npc.ai[1] > 315 ? 18f : 0.5f; * Main.dust[d].scale = 0.5f + 2.5f * modifier; * } * }*/ } } else { //if (npc.ai[3] == 0) npc.damage = 0; //about to begin moving for ritual: 0 39 0 12 //begin transit for ritual: 1 34 0 12 //pause just before ritual: 0 0 0 13 //ritual: 5 0 0 -1 if (!EnteredPhase2 && npc.life < npc.lifeMax / 2) //p2 transition, force a ritual immediately { EnteredPhase2 = true; npc.ai[0] = 5; npc.ai[1] = 0; npc.ai[2] = 0; npc.ai[3] = -1; SoundEngine.PlaySound(SoundID.Roar, npc.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { npc.netUpdate = true; NetSync(npc); } } //necessary because calameme int damage = Math.Max(75, FargoSoulsUtil.ScaledProjectileDamage(npc.damage)); damage /= 4; switch ((int)npc.ai[0]) { case -1: if (npc.ai[1] == 419f) //always start fight with a ritual { npc.ai[0] = 0f; npc.ai[1] = 0f; npc.ai[3] = 11f; npc.netUpdate = true; } break; case 2: //ice mist, frost wave support if (EnteredPhase2) { if (npc.ai[1] < 60 && npc.ai[1] % 4 == 3) { int spacing = 14 - (int)(npc.ai[1] - 3) / 4; //start far and get closer for (int j = -1; j <= 1; j += 2) //from above and below { for (int i = -1; i <= 1; i += 2) //waves beside you { if (i == 0) { continue; } Vector2 spawnPos = Main.player[npc.target].Center; spawnPos.X += Math.Sign(i) * 150 * 2 + i * 120 * spacing; spawnPos.Y -= (700 + Math.Abs(i) * 50) * j; float speed = 8 + spacing * 0.8f; if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(npc.GetSource_FromThis(), spawnPos, Vector2.UnitY * speed * j, ProjectileID.FrostWave, damage / 3, 0f, Main.myPlayer); } } } } } else { if (npc.ai[1] == (FargoSoulsWorld.MasochistModeReal ? 5f : 60f) && Main.netMode != NetmodeID.MultiplayerClient) //single wave { for (int i = 0; i < Main.maxNPCs; i++) { if (Main.npc[i].active && Main.npc[i].type == NPCID.CultistBossClone) { Vector2 distance = Main.player[npc.target].Center - Main.npc[i].Center; distance.Normalize(); distance *= Main.rand.NextFloat(8f, 9f); distance = distance.RotatedByRandom(Math.PI / 24); Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[i].Center, distance, ProjectileID.FrostWave, damage / 3, 0f, Main.myPlayer); } } } } break; case 3: //fireballs if (Main.netMode != NetmodeID.MultiplayerClient) { if (EnteredPhase2) //fireball ring { if (npc.ai[1] == 3f) { int max = NPC.CountNPCS(NPCID.CultistBossClone) * 2 + 6; Vector2 baseOffset = npc.DirectionTo(Main.player[npc.target].Center); const float spawnOffset = 1200f; const float speed = 7f; const float ai0 = spawnOffset / speed; for (int i = 0; i < max; i++) { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.player[npc.target].Center + spawnOffset * baseOffset.RotatedBy(2 * Math.PI / max * i), -speed * baseOffset.RotatedBy(2 * Math.PI / max * i), ModContent.ProjectileType <CultistFireball>(), damage / 3, 0f, Main.myPlayer, ai0); } Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type); } } if (npc.ai[1] % 20 == 6) //homing flare support { for (int i = 0; i < Main.maxNPCs; i++) { if (Main.npc[i].active && Main.npc[i].type == NPCID.CultistBossClone) { FargoSoulsUtil.NewNPCEasy(npc.GetSource_FromAI(), Main.npc[i].Center, NPCID.SolarFlare, target: npc.target); } } } } break; case 4: //lightning if (npc.ai[1] == 19f && npc.HasPlayerTarget && Main.netMode != NetmodeID.MultiplayerClient) { int cultistCount = 1; for (int i = 0; i < Main.maxNPCs; i++) { if (Main.npc[i].active && Main.npc[i].type == NPCID.CultistBossClone) { if (EnteredPhase2) //vortex lightning { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[i].Center, Main.rand.NextVector2Square(-15, 15), ModContent.ProjectileType <CultistVortex>(), damage / 15 * 6, 0, Main.myPlayer, 0f, cultistCount); cultistCount++; } else //aimed lightning { if (FargoSoulsWorld.MasochistModeReal) { Vector2 dir = Main.player[npc.target].Center - Main.npc[i].Center; float ai1New = Main.rand.Next(100); Vector2 vel = Vector2.Normalize(dir.RotatedByRandom(Math.PI / 4)) * 24f; Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[i].Center, vel, ModContent.ProjectileType <HostileLightning>(), damage / 15 * 6, 0, Main.myPlayer, dir.ToRotation(), ai1New); } else { Vector2 vel = Main.npc[i].DirectionTo(Main.player[npc.target].Center).RotatedByRandom(MathHelper.ToRadians(5)); vel *= Main.rand.NextFloat(4f, 6f); Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[i].Center, vel, ModContent.ProjectileType <LightningVortexHostile>(), damage / 15 * 6, 0, Main.myPlayer); } } } } } break; case 7: if (npc.ai[1] == 3f && Main.netMode != NetmodeID.MultiplayerClient) //ancient light, jellyfish support { for (int i = 0; i < Main.maxProjectiles; i++) { if (Main.projectile[i].active && Main.projectile[i].type == ModContent.ProjectileType <CultistRitual>()) { Projectile.NewProjectile(npc.GetSource_FromThis(), new Vector2(Main.projectile[i].Center.X, Main.player[npc.target].Center.Y - 700), Vector2.Zero, ModContent.ProjectileType <StardustRain>(), damage / 3, 0f, Main.myPlayer); } } } break; case 8: if (npc.ai[1] == 3f) //ancient doom, nebula sphere support { int t = npc.HasPlayerTarget ? npc.target : npc.FindClosestPlayer(); if (t != -1 && Main.player[t].active) { for (int i = 0; i < Main.maxNPCs; i++) { if (Main.npc[i].active && Main.npc[i].type == NPCID.CultistBossClone) { Projectile.NewProjectile(npc.GetSource_FromThis(), Main.npc[i].Center, Vector2.Zero, ProjectileID.NebulaSphere, damage / 15 * 6, 0f, Main.myPlayer); } } } } break; default: break; } } npc.defense = npc.defDefense; //prevent vanilla p2 from lowering defense! Lighting.AddLight(npc.Center, 1f, 1f, 1f); EModeUtils.DropSummon(npc, "CultistSummon", NPC.downedAncientCultist, ref DroppedSummon, NPC.downedGolemBoss); return(result); }