public override bool?CanBeHitByProjectile(NPC npc, Projectile projectile) { if (npc.ai[3] == -1f && FargoSoulsUtil.IsSummonDamage(projectile, includeWhips: false)) { return(false); } return(base.CanBeHitByProjectile(npc, projectile)); }
public override void OnHitByProjectile(NPC npc, Projectile projectile, int damage, float knockback, bool crit) { base.OnHitByProjectile(npc, projectile, damage, knockback, crit); if (projectile.DamageType == DamageClass.Melee || projectile.DamageType == DamageClass.Throwing) { MeleeDamageCounter += damage; } if (projectile.DamageType == DamageClass.Ranged) { RangedDamageCounter += damage; } if (projectile.DamageType == DamageClass.Magic) { MagicDamageCounter += damage; } if (FargoSoulsUtil.IsSummonDamage(projectile)) { MinionDamageCounter += damage; } }
public override bool?CanBeHitByProjectile(NPC npc, Projectile projectile) { if (!Main.player[projectile.owner].buffImmune[ModContent.BuffType <NullificationCurse>()] && !FargoSoulsWorld.SwarmActive) { switch (GetVulnerabilityState(npc)) { case 0: if (projectile.DamageType != DamageClass.Melee) { return(false); } break; case 1: if (projectile.DamageType != DamageClass.Ranged) { return(false); } break; case 2: if (projectile.DamageType != DamageClass.Magic) { return(false); } break; case 3: if (!FargoSoulsUtil.IsSummonDamage(projectile)) { return(false); } break; default: break; } } return(base.CanBeHitByProjectile(npc, projectile)); }
public override void AI() { const int time = 1800; const int maxScale = 3; const float suckRange = 150; void Suck() { foreach (Projectile p in Main.projectile.Where(p => p.active && p.friendly && p.Distance(Projectile.Center) < suckRange && !FargoSoulsUtil.IsSummonDamage(p) && FargoSoulsUtil.CanDeleteProjectile(p) && p.type != ModContent.ProjectileType <Minions.LunarCultistLightningArc>())) { //suck in nearby friendly projs p.velocity = p.DirectionTo(Projectile.Center) * p.velocity.Length(); p.velocity *= 1.015f; //kill ones that actually fall in and retaliate if (Main.netMode != NetmodeID.MultiplayerClient && Projectile.Colliding(Projectile.Hitbox, p.Hitbox)) { Player player = Main.player[p.owner]; if (player.active && !player.dead && !player.ghost && suck <= 0) { suck = 6; Vector2 dir = Projectile.DirectionTo(player.Center).RotatedByRandom(MathHelper.ToRadians(10)); float ai1New = (Main.rand.NextBool()) ? 1 : -1; //randomize starting direction Vector2 vel = Vector2.Normalize(dir) * 6f; Projectile.NewProjectile(Terraria.Entity.InheritSource(Projectile), Projectile.Center, vel * 6, ModContent.ProjectileType <Champions.CosmosLightning>(), Projectile.damage, 0, Main.myPlayer, dir.ToRotation(), ai1New); } p.Kill(); } } }; if (suck > 0) { suck--; } NPC npc = FargoSoulsUtil.NPCExists(Projectile.ai[1], NPCID.MoonLordCore); if (npc != null) { Projectile.localAI[0]++; const int orbitTime = 180; Vector2 offset; offset.X = 300f * (float)Math.Sin(Math.PI * 2 / (orbitTime * 2) * Projectile.localAI[0]); offset.Y = 150f * (float)Math.Sin(Math.PI * 2 / orbitTime * Projectile.localAI[0]); Projectile.Center = npc.Center + offset; //if (Projectile.localAI[1] < 120) //{ // float num1 = 0.5f; // for (int i = 0; i < 5; ++i) // { // if (Main.rand.NextFloat() >= num1) // { // float f = Main.rand.NextFloat() * 6.283185f; // float num2 = Main.rand.NextFloat(); // Dust dust = Dust.NewDustPerfect(Projectile.Center + f.ToRotationVector2() * (110 + 600 * num2), 229, (f - 3.141593f).ToRotationVector2() * (14 + 8 * num2), 0, default, 1f); // dust.scale = 0.9f; // dust.fadeIn = 1.15f + num2 * 0.3f; // //dust.color = new Color(1f, 1f, 1f, num1) * (1f - num1); // dust.noGravity = true; // //dust.noLight = true; // } // } //} if (npc.GetEModeNPCMod <MoonLordCore>().VulnerabilityState != 1 && Projectile.timeLeft > 60) { Projectile.timeLeft = 60; } } else { Projectile.Kill(); return; } for (int i = 0; i < 10; i++) { Vector2 offset = new Vector2(); double angle = Main.rand.NextDouble() * 2d * Math.PI; offset.X += (float)(Math.Sin(angle) * suckRange); offset.Y += (float)(Math.Cos(angle) * suckRange); Dust dust = Main.dust[Dust.NewDust( Projectile.Center + offset - new Vector2(4, 4), 0, 0, 229, 0, 0, 100, Color.White, 1f )]; dust.velocity = npc.velocity / 3; if (Main.rand.NextBool(3)) { dust.velocity += Vector2.Normalize(offset); } dust.noGravity = true; } Projectile.localAI[1]++; if (Projectile.localAI[1] <= 50) { if (Main.rand.NextBool(4)) { Vector2 spinningpoint = Vector2.UnitY.RotatedByRandom(6.28318548202515); Dust dust = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint * 30f, 0, 0, 229, 0.0f, 0.0f, 0, new Color(), 1f)]; dust.noGravity = true; dust.position = Projectile.Center - spinningpoint * Main.rand.Next(10, 21); dust.velocity = spinningpoint.RotatedBy(1.57079637050629, new Vector2()) * 4f; dust.scale = 0.5f + Main.rand.NextFloat(); dust.fadeIn = 0.5f; } if (Main.rand.NextBool(4)) { Vector2 spinningpoint = Vector2.UnitY.RotatedByRandom(6.28318548202515); Dust dust = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint * 30f, 0, 0, 240, 0.0f, 0.0f, 0, new Color(), 1f)]; dust.noGravity = true; dust.position = Projectile.Center - spinningpoint * 30f; dust.velocity = spinningpoint.RotatedBy(-1.57079637050629, new Vector2()) * 2f; dust.scale = 0.5f + Main.rand.NextFloat(); dust.fadeIn = 0.5f; } } else if (Projectile.localAI[1] <= 90) { Projectile.scale = (Projectile.localAI[1] - 50) / 40 * maxScale; Projectile.alpha = 255 - (int)(255 * Projectile.scale / maxScale); Projectile.rotation = Projectile.rotation - 0.1570796f; if (Main.rand.NextBool()) { Vector2 spinningpoint = Vector2.UnitY.RotatedByRandom(6.28318548202515) * Projectile.scale; Dust dust = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint * 30f, 0, 0, 229, 0.0f, 0.0f, 0, new Color(), 1f)]; dust.noGravity = true; dust.position = Projectile.Center - spinningpoint * Main.rand.Next(10, 21); dust.velocity = spinningpoint.RotatedBy(1.57079637050629, new Vector2()) * 6f; dust.scale = 0.5f + Main.rand.NextFloat(); dust.fadeIn = 0.5f; dust.customData = Projectile.Center; } if (Main.rand.NextBool()) { Vector2 spinningpoint = Vector2.UnitY.RotatedByRandom(6.28318548202515) * Projectile.scale; Dust dust = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint * 30f, 0, 0, 240, 0.0f, 0.0f, 0, new Color(), 1f)]; dust.noGravity = true; dust.position = Projectile.Center - spinningpoint * 30f; dust.velocity = spinningpoint.RotatedBy(-1.57079637050629, new Vector2()) * 3f; dust.scale = 0.5f + Main.rand.NextFloat(); dust.fadeIn = 0.5f; dust.customData = Projectile.Center; } Suck(); } else if (Projectile.localAI[1] <= 90 + time) { Projectile.velocity *= 0.9f; Projectile.scale = maxScale; Projectile.alpha = 0; Projectile.rotation = Projectile.rotation - (float)Math.PI / 60f; if (Main.rand.NextBool()) { Vector2 spinningpoint = Vector2.UnitY.RotatedByRandom(6.28318548202515) * Projectile.scale; Dust dust = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint * 30f, 0, 0, 229, 0.0f, 0.0f, 0, new Color(), 1f)]; dust.noGravity = true; dust.position = Projectile.Center - spinningpoint * Main.rand.Next(10, 21); dust.velocity = spinningpoint.RotatedBy(1.57079637050629, new Vector2()) * 6f; dust.scale = 0.5f + Main.rand.NextFloat(); dust.fadeIn = 0.5f; dust.customData = Projectile.Center; } else { Vector2 spinningpoint = Vector2.UnitY.RotatedByRandom(6.28318548202515) * Projectile.scale; Dust dust = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint * 30f, 0, 0, 240, 0.0f, 0.0f, 0, new Color(), 1f)]; dust.noGravity = true; dust.position = Projectile.Center - spinningpoint * 30f; dust.velocity = spinningpoint.RotatedBy(-1.57079637050629, new Vector2()) * 3f; dust.scale = 0.5f + Main.rand.NextFloat(); dust.fadeIn = 0.5f; dust.customData = Projectile.Center; } Suck(); } else { Projectile.scale = (float)(1.0 - (Projectile.localAI[1] - time) / 60.0) * maxScale; Projectile.alpha = 255 - (int)(255 * Projectile.scale / maxScale); Projectile.rotation = Projectile.rotation - (float)Math.PI / 30f; if (Projectile.alpha >= 255) { Projectile.Kill(); } for (int index = 0; index < 2; ++index) { switch (Main.rand.Next(3)) { case 0: Vector2 spinningpoint1 = Vector2.UnitY.RotatedByRandom(6.28318548202515) * Projectile.scale; Dust dust1 = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint1 * 30f, 0, 0, 229, 0.0f, 0.0f, 0, new Color(), 1f)]; dust1.noGravity = true; dust1.position = Projectile.Center - spinningpoint1 * Main.rand.Next(10, 21); dust1.velocity = spinningpoint1.RotatedBy(1.57079637050629, new Vector2()) * 6f; dust1.scale = 0.5f + Main.rand.NextFloat(); dust1.fadeIn = 0.5f; dust1.customData = Projectile.Center; break; case 1: Vector2 spinningpoint2 = Vector2.UnitY.RotatedByRandom(6.28318548202515) * Projectile.scale; Dust dust2 = Main.dust[Dust.NewDust(Projectile.Center - spinningpoint2 * 30f, 0, 0, 240, 0.0f, 0.0f, 0, new Color(), 1f)]; dust2.noGravity = true; dust2.position = Projectile.Center - spinningpoint2 * 30f; dust2.velocity = spinningpoint2.RotatedBy(-1.57079637050629, new Vector2()) * 3f; dust2.scale = 0.5f + Main.rand.NextFloat(); dust2.fadeIn = 0.5f; dust2.customData = Projectile.Center; break; } } } Dust dust3 = Main.dust[Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, 229, 0f, 0f, 0, new Color(), 1f)]; dust3.velocity *= 5f; dust3.fadeIn = 1f; dust3.scale = 1f + Main.rand.NextFloat() + Main.rand.Next(4) * 0.3f; dust3.noGravity = true; }
public override void AI() { Player player = Main.player[Projectile.owner]; FargoSoulsPlayer modPlayer = player.GetModPlayer <FargoSoulsPlayer>(); Projectile.netUpdate = true; if (player.whoAmI == Main.myPlayer && (player.dead || !(modPlayer.ShadowEnchantActive || modPlayer.TerrariaSoul) || !player.GetToggleValue("Shadow"))) { modPlayer.ShadowEnchantActive = false; Projectile.Kill(); return; } // CD if (Projectile.ai[0] > 0) { Projectile.ai[0]--; //dusts indicate its back if (Projectile.ai[0] == 0) { const int num226 = 18; for (int num227 = 0; num227 < num226; num227++) { Vector2 vector6 = Vector2.UnitX.RotatedBy(Projectile.rotation) * 6f; vector6 = vector6.RotatedBy(((num227 - (num226 / 2 - 1)) * 6.28318548f / num226), default(Vector2)) + Projectile.Center; Vector2 vector7 = vector6 - Projectile.Center; int num228 = Dust.NewDust(vector6 + vector7, 0, 0, DustID.Shadowflame, 0f, 0f, 0, default(Color), 2f); Main.dust[num228].noGravity = true; Main.dust[num228].velocity = vector7; } } } float num395 = Main.mouseTextColor / 200f - 0.35f; num395 *= 0.2f; Projectile.scale = num395 + 0.95f; if (Projectile.owner == Main.myPlayer) { //rotation mumbo jumbo float distanceFromPlayer = 250; Lighting.AddLight(Projectile.Center, 0.1f, 0.4f, 0.2f); Projectile.position = player.Center + new Vector2(distanceFromPlayer, 0f).RotatedBy(Projectile.ai[1]); Projectile.position.X -= Projectile.width / 2; Projectile.position.Y -= Projectile.height / 2; float rotation = (float)Math.PI / 120; Projectile.ai[1] -= rotation; if (Projectile.ai[1] > (float)Math.PI) { Projectile.ai[1] -= 2f * (float)Math.PI; Projectile.netUpdate = true; } Projectile.rotation = Projectile.ai[1] + (float)Math.PI / 2f; //wait for CD if (Projectile.ai[0] != 0f) { return; } //detect being hit foreach (Projectile proj in Main.projectile.Where(proj => proj.active && proj.friendly && !proj.hostile && proj.owner == Projectile.owner && proj.damage > 0 && !FargoSoulsUtil.IsSummonDamage(proj, false) && proj.type != ModContent.ProjectileType <ShadowBall>() && proj.Colliding(proj.Hitbox, Projectile.Hitbox))) { int numBalls = 5; int dmg = 25; if (modPlayer.AncientShadowEnchantActive) { numBalls = 10; dmg = 50; } int damage = FargoSoulsUtil.HighestDamageTypeScaling(player, dmg); Projectile[] balls = FargoSoulsUtil.XWay(numBalls, Projectile.GetSource_FromThis(), Projectile.Center, ModContent.ProjectileType <ShadowBall>(), 6, damage, 0); foreach (Projectile ball in balls) { ball.originalDamage = damage; } if (FargoSoulsUtil.CanDeleteProjectile(proj)) { proj.Kill(); } Projectile.ai[0] = 300; break; } } }
public override void AI() { EModeGlobalNPC.championBoss = NPC.whoAmI; if (NPC.localAI[3] == 0) //spawn friends { NPC.TargetClosest(false); if (NPC.ai[2] == 1) { NPC.velocity = Vector2.Zero; NPC.noTileCollide = true; NPC.noGravity = true; NPC.alpha = 0; if (FargoSoulsWorld.downedBoss[(int)FargoSoulsWorld.Downed.SpiritChampion] && NPC.ai[1] < 120) { NPC.ai[1] = 120; } if (NPC.ai[1] == 180) { SoundEngine.PlaySound(SoundID.Roar, NPC.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { int n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, -1f, -1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, -1f, 1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, 1f, -1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, 1f, 1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } } } if (++NPC.ai[1] > 300) { NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.localAI[3] = 1; NPC.netUpdate = true; } return; } if (NPC.ai[3] == 0 && NPC.HasValidTarget) { NPC.ai[3] = 1; NPC.Center = Main.player[NPC.target].Center - Vector2.UnitY * 500; NPC.ai[2] = Main.player[NPC.target].Center.Y - NPC.height / 2; //fall this distance, accounting for my height NPC.netUpdate = true; } NPC.alpha -= 10; if (NPC.alpha < 0) { NPC.alpha = 0; NPC.noGravity = false; } if (NPC.Center.Y > NPC.ai[2]) { NPC.noTileCollide = false; } if (++NPC.ai[1] > 300 || (NPC.velocity.Y == 0 && NPC.ai[1] > 30)) { NPC.ai[1] = 0; NPC.ai[2] = 1; SoundEngine.PlaySound(SoundID.Item14, NPC.Center); for (int k = -2; k <= 2; k++) //explosions { Vector2 dustPos = NPC.Center; int width = NPC.width / 5; dustPos.X += width * k; dustPos.Y += NPC.height / 2; for (int i = 0; i < 20; i++) { int dust = Dust.NewDust(dustPos - new Vector2(16, 16), 32, 32, 31, 0f, 0f, 100, default(Color), 2f); //Main.dust[dust].velocity *= 1.4f; } /*for (int i = 0; i < 20; i++) * { * int dust = Dust.NewDust(dustPos - new Vector2(16, 16), 32, 32, 6, 0f, 0f, 100, default(Color), 3.5f); * Main.dust[dust].noGravity = true; * Main.dust[dust].velocity *= 7f; * dust = Dust.NewDust(dustPos - new Vector2(16, 16), 32, 32, 6, 0f, 0f, 100, default(Color), 1.5f); * Main.dust[dust].velocity *= 3f; * }*/ float scaleFactor9 = 0.5f; for (int j = 0; j < 4; j++) { int gore = Gore.NewGore(NPC.GetSource_FromThis(), dustPos, default(Vector2), Main.rand.Next(61, 64)); Main.gore[gore].velocity *= scaleFactor9; //Main.gore[gore].velocity.X += 1f; //Main.gore[gore].velocity.Y += 1f; } } } return; } Player player = Main.player[NPC.target]; Vector2 targetPos; if (NPC.HasValidTarget && NPC.Distance(player.Center) < 2500 && (Framing.GetTileSafely(player.Center).WallType != WallID.None || player.ZoneUndergroundDesert)) { NPC.timeLeft = 600; } NPC.dontTakeDamage = false; switch ((int)NPC.ai[0]) { case -4: //final float NPC.dontTakeDamage = true; goto case 0; case -3: //final you think you're safe NPC.dontTakeDamage = true; if (NPC.localAI[2] == 0) { NPC.localAI[2] = 1; } if (!player.active || player.dead || Vector2.Distance(NPC.Center, player.Center) > 2500f || (Framing.GetTileSafely(player.Center).WallType == WallID.None && !player.ZoneUndergroundDesert)) //despawn code { NPC.TargetClosest(false); if (NPC.timeLeft > 30) { NPC.timeLeft = 30; } NPC.noTileCollide = true; NPC.noGravity = true; NPC.velocity.Y += 1f; return; } targetPos = new Vector2(NPC.localAI[0], NPC.localAI[1]); if (NPC.Distance(targetPos) > 25) { Movement(targetPos, 0.8f, 24f); } if (NPC.ai[1] == 0) //respawn dead hands { bool[] foundHand = new bool[4]; for (int i = 0; i < Main.maxNPCs; i++) { if (Main.npc[i].active && Main.npc[i].type == ModContent.NPCType <SpiritChampionHand>() && Main.npc[i].ai[1] == NPC.whoAmI) { if (!foundHand[0]) { foundHand[0] = Main.npc[i].ai[2] == -1f && Main.npc[i].ai[3] == -1f; } if (!foundHand[1]) { foundHand[1] = Main.npc[i].ai[2] == -1f && Main.npc[i].ai[3] == 1f; } if (!foundHand[2]) { foundHand[2] = Main.npc[i].ai[2] == 1f && Main.npc[i].ai[3] == -1f; } if (!foundHand[3]) { foundHand[3] = Main.npc[i].ai[2] == 1f && Main.npc[i].ai[3] == 1f; } } } if (Main.netMode != NetmodeID.MultiplayerClient) //if hands somehow disappear { if (!foundHand[0]) { int n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, -1f, -1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } } if (!foundHand[1]) { int n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, -1f, 1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } } if (!foundHand[2]) { int n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, 1f, -1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } } if (!foundHand[3]) { int n = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 0f, NPC.whoAmI, 1f, 1f, NPC.target); if (n != Main.maxNPCs) { Main.npc[n].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n); } } } } } else if (NPC.ai[1] == 120) { SoundEngine.PlaySound(SoundID.Roar, NPC.Center); for (int i = 0; i < Main.maxNPCs; i++) //update ai { if (Main.npc[i].active && Main.npc[i].type == ModContent.NPCType <SpiritChampionHand>() && Main.npc[i].ai[1] == NPC.whoAmI) { Main.npc[i].ai[0] = 1f; Main.npc[i].netUpdate = true; } } if (Main.netMode != NetmodeID.MultiplayerClient) //spawn super hand { int n2 = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 3f, NPC.whoAmI, 1f, 1f, NPC.target); if (n2 != Main.maxNPCs) { Main.npc[n2].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n2].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n2); } } } } if (++NPC.ai[2] > 85) //bone spray { NPC.ai[2] = 0; if (Main.netMode != NetmodeID.MultiplayerClient) { SoundEngine.PlaySound(SoundID.Item2, NPC.Center); for (int i = 0; i < 12; i++) { Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.position.X + Main.rand.Next(NPC.width), NPC.position.Y + Main.rand.Next(NPC.height), Main.rand.NextFloat(-8f, 8f), Main.rand.NextFloat(-8f, 8f), ModContent.ProjectileType <SpiritCrossBone>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer); } } } if (++NPC.ai[3] > 110) { NPC.ai[3] = 0; if (Main.netMode != NetmodeID.MultiplayerClient) //sandnado { Vector2 target = player.Center; target.Y -= 100; Projectile.NewProjectile(NPC.GetSource_FromThis(), target, Vector2.Zero, ProjectileID.SandnadoHostileMark, 0, 0f, Main.myPlayer); int length = (int)NPC.Distance(target) / 10; Vector2 offset = NPC.DirectionTo(target) * 10f; for (int i = 0; i < length; i++) //dust warning line for sandnado { int d = Dust.NewDust(NPC.Center + offset * i, 0, 0, 269, 0f, 0f, 0, new Color()); Main.dust[d].noLight = true; Main.dust[d].scale = 1.25f; } } } if (++NPC.ai[1] > 600) { NPC.dontTakeDamage = false; NPC.netUpdate = true; NPC.ai[0] = 0; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.localAI[3] = 2; //can die now } break; case -1: targetPos = new Vector2(NPC.localAI[0], NPC.localAI[1]); if (NPC.Distance(targetPos) > 25) { Movement(targetPos, 0.8f, 24f); } if (++NPC.ai[1] > 360) { NPC.TargetClosest(); NPC.ai[0] = 4; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.netUpdate = true; if (NPC.Hitbox.Intersects(player.Hitbox)) { player.velocity.X = player.Center.X < NPC.Center.X ? -15f : 15f; player.velocity.Y = -10f; SoundEngine.PlaySound(SoundID.Roar, NPC.Center); } } break; case 0: //float to player if (!player.active || player.dead || Vector2.Distance(NPC.Center, player.Center) > 2500f || (Framing.GetTileSafely(player.Center).WallType == WallID.None && !player.ZoneUndergroundDesert)) //despawn code { NPC.TargetClosest(false); if (NPC.timeLeft > 30) { NPC.timeLeft = 30; } NPC.noTileCollide = true; NPC.noGravity = true; NPC.velocity.Y += 1f; return; } if (NPC.ai[1] == 0) { targetPos = player.Center; NPC.velocity = (targetPos - NPC.Center) / 75; NPC.localAI[0] = targetPos.X; NPC.localAI[1] = targetPos.Y; } if (++NPC.ai[1] > 75) { NPC.TargetClosest(); NPC.ai[0]++; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.netUpdate = true; } break; case 1: //cross bone/sandnado if (NPC.localAI[2] == 0) { NPC.localAI[2] = 1; } targetPos = new Vector2(NPC.localAI[0], NPC.localAI[1]); if (NPC.Distance(targetPos) > 25) { Movement(targetPos, 0.8f, 24f); } if (++NPC.ai[2] > 45) { NPC.ai[2] = 0; if (Main.netMode != NetmodeID.MultiplayerClient) { if (NPC.ai[1] < 180) //cross bones { SoundEngine.PlaySound(SoundID.Item2, NPC.Center); for (int i = 0; i < 12; i++) { Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.position.X + Main.rand.Next(NPC.width), NPC.position.Y + Main.rand.Next(NPC.height), Main.rand.NextFloat(-8f, 8f), Main.rand.NextFloat(-8f, 8f), ModContent.ProjectileType <SpiritCrossBone>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer); } } else //sandnado { doPredictiveSandnado = !doPredictiveSandnado; Vector2 target = player.Center; if (doPredictiveSandnado && NPC.life < NPC.lifeMax * 0.66) { target += player.velocity * 30f; //alternate between predictive and direct aim } target.Y -= 100; Projectile.NewProjectile(NPC.GetSource_FromThis(), target, Vector2.Zero, ProjectileID.SandnadoHostileMark, 0, 0f, Main.myPlayer); int length = (int)NPC.Distance(target) / 10; Vector2 offset = NPC.DirectionTo(target) * 10f; for (int i = 0; i < length; i++) //dust warning line for sandnado { int d = Dust.NewDust(NPC.Center + offset * i, 0, 0, 269, 0f, 0f, 0, new Color()); Main.dust[d].noLight = true; Main.dust[d].scale = 1.25f; } } } } if (++NPC.ai[1] > 400) { NPC.TargetClosest(); NPC.ai[0]++; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.netUpdate = true; } break; case 2: goto case 0; case 3: //grab targetPos = new Vector2(NPC.localAI[0], NPC.localAI[1]); if (NPC.Distance(targetPos) > 25) { Movement(targetPos, 0.8f, 24f); } if (++NPC.ai[2] == 30) { for (int i = 0; i < Main.maxNPCs; i++) { if (Main.npc[i].active && Main.npc[i].type == ModContent.NPCType <SpiritChampionHand>() && Main.npc[i].ai[1] == NPC.whoAmI) { Main.npc[i].ai[0] = 1f; Main.npc[i].netUpdate = true; } } } if (NPC.life < NPC.lifeMax * 0.66) { if (++NPC.ai[3] > 55) //homing spectre bolts { NPC.ai[3] = 0; if (Main.netMode != NetmodeID.MultiplayerClient) { const int max = 5; for (int i = 0; i < max; i++) { Vector2 speed = Main.rand.NextFloat(1, 2) * Vector2.UnitX.RotatedByRandom(Math.PI * 2); float ai1 = 60 + Main.rand.Next(30); Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Center, speed, ModContent.ProjectileType <SpiritSpirit>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer, NPC.whoAmI, ai1); } } } } if (++NPC.ai[1] > 360) { NPC.TargetClosest(); NPC.ai[0]++; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.netUpdate = true; } break; case 4: goto case 0; case 5: //swords targetPos = new Vector2(NPC.localAI[0], NPC.localAI[1]); if (NPC.Distance(targetPos) > 25) { Movement(targetPos, 0.8f, 24f); } if (++NPC.ai[2] > 80) { NPC.ai[2] = 0; SoundEngine.PlaySound(SoundID.Item92, NPC.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < 15; i++) //sword burst { float speed = Main.rand.NextFloat(4f, 8f); Vector2 velocity = speed * Vector2.UnitX.RotatedBy(Main.rand.NextDouble() * 2 * Math.PI); float ai1 = speed / Main.rand.NextFloat(60f, 120f); Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Center, velocity, ModContent.ProjectileType <SpiritSword>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer, 0f, ai1); } if (NPC.life < NPC.lifeMax * 0.66) { const int max = 12; //hand ring for (int i = 0; i < max; i++) { Vector2 vel = NPC.DirectionTo(player.Center).RotatedBy(Math.PI * 2 / max * i); float ai0 = 1.04f; Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Center, vel, ModContent.ProjectileType <SpiritHand>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer, ai0); } } } } if (++NPC.ai[1] > 300) { NPC.TargetClosest(); NPC.ai[0]++; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.netUpdate = true; } break; case 6: goto case 0; case 7: //skip this number, staying on even number allows hands to remain drawn close NPC.ai[0]++; break; case 8: //shadow hands, reflect, mummy spirits { targetPos = new Vector2(NPC.localAI[0], NPC.localAI[1]); if (NPC.Distance(targetPos) > 25) { Movement(targetPos, 0.8f, 24f); } const float distance = 150; for (int i = 0; i < 20; i++) { Vector2 offset = new Vector2(); double angle = Main.rand.NextDouble() * 2d * Math.PI; offset.X += (float)(Math.Sin(angle) * distance); offset.Y += (float)(Math.Cos(angle) * distance); Dust dust = Main.dust[Dust.NewDust( NPC.Center + offset - new Vector2(4, 4), 0, 0, 87, 0, 0, 100, Color.White, 1f )]; dust.velocity = NPC.velocity; //if (Main.rand.NextBool(3)) dust.velocity += Vector2.Normalize(offset) * -5f; dust.noGravity = true; } if (NPC.ai[1] > 60) { Main.projectile.Where(x => x.active && x.friendly && !FargoSoulsUtil.IsSummonDamage(x, false)).ToList().ForEach(x => //reflect projectiles { if (Vector2.Distance(x.Center, NPC.Center) <= distance) { for (int i = 0; i < 5; i++) { int dustId = Dust.NewDust(x.position, x.width, x.height, 87, x.velocity.X * 0.2f, x.velocity.Y * 0.2f, 100, default(Color), 1.5f); Main.dust[dustId].noGravity = true; } // Set ownership x.hostile = true; x.friendly = false; x.owner = Main.myPlayer; x.damage /= 4; // Turn around x.velocity *= -1f; // Flip sprite if (x.Center.X > NPC.Center.X * 0.5f) { x.direction = 1; x.spriteDirection = 1; } else { x.direction = -1; x.spriteDirection = -1; } //x.netUpdate = true; if (x.owner == Main.myPlayer) { Projectile.NewProjectile(NPC.GetSource_FromThis(), x.Center, Vector2.Zero, ModContent.ProjectileType <Projectiles.Souls.IronParry>(), 0, 0f, Main.myPlayer); } } }); } if (NPC.ai[1] == 0) { SoundEngine.PlaySound(SoundID.Roar, NPC.Center); if (Main.netMode != NetmodeID.MultiplayerClient) { Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Center, Vector2.Zero, ModContent.ProjectileType <Projectiles.GlowRing>(), 0, 0f, Main.myPlayer, NPC.whoAmI, -6); } } if (++NPC.ai[3] > 10) //spirits { NPC.ai[3] = 0; SoundEngine.PlaySound(SoundID.Item8, NPC.Center); if (Main.netMode != NetmodeID.MultiplayerClient) //vanilla code from desert spirits idfk { Point tileCoordinates1 = NPC.Center.ToTileCoordinates(); Point tileCoordinates2 = Main.player[NPC.target].Center.ToTileCoordinates(); Vector2 vector2 = Main.player[NPC.target].Center - NPC.Center; int num1 = 6; int num2 = 6; int num3 = 0; int num4 = 2; int num5 = 0; bool flag1 = false; if (vector2.Length() > 2000) { flag1 = true; } while (!flag1 && num5 < 50) { ++num5; int index1 = Main.rand.Next(tileCoordinates2.X - num1, tileCoordinates2.X + num1 + 1); int index2 = Main.rand.Next(tileCoordinates2.Y - num1, tileCoordinates2.Y + num1 + 1); if ((index2 < tileCoordinates2.Y - num3 || index2 > tileCoordinates2.Y + num3 || (index1 < tileCoordinates2.X - num3 || index1 > tileCoordinates2.X + num3)) && (index2 < tileCoordinates1.Y - num2 || index2 > tileCoordinates1.Y + num2 || (index1 < tileCoordinates1.X - num2 || index1 > tileCoordinates1.X + num2)) && !Main.tile[index1, index2].HasUnactuatedTile) { bool flag2 = true; if (flag2 && Main.tile[index1, index2].LiquidType == LiquidID.Lava && Main.tile[index1, index2].LiquidAmount > 0) { flag2 = false; } if (flag2 && Collision.SolidTiles(index1 - num4, index1 + num4, index2 - num4, index2 + num4)) { flag2 = false; } if (flag2) { Projectile.NewProjectile(NPC.GetSource_FromThis(), index1 * 16 + 8, index2 * 16 + 8, 0, 0f, ProjectileID.DesertDjinnCurse, 0, 1f, Main.myPlayer, NPC.target, 0); break; } } } } } if (++NPC.ai[2] > 70) //hands { NPC.ai[2] = 0; if (Main.netMode != NetmodeID.MultiplayerClient) { for (int i = 0; i < 4; i++) { Vector2 vel = NPC.DirectionTo(player.Center).RotatedBy(Math.PI / 6 * (Main.rand.NextDouble() - 0.5)); float ai0 = Main.rand.NextFloat(1.04f, 1.06f); float ai1 = Main.rand.NextFloat(0.025f); Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Center, vel, ModContent.ProjectileType <SpiritHand>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer, ai0, ai1); } } } if (NPC.ai[1] % 30 == 0 && Main.netMode != NetmodeID.MultiplayerClient && NPC.life < NPC.lifeMax * 0.66) { SoundEngine.PlaySound(SoundID.Item2, NPC.Center); for (int i = 0; i < 3; i++) { Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.position.X + Main.rand.Next(NPC.width), NPC.position.Y + Main.rand.Next(NPC.height), Main.rand.NextFloat(-1f, 1f), Main.rand.NextFloat(-8f, 0f), ModContent.ProjectileType <SpiritCrossBone>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer); Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.position.X + Main.rand.Next(NPC.width), NPC.position.Y + Main.rand.Next(NPC.height), Main.rand.NextFloat(-1f, 1f), Main.rand.NextFloat(8f, 0f), ModContent.ProjectileType <SpiritCrossBoneReverse>(), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer); } } if (++NPC.ai[1] > 360) { NPC.TargetClosest(); NPC.ai[0]++; NPC.ai[1] = 0; NPC.ai[2] = 0; NPC.ai[3] = 0; NPC.netUpdate = true; } } break; case 9: //skip this number, get back to usual behaviour NPC.ai[0]++; break; /*case 10: * goto case 0;*/ default: NPC.ai[0] = 0; goto case 0; } if (NPC.localAI[2] != 0 && FargoSoulsWorld.EternityMode) //aura { const float auraDistance = 1200; float range = NPC.Distance(player.Center); if (range > auraDistance && range < 3000) { if (++NPC.localAI[2] > 60) { NPC.localAI[2] = 1; NPC.netUpdate = true; SoundEngine.PlaySound(SoundID.Roar, NPC.Center); if (Main.netMode != NetmodeID.MultiplayerClient) //spawn super hand { int n2 = NPC.NewNPC(NPC.GetSource_FromAI(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType <SpiritChampionHand>(), NPC.whoAmI, 4f, NPC.whoAmI, 1f, 1f, NPC.target); if (n2 != Main.maxNPCs) { Main.npc[n2].velocity.X = Main.rand.NextFloat(-24f, 24f); Main.npc[n2].velocity.Y = Main.rand.NextFloat(-24f, 24f); if (Main.netMode == NetmodeID.Server) { NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n2); } } } } } for (int i = 0; i < 20; i++) //dust { int d = Dust.NewDust(NPC.Center + auraDistance * Vector2.UnitX.RotatedBy(Math.PI * 2 * Main.rand.NextDouble()), 0, 0, 87); Main.dust[d].velocity = NPC.velocity; Main.dust[d].noGravity = true; Main.dust[d].scale++; } } }
public override void AI() { Player player = Main.player[Projectile.owner]; FargoSoulsPlayer modPlayer = player.GetModPlayer <FargoSoulsPlayer>(); //destroy duplicates if they somehow spawn if (player.ownedProjectileCounts[Projectile.type] > 1 || (Projectile.owner == Main.myPlayer && (!player.GetToggleValue("Rain") || !modPlayer.RainEnchantActive))) { Projectile.Kill(); } else { Projectile.timeLeft = 2; } //follow player float dist = Vector2.Distance(Projectile.Center, player.Center); if (dist > 200) { Vector2 velocity = Vector2.Normalize(player.Center - Projectile.Center) * player.velocity.Length(); Projectile.position += velocity; } else { Projectile.velocity.Y = 0; } //always max size if (modPlayer.NatureForce) { Projectile.scale = 3f; shrinkTimer = 1; } //absorb Projectiles if (Projectile.owner == Main.myPlayer) { for (int i = 0; i < Main.maxProjectiles; i++) { Projectile proj = Main.projectile[i]; if (proj.active && proj.friendly && !proj.hostile && proj.owner == player.whoAmI && proj.damage > 0 && FargoSoulsUtil.CanDeleteProjectile(proj) && !FargoSoulsUtil.IsSummonDamage(proj, false) && proj.Hitbox.Intersects(Projectile.Hitbox) && proj.type != Projectile.type && proj.type != ProjectileID.RainFriendly && proj.type != ModContent.ProjectileType <LightningArc>() && proj.whoAmI != Main.player[proj.owner].heldProj && Array.IndexOf(FargoSoulsGlobalProjectile.noSplit, Projectile.type) <= -1 && proj.type != ModContent.ProjectileType <Chlorofuck>()) { if (Projectile.scale < 3f) { Projectile.scale *= 1.1f; } else { Vector2 rotationVector2 = (proj.Center + proj.velocity * 25) - Projectile.Center; rotationVector2.Normalize(); Vector2 vector2_3 = rotationVector2 * 10f; float ai_1 = Main.rand.Next(80); int p = Projectile.NewProjectile(Projectile.GetSource_FromThis(), Projectile.position.X + Main.rand.NextFloat(Projectile.width), Projectile.position.Y + Main.rand.NextFloat(Projectile.height), vector2_3.X, vector2_3.Y, ModContent.ProjectileType <LightningArc>(), proj.maxPenetrate == 1 ? proj.damage * 2 : (int)(proj.damage * 1.2), Projectile.knockBack, Projectile.owner, rotationVector2.ToRotation(), ai_1); if (p != Main.maxProjectiles) { Main.projectile[p].DamageType = DamageClass.Magic; Main.projectile[p].usesIDStaticNPCImmunity = false; Main.projectile[p].idStaticNPCHitCooldown = 0; Main.projectile[p].GetGlobalProjectile <FargoSoulsGlobalProjectile>().noInteractionWithNPCImmunityFrames = false; if (proj.maxPenetrate == 1) { Main.projectile[p].penetrate = Main.projectile[p].maxPenetrate = 3; } } } proj.active = false; shrinkTimer = 120; break; } } } //shrink over time if no Projectiles absorbed if (shrinkTimer > 0 && Projectile.scale > 1f) { shrinkTimer--; if (shrinkTimer == 0) { Projectile.scale *= 0.9f; shrinkTimer = 10; } } //cancel normal rain Projectile.ai[0] = 0; Projectile.localAI[1]++; //bigger = more rain if (Projectile.scale > 3f) { Projectile.localAI[1] += 4; } else if (Projectile.scale > 2f) { Projectile.localAI[1] += 3; } else if (Projectile.scale > 1.5f) { Projectile.localAI[1] += 2; } else { Projectile.localAI[1]++; } //do the rain if (Projectile.localAI[1] >= 8) { Projectile.localAI[1] = 0; if (Projectile.owner == Main.myPlayer) { int num414 = (int)(Projectile.Center.X + (float)Main.rand.Next((int)(-20 * Projectile.scale), (int)(20 * Projectile.scale))); int num415 = (int)(Projectile.position.Y + (float)Projectile.height + 4f); int p = Projectile.NewProjectile(Projectile.GetSource_FromThis(), (float)num414, (float)num415, 0f, 5f, ProjectileID.RainFriendly, Projectile.damage / 4, 0f, Projectile.owner, 0f, 0); if (p != Main.maxProjectiles) { Main.projectile[p].penetrate = 1; Main.projectile[p].timeLeft = 45 * Main.projectile[p].MaxUpdates; } } } }