Exemplo n.º 1
0
        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)
        {
            EModeGlobalNPC.empressBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return(base.PreAI(npc));
            }

            if (Main.LocalPlayer.active && !Main.LocalPlayer.dead && !Main.LocalPlayer.ghost)
            {
                Main.LocalPlayer.AddBuff(ModContent.BuffType <Purged>(), 2);
            }

            bool useP2Attacks = npc.ai[3] != 0 || FargoSoulsWorld.MasochistModeReal;

            switch ((int)npc.ai[0])
            {
            //0 spawn

            case 1:     //move over player
                if (npc.ai[1] == 0)
                {
                    AttackTimer = 0;
                    AttackCounter++;
                    NetSync(npc);
                }
                break;

            case 2:     //homing bolts, ends at ai1=130
                if (useP2Attacks && npc.ai[1] > 80 && !FargoSoulsWorld.MasochistModeReal)
                {
                    npc.ai[1] -= 0.5f;     //p2, more delay before next attack
                }
                break;

            case 4:     //pseudorandom swords following you, ends at ai1=100
            {
                if (npc.ai[1] == 0)
                {
                    AttackTimer = 0;
                    NetSync(npc);

                    TryRandom(npc);
                }

                const int specialAttackThreshold = 97;
                if (npc.ai[1] > specialAttackThreshold && useP2Attacks)         //p2 only sword circle
                {
                    SwordCircle(npc, specialAttackThreshold);
                }
            }
            break;

            case 5:     //stupid long trail circle ring
                if (AttackTimer < 2)
                {
                    if (npc.ai[1] > 1f)
                    {
                        npc.ai[1] -= 0.5f;   //progress slower
                    }
                    if (npc.ai[1] == 30)     //repeat attack
                    {
                        npc.ai[1] = 0f;
                        AttackTimer++;
                    }
                }

                //p2, do sword rings
                if (useP2Attacks && AttackTimer >= 2)
                {
                    if (npc.ai[1] == 20)
                    {
                        startRotation = Main.rand.NextFloat(MathHelper.TwoPi);
                    }

                    if (npc.ai[1] >= (FargoSoulsWorld.MasochistModeReal ? 20 : 35) && npc.ai[1] <= 60)
                    {
                        npc.position -= npc.velocity;
                        npc.velocity  = Vector2.Zero;

                        if (npc.ai[1] % 5 == 0)
                        {
                            for (float i = 0; i < 1; i += 1f / 24f)
                            {
                                Vector2 spinningpoint = Vector2.UnitY.RotatedBy(MathHelper.PiOver2 + MathHelper.TwoPi * i + startRotation);
                                if (Main.netMode != NetmodeID.MultiplayerClient)
                                {
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center + spinningpoint.RotatedBy(-MathHelper.PiOver2) * 30f, Vector2.Zero, ProjectileID.FairyQueenLance, FargoSoulsUtil.ScaledProjectileDamage(BaseProjDmg(npc), 1.3f), 0f, Main.myPlayer, spinningpoint.ToRotation(), i);
                                }
                            }
                        }
                    }
                }
                break;

            case 6:     //sun rays
                if (!FargoSoulsWorld.MasochistModeReal)
                {
                    if (npc.ai[1] == 0 && AttackTimer == 0 && Main.projectile.Count(p => p.active && p.type == ProjectileID.HallowBossRainbowStreak) > 20)
                    {
                        npc.ai[1]    -= 30;
                        npc.netUpdate = true;
                    }

                    if (npc.ai[1] == 1)
                    {
                        NetSync(npc);
                    }

                    npc.position -= npc.velocity / (npc.ai[3] == 0 ? 2 : 4);     //move slower
                }
                break;

            case 7:     //sword walls, ends at ai1=260
            {
                int start = FargoSoulsWorld.MasochistModeReal ? -15 : -45;

                if (npc.ai[1] == 0)
                {
                    TryRandom(npc);

                    npc.netUpdate = true;
                    NetSync(npc);         //sync it in advance to prepare for actual attacks
                }

                const int specialAttackThreshold = 255;
                if (npc.ai[1] == specialAttackThreshold)
                {
                    AttackTimer = start;
                    P2SwordsAttackCounter++;
                    startRotation = Main.rand.NextFloat(MathHelper.TwoPi);
                }

                if (npc.ai[1] > specialAttackThreshold)
                {
                    if (DoParallelSwordWalls)
                    {
                        ParallelSwordWalls(npc, specialAttackThreshold);
                    }
                    else         //excel spreadsheet
                    {
                        ExcelSpreadsheet(npc, specialAttackThreshold);
                    }
                }
            }
            break;

            case 8:     //dash from right to left
            case 9:     //dash from left to right
                Dash(npc, useP2Attacks);
                break;

            case 10:     //p2 transition
                if (npc.dontTakeDamage && npc.ai[1] > 120)
                {
                    Vector2 target = Main.player[npc.target].Center - 160f * Vector2.UnitY;
                    npc.Center = Vector2.Lerp(npc.Center, target, 0.1f);

                    if (npc.life < npc.lifeMax / 2)
                    {
                        npc.HealEffect(npc.lifeMax / 2 - npc.life);
                        npc.life = npc.lifeMax / 2;
                    }
                }
                break;

            case 11:                                                                                                   //p2 direct sword trail
                if ((FargoSoulsWorld.MasochistModeReal || npc.ai[1] > 40) && npc.ai[1] % 3 == 0 && npc.HasValidTarget) //add perpendicular swords
                {
                    Vector2 offset = Main.player[npc.target].velocity;
                    if (offset == Vector2.Zero || offset.Length() < 1)
                    {
                        offset = offset.SafeNormalize(-Vector2.UnitY);
                    }
                    offset = 90f * offset.RotatedBy(MathHelper.PiOver2);

                    Vector2 spawnPos = Main.player[npc.target].Center + offset;
                    Vector2 vel      = Main.player[npc.target].DirectionFrom(spawnPos);

                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(npc.GetSource_FromThis(), spawnPos, Vector2.Zero, ProjectileID.FairyQueenLance, FargoSoulsUtil.ScaledProjectileDamage(BaseProjDmg(npc), 1.3f), 0f, Main.myPlayer, vel.ToRotation(), npc.ai[1] / 100f);
                    }
                }
                break;

            case 12:     //8-way homing bolts
            {
                const int max   = 24;
                const int delay = 75;

                if (npc.ai[1] < 4)
                {
                    Vector2 target = Main.player[npc.target].Center - 160f * Vector2.UnitY;
                    npc.Center = Vector2.Lerp(npc.Center, target, 0.1f);
                    if (npc.Distance(target) > 160)
                    {
                        npc.ai[1] -= 1f;
                    }
                }

                if (npc.ai[1] == delay)
                {
                    startRotation = npc.HasValidTarget ? npc.DirectionTo(Main.player[npc.target].Center).ToRotation() : MathHelper.PiOver2;
                }

                if (npc.ai[1] >= delay && npc.ai[1] < delay + max)
                {
                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        float ai1 = (npc.ai[1] - delay) / max;

                        if (FargoSoulsWorld.MasochistModeReal)
                        {
                            float   math    = MathHelper.TwoPi / max * (npc.ai[1] - delay);
                            Vector2 boltVel = -Vector2.UnitY.RotatedBy(-math);
                            Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, 20f * boltVel, ProjectileID.HallowBossRainbowStreak, FargoSoulsUtil.ScaledProjectileDamage(BaseProjDmg(npc), 1.3f), 0f, Main.myPlayer, npc.target, ai1);
                        }

                        float   spread        = MathHelper.ToRadians(24);
                        float   swordRotation = startRotation + MathHelper.Lerp(-spread, spread, ai1);
                        Vector2 appearVel     = swordRotation.ToRotationVector2();
                        Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center + appearVel * 160f + appearVel * 10f * 60f, -appearVel * 10f, ProjectileID.FairyQueenLance, FargoSoulsUtil.ScaledProjectileDamage(BaseProjDmg(npc), 1.3f), 0f, Main.myPlayer, swordRotation, ai1);
                    }
                }

                if (npc.ai[1] > delay + max && !FargoSoulsWorld.MasochistModeReal)
                {
                    npc.ai[1] -= 0.65f;         //more delay before next attack
                }
            }
            break;

            default:
                break;
            }

            EModeUtils.DropSummon(npc, "PrismaticPrimrose", NPC.downedEmpressOfLight, ref DroppedSummon, Main.hardMode);

            return(true);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        public override bool PreAI(NPC npc)
        {
            EModeGlobalNPC.slimeBoss = npc.whoAmI;
            npc.color = Main.DiscoColor * 0.3f; // Rainbow colour

            if (FargoSoulsWorld.SwarmActive)
            {
                return(true);
            }

            if (FargoSoulsWorld.MasochistModeReal)
            {
                npc.position.X += npc.velocity.X * 0.2f;
            }

            // Attack that happens when landing
            if (LandingAttackReady)
            {
                if (npc.velocity.Y == 0f)
                {
                    LandingAttackReady = false;
                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        if (FargoSoulsWorld.MasochistModeReal)
                        {
                            for (int i = 0; i < 30; i++) //spike spray
                            {
                                Projectile.NewProjectile(new Vector2(npc.Center.X + Main.rand.Next(-5, 5), npc.Center.Y - 15),
                                                         new Vector2(Main.rand.NextFloat(-6, 6), Main.rand.NextFloat(-8, -5)),
                                                         ProjectileID.SpikedSlimeSpike, npc.damage / 4, 0f, Main.myPlayer);
                            }
                        }

                        if (npc.HasValidTarget)
                        {
                            Main.PlaySound(SoundID.Item21, Main.player[npc.target].Center);
                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                for (int i = 0; i < 6; i++)
                                {
                                    Vector2 spawn = Main.player[npc.target].Center;
                                    spawn.X += Main.rand.Next(-150, 151);
                                    spawn.Y -= Main.rand.Next(600, 901);
                                    Vector2 speed = Main.player[npc.target].Center - spawn;
                                    speed.Normalize();
                                    speed *= IsBerserk ? 10f : 5f;
                                    speed  = speed.RotatedByRandom(MathHelper.ToRadians(4));
                                    Projectile.NewProjectile(spawn, speed, ModContent.ProjectileType <SlimeBallHostile>(), npc.damage / 6, 0f, Main.myPlayer);
                                }
                            }
                        }
                    }
                }
            }
            else if (npc.velocity.Y > 0)
            {
                // If they're in the air, flag that the landing attack should be used next time they land
                LandingAttackReady = true;
            }

            if (npc.velocity.Y < 0)    // Jumping up
            {
                if (!CurrentlyJumping) // Once per jump...
                {
                    CurrentlyJumping = true;

                    bool shootSpikes = false;

                    if (FargoSoulsWorld.MasochistModeReal)
                    {
                        shootSpikes = true;
                    }

                    // If player is well above me, jump higher and spray spikes
                    if (npc.HasValidTarget && Main.player[npc.target].Center.Y < npc.position.Y + npc.height - 240)
                    {
                        npc.velocity.Y *= 2f;
                        shootSpikes     = true;
                    }

                    if (shootSpikes && Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        const float gravity  = 0.15f;
                        float       time     = 90f;
                        Vector2     distance = Main.player[npc.target].Center - npc.Center + Main.player[npc.target].velocity * 30f;
                        distance.X = distance.X / time;
                        distance.Y = distance.Y / time - 0.5f * gravity * time;
                        for (int i = 0; i < 15; i++)
                        {
                            Projectile.NewProjectile(npc.Center, distance + Main.rand.NextVector2Square(-1f, 1f),
                                                     ModContent.ProjectileType <SlimeSpike>(), npc.damage / 4, 0f, Main.myPlayer);
                        }
                    }
                }
            }
            else
            {
                CurrentlyJumping = false;
            }

            if ((IsBerserk || npc.life < npc.lifeMax * .5f) && npc.HasValidTarget)
            {
                if (--SpikeRainCounter < 0) // Spike rain
                {
                    SpikeRainCounter = 240;

                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        for (int i = -12; i <= 12; i++)
                        {
                            Vector2 spawnPos = Main.player[npc.target].Center;
                            spawnPos.X += 110 * i;
                            spawnPos.Y -= 500;
                            Projectile.NewProjectile(spawnPos, (IsBerserk ? 6f : 0f) * Vector2.UnitY,
                                                     ModContent.ProjectileType <SlimeSpike2>(), npc.damage / 6, 0f, Main.myPlayer);
                        }
                    }
                }
            }

            /*if (!masoBool[0]) //is not berserk
             * {
             *  SharkCount = 0;
             *
             *  if (npc.HasPlayerTarget)
             *  {
             *      Player player = Main.player[npc.target];
             *      if (player.active && !player.dead && player.Center.Y < npc.position.Y && npc.Distance(player.Center) < 1000f)
             *      {
             *          Counter[1]++; //timer runs if player is above me and nearby
             *          if (Counter[1] >= 600 && Main.netMode != NetmodeID.MultiplayerClient) //go berserk
             *          {
             *              masoBool[0] = true;
             *              npc.netUpdate = true;
             *              NetUpdateMaso(npc.whoAmI);
             *              if (Main.netMode == NetmodeID.Server)
             *                  NetMessage.BroadcastChatMessage(NetworkText.FromLiteral("King Slime has enraged!"), new Color(175, 75, 255));
             *              else
             *                  Main.NewText("King Slime has enraged!", 175, 75, 255);
             *          }
             *      }
             *      else
             *      {
             *          Counter[1] = 0;
             *      }
             *  }
             * }
             * else //is berserk
             * {
             *  SharkCount = 1;
             *
             *  if (!masoBool[2])
             *  {
             *      masoBool[2] = true;
             *      Main.PlaySound(SoundID.Roar, npc.Center, 0);
             *  }
             *
             *  if (Counter[0] > 45) //faster slime spike rain
             *      Counter[0] = 45;
             *
             *  if (++Counter[2] > 30) //aimed spikes
             *  {
             *      Counter[2] = 0;
             *      const float gravity = 0.15f;
             *      float time = 45f;
             *      Vector2 distance = Main.player[npc.target].Center - npc.Center + Main.player[npc.target].velocity * 30f;
             *      distance.X = distance.X / time;
             *      distance.Y = distance.Y / time - 0.5f * gravity * time;
             *      for (int i = 0; i < 15; i++)
             *      {
             *          Projectile.NewProjectile(npc.Center, distance + Main.rand.NextVector2Square(-1f, 1f) * 2f,
             *              ModContent.ProjectileType<SlimeSpike>(), npc.damage / 4, 0f, Main.myPlayer);
             *      }
             *  }
             *
             *  if (npc.HasValidTarget && Main.netMode != NetmodeID.MultiplayerClient && Main.player[npc.target].position.Y > npc.position.Y) //player went back down
             *  {
             *      masoBool[0] = false;
             *      masoBool[2] = false;
             *      NetUpdateMaso(npc.whoAmI);
             *  }
             * }*/

            if (npc.life < npc.lifeMax / 2)
            {
                if (npc.ai[1] == 5) //when teleporting
                {
                    if (npc.ai[0] == 1 && !DidP2SpecialTeleport)
                    {
                        Main.PlaySound(SoundID.Roar, npc.Center, 0);
                    }

                    if (npc.HasPlayerTarget) //live update tp position
                    {
                        if (DidP2SpecialTeleport)
                        {
                            if (npc.ai[0] == 1) //only update y pos once
                            {
                                npc.localAI[2] = Main.player[npc.target].Center.Y;
                            }
                        }
                        else
                        {
                            Vector2 desiredTeleport = Main.player[npc.target].Center;
                            desiredTeleport.X += 800 * System.Math.Sign(Main.player[npc.target].Center.X - npc.Center.X); //tp ahead of player

                            if (Collision.CanHitLine(desiredTeleport, 0, 0, Main.player[npc.target].position, Main.player[npc.target].width, Main.player[npc.target].height))
                            {
                                npc.localAI[1] = desiredTeleport.X;
                                npc.localAI[2] = desiredTeleport.Y;
                            }
                        }
                    }
                }
                else if (npc.ai[1] == 6) //actually did the teleport and now regrowing
                {
                    DidP2SpecialTeleport = true;
                }
                else
                {
                    if (!DidP2SpecialTeleport)
                    {
                        npc.ai[2] += 60;
                    }

                    npc.ai[2] += 1f / 3f; //always increment the teleport timer
                }
            }

            // Drop summon
            EModeUtils.DropSummon(npc, ModContent.ItemType <SlimyCrown>(), NPC.downedSlimeKing, ref DroppedSummon);

            return(true);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        public override void AI(NPC npc)
        {
            EModeGlobalNPC.moonBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return;
            }

            if (!SpawnedRituals)
            {
                SpawnedRituals     = true;
                VulnerabilityState = 0;
                if (Main.netMode != NetmodeID.MultiplayerClient)
                {
                    Projectile.NewProjectile(npc.Center, Vector2.Zero, ModContent.ProjectileType <LunarRitual>(), 25, 0f, Main.myPlayer, 0f, npc.whoAmI);
                    Projectile.NewProjectile(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(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);

                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        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++)
                                    {
                                        Projectile.NewProjectile(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));
                                Projectile.NewProjectile(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++)
                                    {
                                        int p = Projectile.NewProjectile(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);
                                        int     n   = NPC.NewNPC((int)bodyPart.Center.X, (int)bodyPart.Center.Y, NPCID.AncientLight, 0, 0f, (Main.rand.NextFloat() - 0.5f) * 0.3f * 6.28318548202515f / 60f, vel.X, vel.Y);
                                        if (n != Main.maxNPCs)
                                        {
                                            Main.npc[n].velocity  = vel;
                                            Main.npc[n].netUpdate = true;
                                            if (Main.netMode == NetmodeID.Server)
                                            {
                                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                                            }
                                        }
                                    }
                                }
                            }
                            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);
                                    int p = Projectile.NewProjectile(npc.Center, vel, type, damage, 0f, Main.myPlayer, rotationModifier, speed);
                                    if (p != Main.maxProjectiles)
                                    {
                                        Main.projectile[p].timeLeft = 1800 - VulnerabilityTimer;
                                    }
                                    p = Projectile.NewProjectile(npc.Center, vel, type, damage, 0f, Main.myPlayer, -rotationModifier, speed);
                                    if (p != Main.maxProjectiles)
                                    {
                                        Main.projectile[p].timeLeft = 1800 - VulnerabilityTimer;
                                    }
                                }
                                Main.PlaySound(SoundID.Item84, npc.Center);
                            }
                            break;
                        }
                    }
                }
            }
            else //only when vulnerable
            {
                if (!EnteredPhase2)
                {
                    EnteredPhase2 = true;
                    AttackTimer   = 0;
                    Main.PlaySound(SoundID.Roar, Main.LocalPlayer.Center, 0);
                    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(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.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(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(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(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(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.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.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.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)
                {
                    VulnerabilityState = ++VulnerabilityState % 5;

                    VulnerabilityTimer = 0;
                    AttackTimer        = 0;
                    AttackMemory       = 0;

                    npc.netUpdate = true;
                    NetSync(npc);
                }
            }

            switch (VulnerabilityState)
            {
            case 0: Main.monolithType = 3; break;

            case 1: Main.monolithType = 0; break;

            case 2: Main.monolithType = 1; break;

            case 3:
                Main.monolithType = 2;
                if (VulnerabilityTimer < 120)     //so that player isn't punished for using weapons during prior phase
                {
                    Main.LocalPlayer.GetModPlayer <FargoPlayer>().MasomodeMinionNerfTimer = 0;
                }
                break;

            default: break;
            }

            EModeUtils.DropSummon(npc, ModContent.ItemType <CelestialSigil2>(), NPC.downedMoonlord, ref DroppedSummon, NPC.downedAncientCultist);
        }
Exemplo n.º 7
0
        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);
        }
Exemplo n.º 8
0
        public override void AI(NPC npc)
        {
            IsVenomEnraged = false;

            if (FargoSoulsWorld.SwarmActive)
            {
                return;
            }

            if (!npc.HasValidTarget)
            {
                npc.velocity.Y++;
            }

            const float innerRingDistance = 130f;
            const int   delayForRingToss  = 360 + 120;

            if (--RingTossTimer < 0)
            {
                RingTossTimer = delayForRingToss;
                if (Main.netMode != NetmodeID.MultiplayerClient && !Main.npc.Any(n => n.active && n.type == ModContent.NPCType <CrystalLeaf>() && n.ai[0] == npc.whoAmI && n.ai[1] == innerRingDistance))
                {
                    const int max      = 5;
                    float     rotation = 2f * (float)Math.PI / max;
                    for (int i = 0; i < max; i++)
                    {
                        Vector2 spawnPos = npc.Center + new Vector2(innerRingDistance, 0f).RotatedBy(rotation * i);
                        int     n        = NPC.NewNPC((int)spawnPos.X, (int)spawnPos.Y, ModContent.NPCType <CrystalLeaf>(), 0, npc.whoAmI, innerRingDistance, 0, rotation * i);
                        if (Main.netMode == NetmodeID.Server && n != Main.maxNPCs)
                        {
                            NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                        }
                    }
                }
            }
            else if (RingTossTimer == 120)
            {
                if (FargoSoulsWorld.MasochistModeReal)
                {
                    RingTossTimer = 0;
                }

                npc.netUpdate = true;
                NetSync(npc);

                if (Main.netMode != NetmodeID.MultiplayerClient)
                {
                    float speed = 8f;
                    int   p     = Projectile.NewProjectile(npc.Center, speed * npc.DirectionTo(Main.player[npc.target].Center), ModContent.ProjectileType <MutantMark2>(), npc.defDamage / 4, 0f, Main.myPlayer);
                    if (p != Main.maxProjectiles)
                    {
                        Main.projectile[p].timeLeft -= 300;

                        foreach (NPC n in Main.npc.Where(n => n.active && n.type == ModContent.NPCType <CrystalLeaf>() && n.ai[0] == npc.whoAmI && n.ai[1] == innerRingDistance)) //my crystal leaves
                        {
                            Main.PlaySound(SoundID.Grass, n.Center);
                            Projectile.NewProjectile(n.Center, Vector2.Zero, ModContent.ProjectileType <PlanteraCrystalLeafRing>(), npc.defDamage / 4, 0f, Main.myPlayer, Main.projectile[p].identity, n.ai[3]);

                            n.life = 0;
                            n.HitEffect();
                            n.checkDead();
                            n.active = false;
                            if (Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n.whoAmI);
                            }
                        }
                    }
                }
            }

            if (npc.life > npc.lifeMax / 2)
            {
                if (--DicerTimer < 0)
                {
                    DicerTimer = 150 * 4 + 25;
                    if (npc.HasValidTarget && Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(Main.player[npc.target].Center, Vector2.Zero, ModContent.ProjectileType <DicerPlantera>(), npc.defDamage / 4, 0f, Main.myPlayer, 0, 0);
                        for (int i = 0; i < 3; i++)
                        {
                            Projectile.NewProjectile(Main.player[npc.target].Center, 30f * npc.DirectionTo(Main.player[npc.target].Center).RotatedBy(2 * (float)Math.PI / 3 * i),
                                                     ModContent.ProjectileType <DicerPlantera>(), npc.defDamage / 4, 0f, Main.myPlayer, 1, 1);
                        }
                    }
                }
            }
            else
            {
                if (!InPhase2)
                {
                    InPhase2   = true;
                    DicerTimer = 0;
                }

                if (FargoSoulsWorld.MasochistModeReal)
                {
                    NPCs.EModeGlobalNPC.Aura(npc, 600, ModContent.BuffType <IvyVenom>(), true, 188);
                    npc.defense += 21;
                }

                void SpawnOuterLeafRing()
                {
                    const int   max      = 12;
                    const float distance = 250;
                    float       rotation = 2f * (float)Math.PI / max;

                    for (int i = 0; i < max; i++)
                    {
                        Vector2 spawnPos = npc.Center + new Vector2(distance, 0f).RotatedBy(rotation * i);
                        int     n        = NPC.NewNPC((int)spawnPos.X, (int)spawnPos.Y, ModContent.NPCType <CrystalLeaf>(), 0, npc.whoAmI, distance, 0, rotation * i);
                        if (Main.netMode == NetmodeID.Server && n != Main.maxNPCs)
                        {
                            NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                        }
                    }
                }

                if (!EnteredPhase2)
                {
                    EnteredPhase2 = true;

                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        if (!Main.npc.Any(n => n.active && n.type == ModContent.NPCType <CrystalLeaf>() && n.ai[0] == npc.whoAmI && n.ai[1] == innerRingDistance))
                        {
                            const int innerMax      = 5;
                            float     innerRotation = 2f * (float)Math.PI / innerMax;
                            for (int i = 0; i < innerMax; i++)
                            {
                                Vector2 spawnPos = npc.Center + new Vector2(innerRingDistance, 0f).RotatedBy(innerRotation * i);
                                int     n        = NPC.NewNPC((int)spawnPos.X, (int)spawnPos.Y, ModContent.NPCType <CrystalLeaf>(), 0, npc.whoAmI, innerRingDistance, 0, innerRotation * i);
                                if (Main.netMode == NetmodeID.Server && n != Main.maxNPCs)
                                {
                                    NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                                }
                            }
                        }

                        SpawnOuterLeafRing();

                        for (int i = 0; i < Main.maxProjectiles; i++)
                        {
                            if (Main.projectile[i].active && Main.projectile[i].hostile &&
                                (Main.projectile[i].type == ProjectileID.ThornBall ||
                                 Main.projectile[i].type == ModContent.ProjectileType <DicerPlantera>() ||
                                 Main.projectile[i].type == ModContent.ProjectileType <PlanteraCrystalLeafRing>() ||
                                 Main.projectile[i].type == ModContent.ProjectileType <CrystalLeafShot>()))
                            {
                                Main.projectile[i].Kill();
                            }
                        }
                    }
                }

                //explode time * explode repetitions + spread delay * propagations
                const int delayForDicers = 150 * 4 + 25 * 8;

                if (--DicerTimer < -120)
                {
                    DicerTimer = delayForDicers + delayForRingToss + 240;
                    //Counter3 = delayForDicers + 120; //extra compensation for the toss offset

                    npc.netUpdate = true;
                    NetSync(npc);

                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(npc.Center, Vector2.Zero, ModContent.ProjectileType <DicerPlantera>(), npc.defDamage / 4, 0f, Main.myPlayer);
                        for (int i = 0; i < 3; i++)
                        {
                            Projectile.NewProjectile(npc.Center, 25f * npc.DirectionTo(Main.player[npc.target].Center).RotatedBy(2 * (float)Math.PI / 3 * i),
                                                     ModContent.ProjectileType <DicerPlantera>(), npc.defDamage / 4, 0f, Main.myPlayer, 1, 8);
                        }
                    }
                }

                if (DicerTimer > delayForDicers || DicerTimer < 0)
                {
                    if (RingTossTimer > 120) //to still respawn the leaf ring if it's missing but disable throwing it
                    {
                        RingTossTimer = 120;
                    }
                }
                else if (DicerTimer < delayForDicers)
                {
                    RingTossTimer -= 1;

                    if (RingTossTimer % 2 == 0) //make sure plantera can get the timing for its check
                    {
                        RingTossTimer--;
                    }
                }
                else if (DicerTimer == delayForDicers)
                {
                    RingTossTimer = 121; //activate it immediately as the mines fade
                }

                IsVenomEnraged = npc.HasPlayerTarget && Main.player[npc.target].venom;

                if (--TentacleTimer <= 0)
                {
                    float slowdown = Math.Min(0.9f, -TentacleTimer / 60f);
                    if (FargoSoulsWorld.MasochistModeReal && slowdown > 0.75f)
                    {
                        slowdown = 0.75f;
                    }
                    npc.position -= npc.velocity * slowdown;

                    if (TentacleTimer == 0)
                    {
                        TentacleAttackAngleOffset = Main.rand.NextFloat(MathHelper.TwoPi);

                        Main.PlaySound(SoundID.Roar, npc.Center, 0);

                        npc.netUpdate = true;
                        NetSync(npc);

                        foreach (NPC n in Main.npc.Where(n => n.active && n.type == ModContent.NPCType <CrystalLeaf>() && n.ai[0] == npc.whoAmI && n.ai[1] > innerRingDistance)) //my crystal leaves
                        {
                            Main.PlaySound(SoundID.Grass, n.Center);

                            n.life = 0;
                            n.HitEffect();
                            n.checkDead();
                            n.active = false;
                            if (Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n.whoAmI);
                            }
                        }
                    }

                    const int maxTime           = 30;
                    const int interval          = 3;
                    float     maxDegreeCoverage = 45f; //on either side of the middle, the full coverage of one side is x2 this
                    if (TentacleTimer >= -maxTime && TentacleTimer % interval == 0)
                    {
                        int tentacleSpawnOffset = Math.Abs(TentacleTimer) / interval;
                        for (int i = -tentacleSpawnOffset; i <= tentacleSpawnOffset; i += tentacleSpawnOffset * 2)
                        {
                            float attackAngle = MathHelper.WrapAngle(
                                TentacleAttackAngleOffset
                                + MathHelper.ToRadians(maxDegreeCoverage / (maxTime / interval)) * (i + Main.rand.NextFloat(-0.5f, 0.5f))
                                );

                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                Projectile.NewProjectile(npc.Center, Main.rand.NextVector2CircularEdge(24, 24),
                                                         ModContent.ProjectileType <PlanteraTentacle>(), npc.damage / 4, 0f, Main.myPlayer, npc.whoAmI, attackAngle);
                                Projectile.NewProjectile(npc.Center, Main.rand.NextVector2CircularEdge(24, 24),
                                                         ModContent.ProjectileType <PlanteraTentacle>(), npc.damage / 4, 0f, Main.myPlayer, npc.whoAmI, attackAngle + MathHelper.Pi);
                            }

                            if (i == 0)
                            {
                                break;
                            }
                        }
                    }

                    if (TentacleTimer < -360)
                    {
                        TentacleTimer = 600 + Main.rand.Next(120);

                        if (!FargoSoulsWorld.MasochistModeReal)
                        {
                            npc.velocity = Vector2.Zero;
                        }

                        npc.netUpdate = true;
                        NetSync(npc);

                        SpawnOuterLeafRing();
                    }
                }
                else
                {
                    npc.position -= npc.velocity * (IsVenomEnraged ? 0.1f : 0.2f);
                }
            }

            EModeUtils.DropSummon(npc, ModContent.ItemType <PlanterasFruit>(), NPC.downedPlantBoss, ref DroppedSummon, NPC.downedMechBoss1 && NPC.downedMechBoss2 && NPC.downedMechBoss3);
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        public override void AI(NPC npc)
        {
            NPC.golemBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return;
            }

            /*if (npc.ai[0] == 0f && npc.velocity.Y == 0f) //manipulating golem jump ai
             * {
             *  if (npc.ai[1] > 0f)
             *  {
             *      npc.ai[1] += 5f; //count up to initiate jump faster
             *  }
             *  else
             *  {
             *      float threshold = -2f - (float)Math.Round(18f * npc.life / npc.lifeMax);
             *
             *      if (npc.ai[1] < threshold) //jump activates at npc.ai[1] == -1
             *          npc.ai[1] = threshold;
             *  }
             * }*/

            if (Main.LocalPlayer.active && Main.LocalPlayer.Distance(npc.Center) < 2000)
            {
                Main.LocalPlayer.AddBuff(ModContent.BuffType <LowGround>(), 2);
            }

            HealPerSecond = FargoSoulsWorld.MasochistModeReal ? 240 : 180;
            if (!IsInTemple) //temple enrage, more horiz move and fast jumps
            {
                HealPerSecond  *= 2;
                npc.position.X += npc.velocity.X / 2f;
                if (npc.velocity.Y < 0)
                {
                    npc.position.Y += npc.velocity.Y * 0.5f;
                    if (npc.velocity.Y > -2)
                    {
                        npc.velocity.Y = 20;
                    }
                }
            }

            if (npc.velocity.Y < 0) //jumping up
            {
                if (!HaveBoostedJumpHeight)
                {
                    HaveBoostedJumpHeight = true;
                    npc.velocity.Y       *= 1.25f;

                    if (!IsInTemple) //temple enrage
                    {
                        if (Main.player[npc.target].Center.Y < npc.Center.Y - 16 * 30)
                        {
                            npc.velocity.Y *= 1.5f;
                        }
                    }
                }
            }
            else
            {
                HaveBoostedJumpHeight = false;
            }

            if (DoStompBehaviour)
            {
                if (npc.velocity.Y == 0f)
                {
                    DoStompBehaviour = false;
                    IsInTemple       = Main.tile[(int)npc.Center.X / 16, (int)npc.Center.Y / 16] != null &&
                                       Main.tile[(int)npc.Center.X / 16, (int)npc.Center.Y / 16].wall == WallID.LihzahrdBrickUnsafe;

                    if (Main.netMode != NetmodeID.MultiplayerClient) //landing attacks
                    {
                        if (IsInTemple)                              //in temple
                        {
                            StompAttackCounter++;
                            if (StompAttackCounter == 1) //plant geysers
                            {
                                if (FargoSoulsWorld.MasochistModeReal)
                                {
                                    StompAttackCounter++;
                                }

                                Vector2 spawnPos = new Vector2(npc.position.X, npc.Center.Y); //floor geysers
                                spawnPos.X -= npc.width * 7;
                                for (int i = 0; i < 6; i++)
                                {
                                    int tilePosX = (int)spawnPos.X / 16 + npc.width * i * 3 / 16;
                                    int tilePosY = (int)spawnPos.Y / 16;// + 1;

                                    Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8, 0f, 0f, ModContent.ProjectileType <GolemGeyser2>(), npc.damage / 4, 0f, Main.myPlayer, npc.whoAmI);
                                }

                                spawnPos = npc.Center;
                                for (int i = -3; i <= 3; i++) //ceiling geysers
                                {
                                    int tilePosX = (int)spawnPos.X / 16 + npc.width * i * 3 / 16;
                                    int tilePosY = (int)spawnPos.Y / 16;// + 1;

                                    Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8, 0f, 0f, ModContent.ProjectileType <GolemGeyser>(), npc.damage / 4, 0f, Main.myPlayer, npc.whoAmI);
                                }
                            }
                            else if (StompAttackCounter == 2) //empty jump
                            {
                            }
                            else if (StompAttackCounter == 3) //rocks fall
                            {
                                if (FargoSoulsWorld.MasochistModeReal)
                                {
                                    StompAttackCounter = 0;
                                }

                                if (npc.HasPlayerTarget)
                                {
                                    for (int i = -2; i <= 2; i++)
                                    {
                                        int tilePosX = (int)Main.player[npc.target].Center.X / 16;
                                        int tilePosY = (int)Main.player[npc.target].Center.Y / 16;// + 1;
                                        tilePosX += 4 * i;

                                        if (Main.tile[tilePosX, tilePosY] == null)
                                        {
                                            Main.tile[tilePosX, tilePosY] = new Tile();
                                        }

                                        //first move up through solid tiles
                                        while (Main.tile[tilePosX, tilePosY].nactive() && Main.tileSolid[Main.tile[tilePosX, tilePosY].type])
                                        {
                                            tilePosY--;
                                            if (Main.tile[tilePosX, tilePosY] == null)
                                            {
                                                Main.tile[tilePosX, tilePosY] = new Tile();
                                            }
                                        }
                                        //then move up through air until next ceiling reached
                                        while (!(Main.tile[tilePosX, tilePosY].nactive() && Main.tileSolid[Main.tile[tilePosX, tilePosY].type]))
                                        {
                                            tilePosY--;
                                            if (Main.tile[tilePosX, tilePosY] == null)
                                            {
                                                Main.tile[tilePosX, tilePosY] = new Tile();
                                            }
                                        }

                                        Vector2 spawn = new Vector2(tilePosX * 16 + 8, tilePosY * 16 + 8);
                                        Projectile.NewProjectile(spawn, Vector2.Zero, ModContent.ProjectileType <GolemBoulder>(), npc.damage / 4, 0f, Main.myPlayer);
                                    }
                                }
                            }
                            else //empty jump
                            {
                                StompAttackCounter = 0;
                            }
                        }
                        else //outside temple
                        {
                            Vector2 spawnPos = new Vector2(npc.position.X, npc.Center.Y);
                            spawnPos.X -= npc.width * 7;
                            for (int i = 0; i < 6; i++)
                            {
                                int tilePosX = (int)spawnPos.X / 16 + npc.width * i * 3 / 16;
                                int tilePosY = (int)spawnPos.Y / 16;// + 1;

                                if (Main.tile[tilePosX, tilePosY] == null)
                                {
                                    Main.tile[tilePosX, tilePosY] = new Tile();
                                }

                                while (!(Main.tile[tilePosX, tilePosY].nactive() && Main.tileSolid[(int)Main.tile[tilePosX, tilePosY].type]))
                                {
                                    tilePosY++;
                                    if (Main.tile[tilePosX, tilePosY] == null)
                                    {
                                        Main.tile[tilePosX, tilePosY] = new Tile();
                                    }
                                }

                                if (npc.HasPlayerTarget && Main.player[npc.target].position.Y > tilePosY * 16)
                                {
                                    Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8, 6.3f, 6.3f,
                                                             ProjectileID.FlamesTrap, npc.damage / 4, 0f, Main.myPlayer);
                                    Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8, -6.3f, 6.3f,
                                                             ProjectileID.FlamesTrap, npc.damage / 4, 0f, Main.myPlayer);
                                }

                                Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8, 0f, -8f, ProjectileID.GeyserTrap, npc.damage / 4, 0f, Main.myPlayer);

                                Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8 - 640, 0f, -8f, ProjectileID.GeyserTrap, npc.damage / 4, 0f, Main.myPlayer);
                                Projectile.NewProjectile(tilePosX * 16 + 8, tilePosY * 16 + 8 - 640, 0f, 8f, ProjectileID.GeyserTrap, npc.damage / 4, 0f, Main.myPlayer);
                            }
                            if (npc.HasPlayerTarget)
                            {
                                for (int i = -3; i <= 3; i++)
                                {
                                    int tilePosX = (int)Main.player[npc.target].Center.X / 16;
                                    int tilePosY = (int)Main.player[npc.target].Center.Y / 16;// + 1;
                                    tilePosX += 10 * i;

                                    if (Main.tile[tilePosX, tilePosY] == null)
                                    {
                                        Main.tile[tilePosX, tilePosY] = new Tile();
                                    }

                                    for (int j = 0; j < 30; j++)
                                    {
                                        if (Main.tile[tilePosX, tilePosY].nactive() && Main.tileSolid[Main.tile[tilePosX, tilePosY].type])
                                        {
                                            break;
                                        }
                                        tilePosY--;
                                        if (Main.tile[tilePosX, tilePosY] == null)
                                        {
                                            Main.tile[tilePosX, tilePosY] = new Tile();
                                        }
                                    }

                                    Vector2 spawn = new Vector2(tilePosX * 16 + 8, tilePosY * 16 + 8);
                                    Projectile.NewProjectile(spawn, Vector2.Zero, ModContent.ProjectileType <GolemBoulder>(), npc.damage / 4, 0f, Main.myPlayer);
                                }
                            }
                        }

                        //golem's anti-air fireball spray (whenever he lands while player is below)

                        /*if (npc.HasPlayerTarget && Main.player[npc.target].position.Y > npc.position.Y + npc.height)
                         * {
                         *  float gravity = 0.2f; //shoot down
                         *  const float time = 60f;
                         *  Vector2 distance = Main.player[npc.target].Center - npc.Center;
                         *  distance += Main.player[npc.target].velocity * 45f;
                         *  distance.X = distance.X / time;
                         *  distance.Y = distance.Y / time - 0.5f * gravity * time;
                         *  if (Math.Sign(distance.Y) != Math.Sign(gravity))
                         *      distance.Y = 0f; //cannot arc shots to hit someone on the same elevation
                         *  int max = masobool3 ? 1 : 3;
                         *  for (int i = -max; i <= max; i++)
                         *  {
                         *      Projectile.NewProjectile(npc.Center.X, npc.Center.Y, distance.X + i * 1.5f, distance.Y,
                         *          ModContent.ProjectileType<GolemFireball>(), npc.damage / 5, 0f, Main.myPlayer, gravity, 0f);
                         *  }
                         * }*/
                    }
                }
            }
            else if (npc.velocity.Y > 0)
            {
                DoStompBehaviour = true;
            }

            if (++SpikyBallTimer >= 900)                                                 //spray spiky balls
            {
                if (Main.tile[(int)npc.Center.X / 16, (int)npc.Center.Y / 16] != null && //in temple
                    Main.tile[(int)npc.Center.X / 16, (int)npc.Center.Y / 16].wall == WallID.LihzahrdBrickUnsafe)
                {
                    if (npc.velocity.Y > 0) //only when falling, implicitly assume at peak of a jump
                    {
                        SpikyBallTimer = FargoSoulsWorld.MasochistModeReal ? 600 : 0;
                        for (int i = 0; i < 8; i++)
                        {
                            Projectile.NewProjectile(npc.position.X + Main.rand.Next(npc.width), npc.position.Y + Main.rand.Next(npc.height),
                                                     Main.rand.NextFloat(-0.3f, 0.3f), Main.rand.NextFloat(-10, -6), ModContent.ProjectileType <GolemSpikyBall>(), npc.damage / 4, 0f, Main.myPlayer);
                        }
                    }
                }
                else //outside temple
                {
                    SpikyBallTimer = 600; //do it more often
                    for (int i = 0; i < 16; i++)
                    {
                        Projectile.NewProjectile(npc.position.X + Main.rand.Next(npc.width), npc.position.Y + Main.rand.Next(npc.height),
                                                 Main.rand.NextFloat(-1f, 1f), Main.rand.Next(-20, -9), ModContent.ProjectileType <GolemSpikyBall>(), npc.damage / 4, 0f, Main.myPlayer);
                    }
                }
            }

            /*Counter2++;
             * if (Counter2 > 240) //golem's anti-air fireball spray (when player is above)
             * {
             *  Counter2 = 0;
             *  if (npc.HasPlayerTarget && Main.player[npc.target].position.Y < npc.position.Y
             *      && Main.netMode != NetmodeID.MultiplayerClient) //shoutouts to arterius
             *  {
             *      bool inTemple = Main.tile[(int)npc.Center.X / 16, (int)npc.Center.Y / 16] != null && //in temple
             *          Main.tile[(int)npc.Center.X / 16, (int)npc.Center.Y / 16].wall == WallID.LihzahrdBrickUnsafe;
             *
             *      float gravity = -0.2f; //normally floats up
             *      //if (Main.player[npc.target].position.Y > npc.position.Y + npc.height) gravity *= -1f; //aim down if player below golem
             *      const float time = 60f;
             *      Vector2 distance = Main.player[npc.target].Center - npc.Center;
             *      distance += Main.player[npc.target].velocity * 45f;
             *      distance.X = distance.X / time;
             *      distance.Y = distance.Y / time - 0.5f * gravity * time;
             *      if (Math.Sign(distance.Y) != Math.Sign(gravity))
             *          distance.Y = 0f; //cannot arc shots to hit someone on the same elevation
             *      int max = inTemple ? 1 : 3;
             *      for (int i = -max; i <= max; i++)
             *      {
             *          Projectile.NewProjectile(npc.Center.X, npc.Center.Y, distance.X + i, distance.Y,
             *              ModContent.ProjectileType<GolemFireball>(), npc.damage / 5, 0f, Main.myPlayer, gravity, 0f);
             *      }
             *  }
             * }*/

            EModeUtils.DropSummon(npc, ModContent.ItemType <LihzahrdPowerCell2>(), NPC.downedGolemBoss, ref DroppedSummon, NPC.downedPlantBoss);
        }
Exemplo n.º 11
0
        public override void AI(NPC npc)
        {
            EModeGlobalNPC.primeBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return;
            }

            if (npc.ai[1] == 3) //despawn faster
            {
                if (npc.timeLeft > 60)
                {
                    npc.timeLeft = 60;
                }
            }

            if (npc.ai[1] == 0f)
            {
                HaveShotGuardians = false;

                if (npc.ai[2] == 600 - 90) //telegraph spin
                {
                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(npc.Center, Vector2.Zero, ModContent.ProjectileType <TargetingReticle>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type);
                    }
                }
                if (npc.ai[2] < 600 - 5)
                {
                    MemorizedTarget = npc.target;
                }
            }

            if (npc.ai[1] == 1f)
            {
                if (MemorizedTarget > -1 && MemorizedTarget < Main.maxPlayers)
                {
                    npc.target      = MemorizedTarget;
                    npc.netUpdate   = true;
                    MemorizedTarget = -1;
                    if (!npc.HasValidTarget)
                    {
                        npc.TargetClosest(false);
                    }
                }
            }

            if (npc.ai[0] != 2f || FargoSoulsWorld.MasochistModeReal)
            {
                if (!HaveShotGuardians && npc.ai[1] == 1f && npc.ai[2] > 2f) //spinning, do wave of guardians
                {
                    HaveShotGuardians = true;

                    if (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      = -10 * Vector2.UnitX;
                                spawnPos = Main.player[npc.target].Center + spawnPos.RotatedBy(Math.PI / 2 * i);
                                vel      = vel.RotatedBy(Math.PI / 2 * i);
                                int p = Projectile.NewProjectile(spawnPos, vel, ModContent.ProjectileType <PrimeGuardian>(), npc.damage / 4, 0f, Main.myPlayer);
                                if (p != Main.maxProjectiles)
                                {
                                    Main.projectile[p].timeLeft = 1200 / 10 + 1;
                                }
                            }
                        }
                    }
                }

                if (++ProjectileAttackTimer >= 360)
                {
                    ProjectileAttackTimer = 0;

                    if (npc.HasPlayerTarget) //skeleton commando rockets LUL
                    {
                        Vector2 speed = Main.player[npc.target].Center - npc.Center;
                        speed.X += Main.rand.Next(-20, 21);
                        speed.Y += Main.rand.Next(-20, 21);
                        speed.Normalize();

                        int damage = npc.damage / 4;

                        if (Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            Projectile.NewProjectile(npc.Center, 3f * speed, ProjectileID.RocketSkeleton, damage, 0f, Main.myPlayer);
                            Projectile.NewProjectile(npc.Center, 3f * speed.RotatedBy(MathHelper.ToRadians(5f)), ProjectileID.RocketSkeleton, damage, 0f, Main.myPlayer);
                            Projectile.NewProjectile(npc.Center, 3f * speed.RotatedBy(MathHelper.ToRadians(-5f)), ProjectileID.RocketSkeleton, damage, 0f, Main.myPlayer);
                        }

                        Main.PlaySound(SoundID.Item11, npc.Center);
                    }
                }
            }

            if (npc.ai[0] != 2f)                  //in phase 1
            {
                if (npc.life < npc.lifeMax * .75) //enter phase 2
                {
                    npc.ai[0] = 2f;

                    npc.ai[1] = 0f;              //revert to nonspin mode
                    npc.ai[2] = 600f - 90f - 2f; //but only for telegraph and then go back into spin

                    npc.ai[3]     = 0f;
                    npc.netUpdate = true;

                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        if (!NPC.AnyNPCs(NPCID.PrimeLaser)) //revive all dead limbs
                        {
                            int n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeLaser, npc.whoAmI, 1f, npc.whoAmI, 0f, 150f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                        }
                        if (!NPC.AnyNPCs(NPCID.PrimeSaw))
                        {
                            int n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeSaw, npc.whoAmI, 1f, npc.whoAmI, 0f, 0f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                        }
                        if (!NPC.AnyNPCs(NPCID.PrimeCannon))
                        {
                            int n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeCannon, npc.whoAmI, -1f, npc.whoAmI, 0f, 150f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                        }
                        if (!NPC.AnyNPCs(NPCID.PrimeVice))
                        {
                            int n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeVice, npc.whoAmI, -1f, npc.whoAmI, 0f, 0f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                        }
                    }

                    Main.PlaySound(SoundID.Roar, (int)npc.position.X, (int)npc.position.Y, 0);
                    return;
                }
            }
            else //in phase 2
            {
                npc.dontTakeDamage = false;

                if (npc.ai[1] == 1f && npc.ai[2] > 2f) //spinning
                {
                    if (npc.HasValidTarget)
                    {
                        npc.position += npc.DirectionTo(Main.player[npc.target].Center) * 5;
                    }

                    if (++ProjectileAttackTimer > 90) //projectile attack
                    {
                        ProjectileAttackTimer = -30;
                        int damage = npc.defDamage / 3;
                        if (Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            Main.PlaySound(SoundID.Item, (int)npc.position.X, (int)npc.position.Y, 105, 2f, -0.3f);

                            float modifier = (float)npc.life / npc.lifeMax;
                            if (FargoSoulsWorld.MasochistModeReal)
                            {
                                modifier /= 2;
                            }
                            int starMax = (int)(7f - 6f * modifier);

                            const int max = 8;
                            for (int i = 0; i < max; i++)
                            {
                                Vector2 speed = 12f * npc.DirectionTo(Main.player[npc.target].Center).RotatedBy(2 * Math.PI / max * i);
                                for (int j = -starMax; j <= starMax; j++)
                                {
                                    int p = Projectile.NewProjectile(npc.Center, speed.RotatedBy(MathHelper.ToRadians(2f) * j),
                                                                     ModContent.ProjectileType <DarkStar>(), damage, 0f, Main.myPlayer);
                                    Main.projectile[p].soundDelay = -1; //dont play sounds
                                    if (p != Main.maxProjectiles)
                                    {
                                        Main.projectile[p].timeLeft = 480;
                                    }
                                }
                            }
                        }
                    }
                }
                else if (npc.ai[1] == 2f) //dg phase
                {
                    while (npc.buffType[0] != 0)
                    {
                        npc.buffImmune[npc.buffType[0]] = true;
                        npc.DelBuff(0);
                    }

                    if (!Main.dayTime)
                    {
                        npc.position -= npc.velocity * 0.1f;

                        if (!FargoSoulsWorld.MasochistModeReal && ++DungeonGuardianStartup < 120)
                        {
                            npc.position -= npc.velocity * (120 - DungeonGuardianStartup) / 120 * 0.9f;
                        }
                    }
                }
                else //not spinning
                {
                    ProjectileAttackTimer = 0; //buffer this for spin

                    npc.position += npc.velocity / 4f;
                }

                if (!FullySpawnedLimbs && npc.ai[3] >= 0f) //spawn 4 more limbs
                {
                    npc.ai[3]++;
                    if (npc.ai[3] == 60f) //first set of limb management
                    {
                        int[] limbs = { NPCID.PrimeCannon, NPCID.PrimeLaser, NPCID.PrimeSaw, NPCID.PrimeVice };

                        foreach (NPC l in Main.npc.Where(l => l.active && l.ai[1] == npc.whoAmI && limbs.Contains(l.type)))
                        {
                            l.GetEModeNPCMod <PrimeLimb>().IsSwipeLimb = true;
                            l.ai[2] = 0;

                            int heal = (l.lifeMax - l.life) / 2;
                            l.life += heal;
                            if (heal > 0)
                            {
                                l.HealEffect(heal);
                            }
                            l.dontTakeDamage = false;

                            l.netUpdate = true;
                            NetSync(l);
                        }

                        if (Main.netMode != NetmodeID.MultiplayerClient) //now spawn the other four
                        {
                            int n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeLaser, npc.whoAmI, -1f, npc.whoAmI, 0f, 150f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                            n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeSaw, npc.whoAmI, -1f, npc.whoAmI, 0f, 0f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                            n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeCannon, npc.whoAmI, 1f, npc.whoAmI, 0f, 150f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                            n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.PrimeVice, npc.whoAmI, 1f, npc.whoAmI, 0f, 0f, npc.target);
                            if (n != Main.maxNPCs && Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                        }
                    }
                    else if (npc.ai[3] >= 180f)
                    {
                        FullySpawnedLimbs = true;
                        npc.ai[3]         = -1f;
                        npc.netUpdate     = true;

                        Main.PlaySound(SoundID.Roar, (int)npc.position.X, (int)npc.position.Y, 0);

                        if (Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            int rangedArm = Main.rand.NextBool() ? NPCID.PrimeCannon : NPCID.PrimeLaser;
                            int meleeArm  = Main.rand.NextBool() ? NPCID.PrimeSaw : NPCID.PrimeVice;

                            int[] limbs = { NPCID.PrimeCannon, NPCID.PrimeLaser, NPCID.PrimeSaw, NPCID.PrimeVice };

                            foreach (NPC l in Main.npc.Where(l => l.active && l.ai[1] == npc.whoAmI && limbs.Contains(l.type) && !l.GetEModeNPCMod <PrimeLimb>().IsSwipeLimb))
                            {
                                l.GetEModeNPCMod <PrimeLimb>().RangedAttackMode = npc.type == rangedArm || npc.type == meleeArm;

                                int heal = l.lifeMax;
                                l.life = Math.Min(l.life + l.lifeMax / 2, l.lifeMax);
                                heal  -= l.life;
                                if (heal > 0)
                                {
                                    l.HealEffect(heal);
                                }

                                l.dontTakeDamage = false;

                                l.netUpdate = true;
                                NetSync(l);
                            }
                        }
                    }
                }
            }

            EModeUtils.DropSummon(npc, ModContent.ItemType <MechSkull>(), NPC.downedMechBoss3, ref DroppedSummon, Main.hardMode);
        }
Exemplo n.º 12
0
        public override bool PreAI(NPC npc)
        {
            base.AI(npc);

            EModeGlobalNPC.beeBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return(true);
            }

            if (!SpawnedRoyalSubjectWave1 && npc.life < npc.lifeMax / 3 * 2 && npc.HasPlayerTarget)
            {
                SpawnedRoyalSubjectWave1 = true;

                Vector2 vector72 = new Vector2(npc.position.X + npc.width / 2 + Main.rand.Next(20) * npc.direction, npc.position.Y + npc.height * 0.8f);

                int n = NPC.NewNPC((int)vector72.X, (int)vector72.Y, ModContent.NPCType <RoyalSubject>(), 0, 0f, 0f, 0f, 0f, 255);
                if (n != Main.maxNPCs)
                {
                    Main.npc[n].velocity.X = Main.rand.Next(-200, 201) * 0.002f;
                    Main.npc[n].velocity.Y = Main.rand.Next(-200, 201) * 0.002f;
                    Main.npc[n].localAI[0] = 60f;
                    if (Main.netMode == NetmodeID.Server)
                    {
                        NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                    }
                }

                FargoSoulsUtil.PrintText("Royal Subject has awoken!", new Color(175, 75, 255));

                npc.netUpdate = true;
                NetSync(npc);
            }

            if (!SpawnedRoyalSubjectWave2 && npc.life < npc.lifeMax / 3 && npc.HasPlayerTarget)
            {
                SpawnedRoyalSubjectWave2 = true;

                if (FargoSoulsWorld.MasochistModeReal)
                {
                    SpawnedRoyalSubjectWave1 = false; //do this again
                }
                Vector2 vector72 = new Vector2(npc.position.X + npc.width / 2 + Main.rand.Next(20) * npc.direction, npc.position.Y + npc.height * 0.8f);

                int n = NPC.NewNPC((int)vector72.X, (int)vector72.Y, ModContent.NPCType <RoyalSubject>(), 0, 0f, 0f, 0f, 0f, 255);
                if (n != Main.maxNPCs)
                {
                    Main.npc[n].velocity.X = Main.rand.Next(-200, 201) * 0.1f;
                    Main.npc[n].velocity.Y = Main.rand.Next(-200, 201) * 0.1f;
                    Main.npc[n].localAI[0] = 60f;
                    if (Main.netMode == NetmodeID.Server)
                    {
                        NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                    }
                }

                FargoSoulsUtil.PrintText("Royal Subject has awoken!", new Color(175, 75, 255));

                NPC.SpawnOnPlayer(npc.target, ModContent.NPCType <RoyalSubject>()); //so that both dont stack for being spawned from qb

                npc.netUpdate = true;
                NetSync(npc);
            }

            if (!InPhase2 && npc.life < npc.lifeMax / 2) //enable new attack and roar below 50%
            {
                InPhase2 = true;
                Main.PlaySound(SoundID.Roar, npc.Center, 0);

                if (FargoSoulsWorld.MasochistModeReal)
                {
                    SpawnedRoyalSubjectWave1 = false; //do this again
                }
                npc.netUpdate = true;
                NetSync(npc);
            }

            if (NPC.AnyNPCs(ModContent.NPCType <RoyalSubject>()))
            {
                npc.HitSound = SoundID.NPCHit4;
                npc.color    = new Color(127, 127, 127);

                int dustId = Dust.NewDust(npc.position, npc.width, npc.height, 1, 0f, 0f, 100, default(Color), 2f);
                Main.dust[dustId].noGravity = true;
                int dustId3 = Dust.NewDust(npc.position, npc.width, npc.height, 1, 0f, 0f, 100, default(Color), 2f);
                Main.dust[dustId3].noGravity = true;

                npc.ai[0] = 3; //always shoot stingers mode
            }
            else
            {
                npc.HitSound = SoundID.NPCHit1;
                npc.color    = default;

                if (InPhase2 && HiveThrowTimer % 2 == 0)
                {
                    HiveThrowTimer++; //throw hives faster when no royal subjects alive
                }
            }

            if (FargoSoulsWorld.MasochistModeReal)
            {
                HiveThrowTimer++;
            }

            if (!InPhase2)
            {
                if (npc.ai[0] == 3f || npc.ai[0] == 1f) //only when in stationary modes
                {
                    if (++StingerRingTimer > 90 * 3)
                    {
                        StingerRingTimer = 0;
                    }

                    if (StingerRingTimer % 90 == 0)
                    {
                        if (Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            FargoSoulsUtil.XWay(StingerRingTimer == 90 * 3 ? 16 : 8, npc.Center, ProjectileID.Stinger, 6, 11, 1);
                        }
                    }
                }
            }
            else
            {
                if (++HiveThrowTimer > 570 && BeeSwarmTimer <= 600 && (npc.ai[0] == 3f || npc.ai[0] == 1f)) //lobs hives below 50%, not dashing
                {
                    HiveThrowTimer = 0;

                    npc.netUpdate = true;
                    NetSync(npc);

                    const float gravity  = 0.25f;
                    float       time     = 75f;
                    Vector2     distance = Main.player[npc.target].Center - Vector2.UnitY * 16 - npc.Center + Main.player[npc.target].velocity * 30f;
                    distance.X = distance.X / time;
                    distance.Y = distance.Y / time - 0.5f * gravity * time;
                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(npc.Center, distance, ModContent.ProjectileType <Beehive>(),
                                                 npc.damage / 4, 0f, Main.myPlayer, time - 5);
                    }
                }

                if (npc.ai[0] == 0 && npc.ai[1] == 1f) //if qb tries to start doing dashes of her own volition
                {
                    npc.ai[0]     = 3f;
                    npc.ai[1]     = 0f; //don't
                    npc.netUpdate = true;
                }
            }

            //only while stationary mode
            if (npc.ai[0] == 3f || npc.ai[0] == 1f)
            {
                if (InPhase2 && ++BeeSwarmTimer > 600)
                {
                    if (BeeSwarmTimer < 720) //slow down
                    {
                        if (BeeSwarmTimer == 601)
                        {
                            npc.netUpdate = true;
                            NetSync(npc);

                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                Projectile.NewProjectile(npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type);
                            }

                            if (npc.HasValidTarget)
                            {
                                Main.PlaySound(SoundID.ForceRoar, Main.player[npc.target].Center, -1); //eoc roar
                            }
                            if (FargoSoulsWorld.MasochistModeReal)
                            {
                                BeeSwarmTimer += 30;
                            }
                        }

                        if (Collision.CanHitLine(npc.Center, 0, 0, Main.player[npc.target].Center, 0, 0))
                        {
                            npc.velocity *= 0.975f;
                        }
                        else if (BeeSwarmTimer > 630)
                        {
                            BeeSwarmTimer--; //stall this section until has line of sight
                            return(true);
                        }
                    }
                    else if (BeeSwarmTimer < 840) //spray bees
                    {
                        npc.velocity = Vector2.Zero;

                        if (BeeSwarmTimer % 2 == 0 && Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            const float rotation = 0.025f;
                            for (int i = -1; i <= 1; i += 2)
                            {
                                Projectile.NewProjectile(npc.Center + new Vector2(3 * npc.direction, 15), i * Main.rand.NextFloat(9f, 18f) * Vector2.UnitX.RotatedBy(MathHelper.ToRadians(Main.rand.NextFloat(-45, 45))),
                                                         ModContent.ProjectileType <Bee>(), npc.damage / (FargoSoulsWorld.MasochistModeReal ? 3 : 4), 0f, Main.myPlayer, npc.target, Main.rand.NextBool() ? -rotation : rotation);
                            }
                        }
                    }
                    else if (BeeSwarmTimer > 870) //return to normal AI
                    {
                        BeeSwarmTimer   = 0;
                        HiveThrowTimer -= 60;

                        npc.netUpdate = true;
                        NetSync(npc);

                        npc.ai[0] = 0f;
                        npc.ai[1] = 4f; //trigger dashes, but skip the first one
                        npc.ai[2] = -44f;
                        npc.ai[3] = 0f;
                    }

                    if (npc.netUpdate)
                    {
                        npc.netUpdate = false;

                        if (Main.netMode == NetmodeID.Server)
                        {
                            NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, npc.whoAmI);
                        }
                    }
                    return(false);
                }
            }

            if (npc.ai[0] == 0 && npc.ai[1] == 4 && npc.ai[2] < 0) //when about to do dashes triggered by royal subjects/bee swarm, telegraph and stall
            {
                if (npc.ai[2] == -44)                              //telegraph
                {
                    Main.PlaySound(SoundID.Item21, npc.Center);

                    for (int i = 0; i < 44; i++)
                    {
                        int d = Dust.NewDust(npc.position, npc.width, npc.height, Main.rand.NextBool() ? 152 : 153, npc.velocity.X * 0.2f, npc.velocity.Y * 0.2f);
                        Main.dust[d].scale     = Main.rand.NextFloat(1f, 3f);
                        Main.dust[d].velocity *= Main.rand.NextFloat(4.4f);
                        Main.dust[d].noGravity = Main.rand.NextBool();
                        if (Main.dust[d].noGravity)
                        {
                            Main.dust[d].scale    *= 2.2f;
                            Main.dust[d].velocity *= 4.4f;
                        }
                    }

                    if (FargoSoulsWorld.MasochistModeReal)
                    {
                        npc.ai[2] = 0;
                    }
                }

                npc.velocity *= 0.95f;
                npc.ai[2]++;

                return(false);
            }

            EModeUtils.DropSummon(npc, ModContent.ItemType <Abeemination2>(), NPC.downedQueenBee, ref DroppedSummon);

            return(true);
        }
Exemplo n.º 13
0
        public override bool PreAI(NPC npc)
        {
            bool result = base.PreAI(npc);

            NPC.golemBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return(result);
            }

            /*if (npc.ai[0] == 0f && npc.velocity.Y == 0f) //manipulating golem jump ai
             * {
             *  if (npc.ai[1] > 0f)
             *  {
             *      npc.ai[1] += 5f; //count up to initiate jump faster
             *  }
             *  else
             *  {
             *      float threshold = -2f - (float)Math.Round(18f * npc.life / npc.lifeMax);
             *
             *      if (npc.ai[1] < threshold) //jump activates at npc.ai[1] == -1
             *          npc.ai[1] = threshold;
             *  }
             * }*/

            foreach (Player p in Main.player)
            {
                if (p.active && p.Distance(npc.Center) < 2000)
                {
                    p.AddBuff(ModContent.BuffType <LowGround>(), 2);
                }
            }

            HealPerSecond = FargoSoulsWorld.MasochistModeReal ? 240 : 180;
            if (!IsInTemple) //temple enrage, more horiz move and fast jumps
            {
                HealPerSecond  *= 2;
                npc.position.X += npc.velocity.X / 2f;
                if (npc.velocity.Y < 0)
                {
                    npc.position.Y += npc.velocity.Y * 0.5f;
                    if (npc.velocity.Y > -2)
                    {
                        npc.velocity.Y = 20;
                    }
                }
            }

            if (npc.velocity.Y < 0) //jumping up
            {
                if (!HaveBoostedJumpHeight)
                {
                    HaveBoostedJumpHeight = true;
                    npc.velocity.Y       *= 1.25f;

                    if (!IsInTemple) //temple enrage
                    {
                        if (Main.player[npc.target].Center.Y < npc.Center.Y - 16 * 30)
                        {
                            npc.velocity.Y *= 1.5f;
                        }
                    }
                }
            }
            else
            {
                HaveBoostedJumpHeight = false;
            }

            if (DoStompBehaviour)
            {
                if (npc.velocity.Y == 0f) //landing attacks
                {
                    DoStompBehaviour = false;
                    IsInTemple       = Framing.GetTileSafely(npc.Center).WallType == WallID.LihzahrdBrickUnsafe;

                    if (IsInTemple) //in temple
                    {
                        StompAttackCounter++;
                        if (StompAttackCounter == 1) //plant geysers
                        {
                            if (FargoSoulsWorld.MasochistModeReal)
                            {
                                StompAttackCounter++;
                            }

                            Vector2 spawnPos = new Vector2(npc.position.X, npc.Center.Y); //floor geysers
                            spawnPos.X -= npc.width * 7;
                            for (int i = 0; i < 6; i++)
                            {
                                int tilePosX = (int)spawnPos.X / 16 + npc.width * i * 3 / 16;
                                int tilePosY = (int)spawnPos.Y / 16;// + 1;

                                if (Main.netMode != NetmodeID.MultiplayerClient)
                                {
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8, 0f, 0f, ModContent.ProjectileType <GolemGeyser2>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer, npc.whoAmI);
                                }
                            }

                            spawnPos = npc.Center;
                            for (int i = -3; i <= 3; i++) //ceiling geysers
                            {
                                int tilePosX = (int)spawnPos.X / 16 + npc.width * i * 3 / 16;
                                int tilePosY = (int)spawnPos.Y / 16;// + 1;

                                if (Main.netMode != NetmodeID.MultiplayerClient)
                                {
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8, 0f, 0f, ModContent.ProjectileType <GolemGeyser>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer, npc.whoAmI);
                                }
                            }
                        }
                        else if (StompAttackCounter == 2) //empty jump
                        {
                        }
                        else if (StompAttackCounter == 3) //rocks fall
                        {
                            if (FargoSoulsWorld.MasochistModeReal)
                            {
                                StompAttackCounter = 0;
                            }

                            if (npc.HasPlayerTarget)
                            {
                                if (!Main.dedServ)
                                {
                                    Main.LocalPlayer.GetModPlayer <FargoSoulsPlayer>().Screenshake = 20;
                                }

                                if (Main.netMode != NetmodeID.MultiplayerClient)
                                {
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ProjectileID.DD2OgreSmash, 0, 0, Main.myPlayer);
                                }

                                for (int i = -2; i <= 2; i++)
                                {
                                    int tilePosX = (int)Main.player[npc.target].Center.X / 16;
                                    int tilePosY = (int)Main.player[npc.target].Center.Y / 16;// + 1;
                                    tilePosX += 4 * i;

                                    //first move up through solid tiles
                                    while (Main.tile[tilePosX, tilePosY].HasUnactuatedTile && Main.tileSolid[Main.tile[tilePosX, tilePosY].TileType])
                                    {
                                        tilePosY--;
                                    }
                                    //then move up through air until next ceiling reached
                                    while (!(Main.tile[tilePosX, tilePosY].HasUnactuatedTile && Main.tileSolid[Main.tile[tilePosX, tilePosY].TileType]))
                                    {
                                        tilePosY--;
                                    }

                                    Vector2 spawn = new Vector2(tilePosX * 16 + 8, tilePosY * 16 + 8);
                                    if (Main.netMode != NetmodeID.MultiplayerClient)
                                    {
                                        Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, Vector2.Zero, ModContent.ProjectileType <GolemBoulder>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                                    }
                                }
                            }
                        }
                        else //empty jump
                        {
                            StompAttackCounter = 0;
                        }
                    }
                    else //outside temple
                    {
                        Vector2 spawnPos = new Vector2(npc.position.X, npc.Center.Y);
                        spawnPos.X -= npc.width * 7;
                        for (int i = 0; i < 6; i++)
                        {
                            int tilePosX = (int)spawnPos.X / 16 + npc.width * i * 3 / 16;
                            int tilePosY = (int)spawnPos.Y / 16;// + 1;

                            while (!(Main.tile[tilePosX, tilePosY].HasUnactuatedTile && Main.tileSolid[(int)Main.tile[tilePosX, tilePosY].TileType]))
                            {
                                tilePosY++;
                            }

                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                if (npc.HasPlayerTarget && Main.player[npc.target].position.Y > tilePosY * 16)
                                {
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8, 6.3f, 6.3f,
                                                             ProjectileID.FlamesTrap, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8, -6.3f, 6.3f,
                                                             ProjectileID.FlamesTrap, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                                }

                                Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8, 0f, -8f, ProjectileID.GeyserTrap, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);

                                Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8 - 640, 0f, -8f, ProjectileID.GeyserTrap, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                                Projectile.NewProjectile(npc.GetSource_FromThis(), tilePosX * 16 + 8, tilePosY * 16 + 8 - 640, 0f, 8f, ProjectileID.GeyserTrap, FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                            }
                        }
                        if (npc.HasPlayerTarget)
                        {
                            for (int i = -3; i <= 3; i++)
                            {
                                int tilePosX = (int)Main.player[npc.target].Center.X / 16;
                                int tilePosY = (int)Main.player[npc.target].Center.Y / 16;// + 1;
                                tilePosX += 10 * i;

                                for (int j = 0; j < 30; j++)
                                {
                                    if (Main.tile[tilePosX, tilePosY].HasUnactuatedTile && Main.tileSolid[Main.tile[tilePosX, tilePosY].TileType])
                                    {
                                        break;
                                    }
                                    tilePosY--;
                                }

                                Vector2 spawn = new Vector2(tilePosX * 16 + 8, tilePosY * 16 + 8);
                                if (Main.netMode != NetmodeID.MultiplayerClient)
                                {
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), spawn, Vector2.Zero, ModContent.ProjectileType <GolemBoulder>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                                }
                            }
                        }
                    }
                }
            }
            else if (npc.velocity.Y > 0)
            {
                DoStompBehaviour = true;
            }

            //spray spiky balls
            if (FargoSoulsWorld.MasochistModeReal && ++SpikyBallTimer >= 900)
            {
                if (Framing.GetTileSafely(npc.Center).WallType == WallID.LihzahrdBrickUnsafe)
                {
                    if (npc.velocity.Y > 0) //only when falling, implicitly assume at peak of a jump
                    {
                        SpikyBallTimer = FargoSoulsWorld.MasochistModeReal ? 600 : 0;
                        for (int i = 0; i < 8; 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(-0.3f, 0.3f), Main.rand.NextFloat(-10, -6), ModContent.ProjectileType <GolemSpikyBall>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                        }
                    }
                }
                else //outside temple
                {
                    SpikyBallTimer = 600; //do it more often
                    for (int i = 0; i < 16; 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.Next(-20, -9), ModContent.ProjectileType <GolemSpikyBall>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage), 0f, Main.myPlayer);
                    }
                }
            }

            //golem's anti-air fireball spray (when player is above)
            if (FargoSoulsWorld.MasochistModeReal && ++AntiAirTimer > 240 && npc.velocity.Y == 0)
            {
                AntiAirTimer = 0;
                if (npc.HasPlayerTarget && Main.player[npc.target].Center.Y < npc.Bottom.Y &&
                    Main.netMode != NetmodeID.MultiplayerClient)    //shoutouts to arterius
                {
                    bool inTemple = Framing.GetTileSafely(npc.Center).WallType == WallID.LihzahrdBrickUnsafe;

                    float gravity = -0.2f; //normally floats up
                    if (Main.player[npc.target].Center.Y > npc.Bottom.Y)
                    {
                        gravity *= -1f; //aim down if player below golem
                    }
                    const float time     = 60f;
                    Vector2     distance = Main.player[npc.target].Center - npc.Center;
                    distance  += Main.player[npc.target].velocity * 45f;
                    distance.X = distance.X / time;
                    distance.Y = distance.Y / time - 0.5f * gravity * time;

                    if (Math.Sign(distance.Y) != Math.Sign(gravity))
                    {
                        distance.Y = 0f; //cannot arc shots to hit someone on the same elevation
                    }
                    int max = inTemple ? 2 : 4;
                    for (int i = -max; i <= max; i++)
                    {
                        Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center.X, npc.Center.Y, distance.X + i, distance.Y,
                                                 ModContent.ProjectileType <GolemFireball>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 0.8f), 0f, Main.myPlayer, gravity, 0);
                    }
                }
            }

            EModeUtils.DropSummon(npc, "LihzahrdPowerCell2", NPC.downedGolemBoss, ref DroppedSummon, NPC.downedPlantBoss);

            return(result);
        }
Exemplo n.º 14
0
        public override void AI(NPC npc)
        {
            base.AI(npc);

            EModeGlobalNPC.wallBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return;
            }

            if (npc.ai[3] == 0f) //when spawned in, make one eye invul
            {
                for (int i = 0; i < Main.maxNPCs; i++)
                {
                    if (Main.npc[i].active && Main.npc[i].type == NPCID.WallofFleshEye && Main.npc[i].realLife == npc.whoAmI)
                    {
                        Main.npc[i].ai[2]     = -1f;
                        Main.npc[i].netUpdate = true;

                        npc.ai[3]     = 1f;
                        npc.netUpdate = true;
                        break;
                    }
                }
            }

            if (InPhase2) //phase 2
            {
                if (++WorldEvilAttackCycleTimer > 600)
                {
                    WorldEvilAttackCycleTimer = 0;
                    UseCorruptAttack          = !UseCorruptAttack;

                    npc.netUpdate = true;
                    NetSync(npc);
                }
                else if (WorldEvilAttackCycleTimer > 600 - 120)           //telegraph for special attacks
                {
                    int     type          = !UseCorruptAttack ? 75 : 170; //corruption dust, then crimson dust
                    int     speed         = !UseCorruptAttack ? 10 : 8;
                    float   scale         = !UseCorruptAttack ? 6f : 4f;
                    float   speedModifier = !UseCorruptAttack ? 12f : 5f;
                    Vector2 direction     = npc.DirectionTo(Main.player[npc.target].Center);
                    Vector2 vel           = speed * direction;
                    int     d             = Dust.NewDust(npc.Center + 32f * direction, 0, 0, type, vel.X, vel.Y, 100, Color.White, scale);
                    Main.dust[d].velocity *= speedModifier;
                    Main.dust[d].noGravity = true;
                }
                else if (WorldEvilAttackCycleTimer < 240) //special attacks
                {
                    if (UseCorruptAttack)                 //cursed inferno attack
                    {
                        if (WorldEvilAttackCycleTimer == 10 && Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            Projectile.NewProjectile(npc.Center, Vector2.UnitY, ModContent.ProjectileType <CursedDeathrayWOFS>(), 0, 0f, Main.myPlayer, npc.direction, npc.whoAmI);
                        }

                        if (WorldEvilAttackCycleTimer % 4 == 0)
                        {
                            float   xDistance = (2500f - 1800f * WorldEvilAttackCycleTimer / 240f) * Math.Sign(npc.velocity.X);
                            Vector2 spawnPos  = new Vector2(npc.Center.X + xDistance, npc.Center.Y);

                            Main.PlaySound(SoundID.Item34, spawnPos);

                            const int offsetY = 800;
                            const int speed   = 14;
                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                Projectile.NewProjectile(spawnPos + Vector2.UnitY * offsetY, Vector2.UnitY * -speed, ModContent.ProjectileType <CursedFlamethrower>(), npc.damage / 4, 0f, Main.myPlayer);
                                Projectile.NewProjectile(spawnPos + Vector2.UnitY * offsetY / 2, Vector2.UnitY * speed, ModContent.ProjectileType <CursedFlamethrower>(), npc.damage / 4, 0f, Main.myPlayer);
                                Projectile.NewProjectile(spawnPos + Vector2.UnitY * -offsetY / 2, Vector2.UnitY * -speed, ModContent.ProjectileType <CursedFlamethrower>(), npc.damage / 4, 0f, Main.myPlayer);
                                Projectile.NewProjectile(spawnPos + Vector2.UnitY * -offsetY, Vector2.UnitY * speed, ModContent.ProjectileType <CursedFlamethrower>(), npc.damage / 4, 0f, Main.myPlayer);
                            }
                        }
                    }
                    else //ichor attack
                    {
                        if (WorldEvilAttackCycleTimer % 8 == 0)
                        {
                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                for (int i = 0; i < 8; i++)
                                {
                                    Vector2 target = npc.Center;
                                    target.X += Math.Sign(npc.velocity.X) * 1000f * WorldEvilAttackCycleTimer / 240f; //gradually targets further and further
                                    target.X += Main.rand.NextFloat(-100, 100);
                                    target.Y += Main.rand.NextFloat(-450, 450);

                                    const float gravity  = 0.5f;
                                    float       time     = 60f;
                                    Vector2     distance = target - npc.Center;
                                    distance.X = distance.X / time;
                                    distance.Y = distance.Y / time - 0.5f * gravity * time;

                                    Projectile.NewProjectile(npc.Center + Vector2.UnitX * Math.Sign(npc.velocity.X) * 32f, distance,
                                                             ModContent.ProjectileType <GoldenShowerWOF>(), npc.damage / 4, 0f, Main.myPlayer, time);
                                }
                            }
                        }
                    }
                }
            }
            else if (npc.life < npc.lifeMax * (FargoSoulsWorld.MasochistModeReal ? 0.9 : .75)) //enter phase 2
            {
                InPhase2      = true;
                npc.netUpdate = true;
                NetSync(npc);

                if (!Main.dedServ)
                {
                    Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/Monster94"),
                                   npc.HasValidTarget && Main.player[npc.target].ZoneUnderworldHeight ? Main.player[npc.target].Center : npc.Center);

                    if (Main.LocalPlayer.active)
                    {
                        Main.LocalPlayer.GetModPlayer <FargoPlayer>().Screenshake = 90;
                    }
                }
            }

            if (npc.ai[3] == 2) //phase 3
            {
                if (InDesperationPhase)
                {
                    //ChainBarrageTimer -= 0.5f; //increment faster

                    if (WorldEvilAttackCycleTimer % 2 == 1) //always make sure its even in here
                    {
                        WorldEvilAttackCycleTimer--;
                    }
                }

                int floor   = 240 - (InDesperationPhase ? 120 : 0);
                int ceiling = 600 - 180 - (InDesperationPhase ? 120 : 0);

                if (WorldEvilAttackCycleTimer >= floor && WorldEvilAttackCycleTimer <= ceiling)
                {
                    if (--ChainBarrageTimer < 0)
                    {
                        ChainBarrageTimer = 80;
                        if (npc.HasValidTarget && Main.player[npc.target].ZoneUnderworldHeight)
                        {
                            if (Main.netMode != NetmodeID.MultiplayerClient) //spawn reticles for chain barrages
                            {
                                Vector2 spawnPos = Main.player[npc.target].Center;

                                float offset = 1000f * (ceiling - WorldEvilAttackCycleTimer) / (ceiling - floor); //progress further as attack continues
                                spawnPos.X += Math.Sign(npc.velocity.X) * offset;
                                spawnPos.Y += Main.rand.NextFloat(-100, 100);

                                if (spawnPos.Y / 16 < Main.maxTilesY - 200) //clamp so it stays in hell
                                {
                                    spawnPos.Y = (Main.maxTilesY - 200) * 16;
                                }
                                if (spawnPos.Y / 16 >= Main.maxTilesY)
                                {
                                    spawnPos.Y = Main.maxTilesY * 16 - 16;
                                }
                                Projectile.NewProjectile(spawnPos, Vector2.Zero, ModContent.ProjectileType <WOFReticle>(), npc.damage / 6, 0f, Main.myPlayer);
                            }
                        }
                    }
                }
                else
                {
                    ChainBarrageTimer = 0;
                }
            }
            else if (npc.ai[3] == 1 && npc.life < npc.lifeMax * (FargoSoulsWorld.MasochistModeReal ? .8 : .5)) //enter phase 3
            {
                npc.ai[3]     = 2;
                npc.netUpdate = true;
                NetSync(npc);

                if (!Main.dedServ)
                {
                    Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/Monster94"),
                                   npc.HasValidTarget && Main.player[npc.target].ZoneUnderworldHeight ? Main.player[npc.target].Center : npc.Center);

                    if (Main.LocalPlayer.active)
                    {
                        Main.LocalPlayer.GetModPlayer <FargoPlayer>().Screenshake = 90;
                    }
                }
            }

            if (npc.life < npc.lifeMax / (FargoSoulsWorld.MasochistModeReal ? 4 : 10)) //final phase
            {
                WorldEvilAttackCycleTimer++;

                if (!InDesperationPhase)
                {
                    InDesperationPhase = true;

                    //temporarily stop eyes from attacking during the transition to avoid accidental insta-lasers
                    for (int i = 0; i < Main.maxNPCs; i++)
                    {
                        if (Main.npc[i].active && Main.npc[i].type == NPCID.WallofFleshEye && Main.npc[i].realLife == npc.whoAmI)
                        {
                            Main.npc[i].GetEModeNPCMod <WallofFleshEye>().PreventAttacks = 60;
                        }
                    }

                    npc.netUpdate = true;
                    NetSync(npc);

                    if (!Main.dedServ)
                    {
                        Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/Monster5").WithVolume(1.5f),
                                       npc.HasValidTarget && Main.player[npc.target].ZoneUnderworldHeight ? Main.player[npc.target].Center : npc.Center);

                        if (Main.LocalPlayer.active)
                        {
                            Main.LocalPlayer.GetModPlayer <FargoPlayer>().Screenshake = 180;
                        }
                    }
                }
            }

            float maxSpeed = FargoSoulsWorld.MasochistModeReal ? 4.5f : 3.5f; //don't let wof move faster than this normally

            if (npc.HasPlayerTarget && (Main.player[npc.target].dead || Vector2.Distance(npc.Center, Main.player[npc.target].Center) > 3000))
            {
                npc.TargetClosest(true);
                if (Main.player[npc.target].dead || Vector2.Distance(npc.Center, Main.player[npc.target].Center) > 3000)
                {
                    npc.position.X += 60 * Math.Sign(npc.velocity.X); //move faster to despawn
                }
                else if (Math.Abs(npc.velocity.X) > maxSpeed)
                {
                    npc.position.X -= (Math.Abs(npc.velocity.X) - maxSpeed) * Math.Sign(npc.velocity.X);
                }
            }
            else if (Math.Abs(npc.velocity.X) > maxSpeed)
            {
                npc.position.X -= (Math.Abs(npc.velocity.X) - maxSpeed) * Math.Sign(npc.velocity.X);
            }

            if (Main.LocalPlayer.active & !Main.LocalPlayer.dead && !Main.LocalPlayer.ghost && Main.LocalPlayer.ZoneUnderworldHeight)
            {
                float velX = npc.velocity.X;
                if (velX > maxSpeed)
                {
                    velX = maxSpeed;
                }
                else if (velX < -maxSpeed)
                {
                    velX = -maxSpeed;
                }

                for (int i = 0; i < 10; i++) //dust
                {
                    Vector2 dustPos = new Vector2(2000 * npc.direction, 0f).RotatedBy(Math.PI / 3 * (-0.5 + Main.rand.NextDouble()));
                    int     d       = Dust.NewDust(npc.Center + dustPos, 0, 0, DustID.Fire);
                    Main.dust[d].scale     += 1f;
                    Main.dust[d].velocity.X = velX;
                    Main.dust[d].velocity.Y = npc.velocity.Y;
                    Main.dust[d].noGravity  = true;
                    Main.dust[d].noLight    = true;
                }

                if (++npc.localAI[1] > 15f)
                {
                    npc.localAI[1] = 0f; //tongue the player if they're 2000-2800 units away
                    if (Math.Abs(2400 - npc.Distance(Main.LocalPlayer.Center)) < 400)
                    {
                        if (!Main.LocalPlayer.tongued)
                        {
                            Main.PlaySound(SoundID.ForceRoar, Main.LocalPlayer.Center, -1); //eoc roar
                        }
                        Main.LocalPlayer.AddBuff(BuffID.TheTongue, 10);
                    }
                }
            }

            EModeUtils.DropSummon(npc, ModContent.ItemType <FleshyDoll>(), Main.hardMode, ref DroppedSummon);
        }
Exemplo n.º 15
0
        public override bool PreAI(NPC npc)
        {
            EModeGlobalNPC.eyeBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return(true);
            }

            void SpawnServants()
            {
                if (FargoSoulsWorld.MasochistModeReal && npc.life <= npc.lifeMax * 0.65 && NPC.CountNPCS(NPCID.ServantofCthulhu) < 9 && Main.netMode != NetmodeID.MultiplayerClient)
                {
                    Vector2 vel = new Vector2(3, 3);
                    for (int i = 0; i < 4; i++)
                    {
                        int n = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCID.ServantofCthulhu);
                        if (n != Main.maxNPCs)
                        {
                            Main.npc[n].velocity = vel.RotatedBy(Math.PI / 2 * i);
                            if (Main.netMode == NetmodeID.Server)
                            {
                                NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, n);
                            }
                        }
                    }
                }
            }

            npc.dontTakeDamage = npc.alpha > 50;
            if (npc.dontTakeDamage)
            {
                Lighting.AddLight(npc.Center, 0.75f, 1.35f, 1.5f);
            }

            if (ScytheSpawnTimer > 0)
            {
                if (ScytheSpawnTimer % (IsInFinalPhase ? 2 : 6) == 0 && Main.netMode != NetmodeID.MultiplayerClient)
                {
                    if (IsInFinalPhase)
                    {
                        int p = Projectile.NewProjectile(npc.Center, Vector2.Zero, ModContent.ProjectileType <BloodScythe>(), npc.damage / 4, 1f, Main.myPlayer);
                        if (p != Main.maxProjectiles)
                        {
                            Main.projectile[p].timeLeft = 75;
                        }
                    }
                    else
                    {
                        Projectile.NewProjectile(npc.Center, Vector2.Normalize(npc.velocity), ModContent.ProjectileType <BloodScythe>(), npc.damage / 4, 1f, Main.myPlayer);
                    }
                }
                ScytheSpawnTimer--;
            }

            if (npc.ai[0] == 0f && npc.ai[1] == 2f && npc.ai[2] == 0f)
            {
                ScytheSpawnTimer = 30;
            }

            if (npc.ai[1] == 3f && !IsInFinalPhase) //during dashes in phase 2
            {
                if (FargoSoulsWorld.MasochistModeReal)
                {
                    ScytheSpawnTimer = 30;
                }

                if (Main.netMode != NetmodeID.MultiplayerClient)
                {
                    FargoSoulsUtil.XWay(8, npc.Center, ModContent.ProjectileType <BloodScythe>(), 1.5f, npc.damage / 4, 0);
                }
            }

            if (npc.life < npc.lifeMax / 2)
            {
                if (IsInFinalPhase) //final phase
                {
                    const float speedModifier = 0.3f;

                    if (npc.HasValidTarget && !Main.dayTime)
                    {
                        if (npc.timeLeft < 300)
                        {
                            npc.timeLeft = 300;
                        }
                    }
                    else //despawn and retarget
                    {
                        npc.TargetClosest(false);
                        npc.velocity.X *= 0.98f;
                        npc.velocity.Y -= npc.velocity.Y > 0 ? 1f : 0.25f;

                        if (npc.timeLeft > 30)
                        {
                            npc.timeLeft = 30;
                        }

                        AITimer          = 90;
                        FinalPhaseDashCD = 0;
                        FinalPhaseBerserkDashesComplete = true;
                        FinalPhaseDashHorizSpeedSet     = false;
                        FinalPhaseAttackCounter         = 0;

                        npc.alpha = 0;

                        const float PI = (float)Math.PI;
                        if (npc.rotation > PI)
                        {
                            npc.rotation -= 2 * PI;
                        }
                        if (npc.rotation < -PI)
                        {
                            npc.rotation += 2 * PI;
                        }

                        float targetRotation = npc.DirectionTo(Main.player[npc.target].Center).ToRotation() - PI / 2;
                        if (targetRotation > PI)
                        {
                            targetRotation -= 2 * PI;
                        }
                        if (targetRotation < -PI)
                        {
                            targetRotation += 2 * PI;
                        }
                        npc.rotation = MathHelper.Lerp(npc.rotation, targetRotation, 0.07f);
                    }

                    if (++AITimer == 1) //teleport to random position
                    {
                        if (Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            npc.Center      = Main.player[npc.target].Center;
                            npc.position.X += Main.rand.NextBool() ? -600 : 600;
                            npc.position.Y += Main.rand.NextBool() ? -400 : 400;
                            npc.TargetClosest(false);
                            npc.netUpdate = true;
                            NetSync(npc);
                        }
                    }
                    else if (AITimer < 90) //fade in, moving into position
                    {
                        npc.alpha -= 4;
                        if (npc.alpha < 0)
                        {
                            npc.alpha = 0;
                            if (FargoSoulsWorld.MasochistModeReal && AITimer < 90)
                            {
                                AITimer = 90;
                            }
                        }

                        const float PI = (float)Math.PI;
                        if (npc.rotation > PI)
                        {
                            npc.rotation -= 2 * PI;
                        }
                        if (npc.rotation < -PI)
                        {
                            npc.rotation += 2 * PI;
                        }

                        float targetRotation = npc.DirectionTo(Main.player[npc.target].Center).ToRotation() - PI / 2;
                        if (targetRotation > PI)
                        {
                            targetRotation -= 2 * PI;
                        }
                        if (targetRotation < -PI)
                        {
                            targetRotation += 2 * PI;
                        }
                        npc.rotation = MathHelper.Lerp(npc.rotation, targetRotation, 0.07f);

                        for (int i = 0; i < 3; i++)
                        {
                            int d = Dust.NewDust(npc.position, npc.width, npc.height, 229, 0f, 0f, 0, default(Color), 1.5f);
                            Main.dust[d].noGravity = true;
                            Main.dust[d].noLight   = true;
                            Main.dust[d].velocity *= 4f;
                        }

                        Vector2 target = Main.player[npc.target].Center;
                        target.X += npc.Center.X < target.X ? -600 : 600;
                        target.Y += npc.Center.Y < target.Y ? -400 : 400;

                        if (npc.Center.X < target.X)
                        {
                            npc.velocity.X += speedModifier;
                            if (npc.velocity.X < 0)
                            {
                                npc.velocity.X += speedModifier * 2;
                            }
                        }
                        else
                        {
                            npc.velocity.X -= speedModifier;
                            if (npc.velocity.X > 0)
                            {
                                npc.velocity.X -= speedModifier * 2;
                            }
                        }
                        if (npc.Center.Y < target.Y)
                        {
                            npc.velocity.Y += speedModifier;
                            if (npc.velocity.Y < 0)
                            {
                                npc.velocity.Y += speedModifier * 2;
                            }
                        }
                        else
                        {
                            npc.velocity.Y -= speedModifier;
                            if (npc.velocity.Y > 0)
                            {
                                npc.velocity.Y -= speedModifier * 2;
                            }
                        }
                        if (Math.Abs(npc.velocity.X) > 24)
                        {
                            npc.velocity.X = 24 * Math.Sign(npc.velocity.X);
                        }
                        if (Math.Abs(npc.velocity.Y) > 24)
                        {
                            npc.velocity.Y = 24 * Math.Sign(npc.velocity.Y);
                        }
                    }
                    else if (!FinalPhaseBerserkDashesComplete) //berserk dashing phase
                    {
                        AITimer = 90;

                        const float xSpeed = 18f;
                        const float ySpeed = 40f;

                        if (++FinalPhaseDashCD == 1)
                        {
                            Main.PlaySound(SoundID.ForceRoar, Main.player[npc.target].Center, -1); //eoc roar

                            if (!FinalPhaseDashHorizSpeedSet)                                      //only set this on the first dash of each set
                            {
                                FinalPhaseDashHorizSpeedSet = true;
                                npc.velocity.X = npc.Center.X < Main.player[npc.target].Center.X ? xSpeed : -xSpeed;
                            }

                            npc.velocity.Y = npc.Center.Y < Main.player[npc.target].Center.Y ? ySpeed : -ySpeed; //alternate this every dash

                            ScytheSpawnTimer = 30;
                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                FargoSoulsUtil.XWay(8, npc.Center, ModContent.ProjectileType <BloodScythe>(), 1f, npc.damage / 4, 0);
                            }

                            npc.netUpdate = true;
                        }
                        else if (FinalPhaseDashCD > 20)
                        {
                            FinalPhaseDashCD = 0;
                        }

                        if (++FinalPhaseDashStageDuration > 600 * 3 / xSpeed + 5) //proceed
                        {
                            ScytheSpawnTimer                = 0;
                            FinalPhaseDashStageDuration     = 0;
                            FinalPhaseBerserkDashesComplete = true;
                            if (!FargoSoulsWorld.MasochistModeReal)
                            {
                                FinalPhaseAttackCounter++;
                            }
                            npc.velocity *= 0.75f;
                            npc.netUpdate = true;
                        }

                        const float PI = (float)Math.PI;
                        npc.rotation = npc.velocity.ToRotation() - PI / 2;
                        if (npc.rotation > PI)
                        {
                            npc.rotation -= 2 * PI;
                        }
                        if (npc.rotation < -PI)
                        {
                            npc.rotation += 2 * PI;
                        }
                    }
                    else
                    {
                        bool mustRest = FinalPhaseAttackCounter >= 5;

                        const int restingTime = 240;

                        float threshold = 180;
                        if (mustRest)
                        {
                            threshold += restingTime;
                        }

                        if (mustRest && AITimer < restingTime + 90)
                        {
                            if (AITimer == 91)
                            {
                                npc.velocity = npc.DirectionTo(Main.player[npc.target].Center) * npc.velocity.Length() * 0.75f;
                            }

                            npc.velocity.X *= 0.98f;
                            if (Math.Abs(npc.Center.X - Main.player[npc.target].Center.X) < 300)
                            {
                                npc.velocity.X *= 0.9f;
                            }

                            bool floatUp = Collision.SolidCollision(npc.position, npc.width, npc.height);
                            if (!floatUp && npc.Bottom.X > 0 && npc.Bottom.X < Main.maxTilesX * 16 && npc.Bottom.Y > 0 && npc.Bottom.Y < Main.maxTilesY * 16)
                            {
                                Tile tile = Framing.GetTileSafely(npc.Bottom);
                                if (tile != null && tile.nactive())
                                {
                                    floatUp = Main.tileSolid[tile.type];
                                }
                            }

                            if (floatUp)
                            {
                                npc.velocity.X *= 0.95f;

                                npc.velocity.Y -= speedModifier;
                                if (npc.velocity.Y > 0)
                                {
                                    npc.velocity.Y = 0;
                                }
                                if (Math.Abs(npc.velocity.Y) > 24)
                                {
                                    npc.velocity.Y = 24 * Math.Sign(npc.velocity.Y);
                                }
                            }
                            else
                            {
                                npc.velocity.Y += speedModifier;
                                if (npc.velocity.Y < 0)
                                {
                                    npc.velocity.Y += speedModifier * 2;
                                }
                                if (npc.velocity.Y > 15)
                                {
                                    npc.velocity.Y = 15;
                                }
                            }
                        }
                        else
                        {
                            npc.alpha += 4;
                            if (npc.alpha > 255)
                            {
                                npc.alpha = 255;
                            }

                            if (mustRest)
                            {
                                npc.velocity.Y -= speedModifier * 0.5f;
                                if (npc.velocity.Y > 0)
                                {
                                    npc.velocity.Y = 0;
                                }
                                if (Math.Abs(npc.velocity.Y) > 24)
                                {
                                    npc.velocity.Y = 24 * Math.Sign(npc.velocity.Y);
                                }
                            }
                            else
                            {
                                npc.velocity *= 0.98f;
                            }
                        }

                        const float PI             = (float)Math.PI;
                        float       targetRotation = MathHelper.WrapAngle(npc.DirectionTo(Main.player[npc.target].Center).ToRotation() - PI / 2);
                        npc.rotation = MathHelper.WrapAngle(MathHelper.Lerp(npc.rotation, targetRotation, 0.07f));

                        if (npc.alpha > 0)
                        {
                            for (int i = 0; i < 3; i++)
                            {
                                int d = Dust.NewDust(npc.position, npc.width, npc.height, 229, 0f, 0f, 0, default(Color), 1.5f);
                                Main.dust[d].noGravity = true;
                                Main.dust[d].noLight   = true;
                                Main.dust[d].velocity *= 4f;
                            }
                        }

                        if (AITimer > threshold) //reset
                        {
                            AITimer          = 0;
                            FinalPhaseDashCD = 0;
                            FinalPhaseBerserkDashesComplete = false;
                            FinalPhaseDashHorizSpeedSet     = false;
                            if (mustRest)
                            {
                                FinalPhaseAttackCounter = 0;
                            }
                            npc.velocity  = Vector2.Zero;
                            npc.netUpdate = true;
                        }
                    }

                    if (npc.netUpdate)
                    {
                        if (Main.netMode == NetmodeID.Server)
                        {
                            NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, npc.whoAmI);
                            NetSync(npc);
                        }
                        npc.netUpdate = false;
                    }
                    return(false);
                }
                else if (!IsInFinalPhase && npc.life <= npc.lifeMax * 0.1) //go into final phase
                {
                    npc.velocity *= 0.98f;
                    npc.alpha    += 4;
                    for (int i = 0; i < 3; i++)
                    {
                        int d = Dust.NewDust(npc.position, npc.width, npc.height, 229, 0f, 0f, 0, default(Color), 1.5f);
                        Main.dust[d].noGravity = true;
                        Main.dust[d].noLight   = true;
                        Main.dust[d].velocity *= 4f;
                    }
                    if (npc.alpha > 255)
                    {
                        npc.alpha      = 255;
                        IsInFinalPhase = true;

                        Main.PlaySound(SoundID.Roar, npc.HasValidTarget ? Main.player[npc.target].Center : npc.Center, 0);

                        if (Main.netMode != NetmodeID.MultiplayerClient)
                        {
                            Projectile.NewProjectile(npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type);
                        }
                    }
                    return(false);
                }
                else if (npc.ai[0] == 3 && (npc.ai[1] == 0 || npc.ai[1] == 5))
                {
                    if (npc.ai[2] < 2)
                    {
                        npc.ai[2]--;
                        npc.alpha += 4;
                        for (int i = 0; i < 3; i++)
                        {
                            int d = Dust.NewDust(npc.position, npc.width, npc.height, 229, 0f, 0f, 0, default(Color), 1.5f);
                            Main.dust[d].noGravity = true;
                            Main.dust[d].noLight   = true;
                            Main.dust[d].velocity *= 4f;
                        }
                        if (npc.alpha > 255)
                        {
                            npc.alpha = 255;
                            if (Main.netMode != NetmodeID.MultiplayerClient && npc.HasPlayerTarget)
                            {
                                npc.ai[2] = 60;
                                npc.ai[1] = 5f;

                                Vector2 distance = Main.player[npc.target].Center - npc.Center;
                                if (Math.Abs(distance.X) > 1200)
                                {
                                    distance.X = 1200 * Math.Sign(distance.X);
                                }
                                else if (Math.Abs(distance.X) < 600)
                                {
                                    distance.X = 600 * Math.Sign(distance.X);
                                }
                                if (distance.Y > 0) //always ensure eoc teleports above player
                                {
                                    distance.Y *= -1;
                                }
                                if (Math.Abs(distance.Y) > 450)
                                {
                                    distance.Y = 450 * Math.Sign(distance.Y);
                                }
                                if (Math.Abs(distance.Y) < 150)
                                {
                                    distance.Y = 150 * Math.Sign(distance.Y);
                                }
                                npc.Center = Main.player[npc.target].Center + distance;

                                npc.netUpdate = true;
                            }
                        }
                    }
                    else
                    {
                        npc.alpha -= 4;
                        if (npc.alpha < 0)
                        {
                            npc.alpha = 0;
                        }
                        else
                        {
                            npc.ai[2]--;
                            npc.position -= npc.velocity / 2;
                            for (int i = 0; i < 3; i++)
                            {
                                int d = Dust.NewDust(npc.position, npc.width, npc.height, 229, 0f, 0f, 0, default(Color), 1.5f);
                                Main.dust[d].noGravity = true;
                                Main.dust[d].noLight   = true;
                                Main.dust[d].velocity *= 4f;
                            }
                        }
                    }
                }

                /*if (++Timer > 600)
                 * {
                 *  Timer = 0;
                 *  if (npc.HasValidTarget)
                 *  {
                 *      Player player = Main.player[npc.target];
                 *      Main.PlaySound(SoundID.Item9, (int)player.position.X, (int)player.position.Y, 104, 1f, 0f);
                 *      if (Main.netMode != NetmodeID.MultiplayerClient)
                 *      {
                 *          Vector2 spawnPos = player.Center;
                 *          int direction;
                 *          if (player.velocity.X == 0f)
                 *              direction = player.direction;
                 *          else
                 *              direction = Math.Sign(player.velocity.X);
                 *          spawnPos.X += 600 * direction;
                 *          spawnPos.Y -= 600;
                 *          Vector2 speed = Vector2.UnitY;
                 *          for (int i = 0; i < 30; i++)
                 *          {
                 *              Projectile.NewProjectile(spawnPos, speed, ModContent.ProjectileType<BloodScythe>(), npc.damage / 4, 1f, Main.myPlayer);
                 *              spawnPos.X += 72 * direction;
                 *              speed.Y += 0.15f;
                 *          }
                 *      }
                 *  }
                 * }*/
            }
            else
            {
                npc.alpha          = 0;
                npc.dontTakeDamage = false;
            }

            // Drop summon
            EModeUtils.DropSummon(npc, ModContent.ItemType <SuspiciousEye>(), NPC.downedBoss1, ref DroppedSummon);

            return(true);
        }
Exemplo n.º 16
0
        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);
        }
Exemplo n.º 17
0
        public override void AI(NPC npc)
        {
            base.AI(npc);

            EModeGlobalNPC.skeleBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return;
            }

            if (npc.ai[1] == 0f)
            {
                if (npc.ai[2] == 800 - 90) //telegraph spin
                {
                    if (Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(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 (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(spawnPos, vel, ModContent.ProjectileType <Projectiles.Champions.ShadowGuardian>(),
                                                                     npc.damage / 4, 0f, Main.myPlayer);
                                    if (p != Main.maxProjectiles)
                                    {
                                        Main.projectile[p].timeLeft = 1200 / 8 + 1;
                                    }
                                }
                            }
                        }
                    }
                }

                npc.localAI[2]++;
                float ratio     = (float)npc.life / npc.lifeMax;
                float threshold = 20f + 100f * ratio;
                if (npc.localAI[2] >= threshold) //spray bones
                {
                    npc.localAI[2] = 0f;
                    if (threshold > 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.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;

                    Main.PlaySound(SoundID.ForceRoar, npc.Center, -1);

                    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)
                        {
                            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.Center, velocity, ModContent.ProjectileType <SkeletronGuardian>(), npc.damage / 5, 0f, Main.myPlayer, 0f, ai1);
                        }
                    }
                }
            }
            else
            {
                //prevent skeletron from firing his stupid tick 1 no telegraph skull right after finishing spin
                if (npc.ai[2] == 0 && !FargoSoulsWorld.MasochistModeReal)
                {
                    npc.ai[2] = 1;
                }

                if (npc.life < npc.lifeMax * .75 && --BabyGuardianTimer < 0)
                {
                    BabyGuardianTimer = FargoSoulsWorld.MasochistModeReal ? 180 : 240;

                    Main.PlaySound(SoundID.ForceRoar, npc.Center, -1);

                    if (Main.netMode != NetmodeID.MultiplayerClient) //area denial circle spray of baby guardians
                    {
                        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)
                            {
                                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.Center, velModifier * baseVel.RotatedBy(MathHelper.ToRadians(10) * j * k),
                                                             ModContent.ProjectileType <SkeletronGuardian2>(), npc.damage / 5, 0f, Main.myPlayer);
                                }
                            }
                        }

                        if (Main.netMode != NetmodeID.MultiplayerClient) //one more shot straight behind skeletron
                        {
                            float velModifier = 10f;
                            Projectile.NewProjectile(npc.Center, velModifier * npc.DirectionFrom(Main.player[npc.target].Center),
                                                     ModContent.ProjectileType <SkeletronGuardian2>(), npc.damage / 5, 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, ModContent.ItemType <SuspiciousSkull>(), NPC.downedBoss3, ref DroppedSummon);

            //FargoSoulsUtil.PrintAI(npc);
        }
Exemplo n.º 18
0
        public override bool PreAI(NPC npc)
        {
            bool result = base.PreAI(npc);

            EModeGlobalNPC.deerBoss = npc.whoAmI;

            if (FargoSoulsWorld.SwarmActive)
            {
                return(result);
            }

            const int MaxBerserkTime = 600;

            BerserkSpeedupTimer -= 1;

            if (npc.localAI[3] > 0 || EnteredPhase3)
            {
                npc.localAI[2]++; //cry about it
            }
            const int TeleportThreshold = 780;

            if (npc.ai[0] != 0)
            {
                npc.alpha -= 10;
                if (npc.alpha < 0)
                {
                    npc.alpha = 0;
                }

                if (EnteredPhase3)
                {
                    npc.localAI[2]++;
                }
            }

            TeleportTimer++;
            if (EnteredPhase3)
            {
                TeleportTimer++;
            }

            if (Main.LocalPlayer.active && !Main.LocalPlayer.ghost && !Main.LocalPlayer.dead && npc.Distance(Main.LocalPlayer.Center) < 1200)
            {
                Main.LocalPlayer.AddBuff(ModContent.BuffType <LowGround>(), 2);
            }

            switch ((int)npc.ai[0])
            {
            case 0:     //walking at player
                if (TeleportTimer < TeleportThreshold)
                {
                    if (EnteredPhase3)
                    {
                        npc.position.X += npc.velocity.X;
                    }

                    if (npc.velocity.Y == 0)
                    {
                        if (EnteredPhase2)
                        {
                            npc.position.X += npc.velocity.X;
                        }
                        if (BerserkSpeedupTimer > 0)
                        {
                            npc.position.X += npc.velocity.X * 4f * BerserkSpeedupTimer / MaxBerserkTime;
                        }
                    }
                }

                if (EnteredPhase2)
                {
                    if (!EnteredPhase3 && npc.life < npc.lifeMax * .33)
                    {
                        npc.ai[0]     = 3;
                        npc.ai[1]     = 0;
                        npc.netUpdate = true;
                        break;
                    }

                    if (TeleportTimer > TeleportThreshold)
                    {
                        npc.velocity.X    *= 0.9f;
                        npc.dontTakeDamage = true;
                        npc.localAI[1]     = 0; //reset walls attack counter

                        if (EnteredPhase2 && Main.LocalPlayer.active && !Main.LocalPlayer.ghost && !Main.LocalPlayer.dead)
                        {
                            FargoSoulsUtil.AddDebuffFixedDuration(Main.LocalPlayer, BuffID.Darkness, 2);
                            FargoSoulsUtil.AddDebuffFixedDuration(Main.LocalPlayer, BuffID.Blackout, 2);
                        }

                        if (npc.alpha == 0)
                        {
                            SoundEngine.PlaySound(SoundID.Roar, npc.Center);

                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                const int max = 12;
                                for (int i = 0; i < 12; i++)
                                {
                                    Vector2 spawnPos = Main.player[npc.target].Center + 16 * Main.rand.NextFloat(6, 36) * Vector2.UnitX.RotatedBy(MathHelper.TwoPi / max * (i + Main.rand.NextFloat()));
                                    Projectile.NewProjectile(npc.GetSource_FromThis(), spawnPos, Vector2.Zero, ModContent.ProjectileType <DeerclopsHand>(), 0, 0f, Main.myPlayer, npc.target);
                                }
                            }
                        }

                        npc.alpha += 5;
                        if (npc.alpha > 255)
                        {
                            npc.alpha = 255;

                            npc.localAI[3] = 30;

                            if (npc.HasPlayerTarget)     //teleport
                            {
                                float distance = 16 * 14 * Math.Sign(npc.Center.X - Main.player[npc.target].Center.X);
                                distance *= -1f;                             //alternate back and forth

                                if (TeleportTimer == TeleportThreshold + 10) //introduce randomness
                                {
                                    if (Main.rand.NextBool())
                                    {
                                        distance *= -1f;
                                    }

                                    if (Main.netMode == NetmodeID.Server)
                                    {
                                        NetMessage.SendData(MessageID.SyncNPC, number: npc.whoAmI);
                                    }

                                    DoLaserAttack = !DoLaserAttack;     //guarantee he alternates wall attacks at some point in the fight
                                    NetSync(npc);
                                }

                                npc.Bottom = Main.player[npc.target].Bottom + distance * Vector2.UnitX;

                                npc.direction  = Math.Sign(Main.player[npc.target].Center.X - npc.Center.X);
                                npc.velocity.X = 3.4f * npc.direction;
                                npc.velocity.Y = 0;

                                int addedThreshold = 180;
                                if (EnteredPhase3)
                                {
                                    addedThreshold -= 30;
                                }
                                if (FargoSoulsWorld.MasochistModeReal)
                                {
                                    addedThreshold -= 30;
                                }

                                if (TeleportTimer > TeleportThreshold + addedThreshold)
                                {
                                    TeleportTimer  = 0;
                                    npc.velocity.X = 0;
                                    npc.ai[0]      = 4;
                                    npc.ai[1]      = 0;
                                    NetSync(npc);
                                    if (Main.netMode == NetmodeID.Server)
                                    {
                                        NetMessage.SendData(MessageID.SyncNPC, number: npc.whoAmI);
                                    }
                                }
                            }
                        }
                        else
                        {
                            TeleportTimer = TeleportThreshold;

                            if (npc.localAI[3] > 0)
                            {
                                npc.localAI[3] -= 3;     //remove visual effect
                            }
                        }

                        return(false);
                    }
                }
                else if (npc.life < npc.lifeMax * .66)
                {
                    npc.ai[0]     = 3;
                    npc.ai[1]     = 0;
                    npc.netUpdate = true;
                }
                break;

            case 1:     //ice wave, npc.localai[1] counts them, attacks at ai1=30, last spike 52, ends at ai1=80
                if (npc.ai[1] < 30)
                {
                    if (FargoSoulsWorld.MasochistModeReal)
                    {
                        npc.ai[1]        += 0.5f;
                        npc.frameCounter += 0.5;
                    }
                }
                break;

            case 2:     //debris attack
                break;

            case 3:     //roar at 30, ends at ai1=60
                if (!FargoSoulsWorld.MasochistModeReal && npc.ai[1] < 30)
                {
                    npc.ai[1]        -= 0.5f;
                    npc.frameCounter -= 0.5;
                }

                if (EnteredPhase2)
                {
                    npc.localAI[1] = 0;     //ensure this is always the same
                    npc.localAI[3] = 30;    //go invul

                    if (npc.ai[1] > 30)
                    {
                        Main.dayTime = false;
                        Main.time    = 16200;  //midnight, to help teleport visual
                    }
                }
                else if (npc.life < npc.lifeMax * .66)
                {
                    EnteredPhase2 = true;
                    NetSync(npc);
                }

                if (EnteredPhase3)
                {
                    if (!Main.dedServ)
                    {
                        Main.LocalPlayer.GetModPlayer <FargoSoulsPlayer>().Screenshake = 2;
                    }

                    if (npc.ai[1] > 30)         //roaring
                    {
                        if (npc.HasValidTarget) //fly over player
                        {
                            npc.position = Vector2.Lerp(npc.position, Main.player[npc.target].Center - 450 * Vector2.UnitY, 0.2f);
                        }
                    }
                }
                else if (npc.life < npc.lifeMax * .33)
                {
                    EnteredPhase3 = true;
                    NetSync(npc);
                }

                if (EnteredPhase3 || FargoSoulsWorld.MasochistModeReal)
                {
                    BerserkSpeedupTimer = MaxBerserkTime;
                }
                break;

            case 4:                 //both sides ice wave, attacks at ai1=50, last spike 70, ends at ai1=90
            {
                int cooldown = 100; //stops deerclops from teleporting while old ice walls are still there
                if (EnteredPhase3)
                {
                    cooldown *= 2;
                }
                if (TeleportTimer > TeleportThreshold - cooldown)
                {
                    TeleportTimer = TeleportThreshold - cooldown;
                }

                if (EnteredPhase2 && npc.ai[1] == 0)
                {
                    if (npc.alpha == 0)         //i.e. dont randomize when coming out of tp
                    {
                        DoLaserAttack = Main.rand.NextBool();
                    }
                    NetSync(npc);

                    if (DoLaserAttack && Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        Projectile.NewProjectile(npc.GetSource_FromThis(), npc.Center, Vector2.Zero, ModContent.ProjectileType <GlowRing>(), 0, 0f, Main.myPlayer, npc.whoAmI, npc.type);
                    }
                }

                Vector2 eye = npc.Center + new Vector2(64 * npc.direction, -24f) * npc.scale;

                if (FargoSoulsWorld.MasochistModeReal)
                {
                    const int desiredStartup = 30;         //effectively changes startup from 50 to this value
                    const int threshold      = 50 - desiredStartup / 2;
                    if (npc.ai[1] < threshold)
                    {
                        npc.ai[1]++;
                    }
                }

                if (DoLaserAttack && npc.ai[1] >= 70)
                {
                    if (EnteredPhase3)
                    {
                        const float baseIncrement = 0.33f;
                        float       increment     = baseIncrement;
                        //if (FargoSoulsWorld.MasochistModeReal) increment *= 2;

                        if (npc.ai[1] == 70)         //shoot laser
                        {
                            float time = (90 - 70) / baseIncrement - 5;
                            time *= 5;         //account for the ray having extra updates
                            float rotation = MathHelper.Pi * (FargoSoulsWorld.MasochistModeReal ? 1f : 0.8f) / time * -npc.direction;

                            if (Main.netMode != NetmodeID.MultiplayerClient)
                            {
                                Projectile.NewProjectile(npc.GetSource_FromThis(), eye, Vector2.UnitY, ModContent.ProjectileType <DeerclopsDeathray>(), FargoSoulsUtil.ScaledProjectileDamage(npc.damage, 2f), 0f, Main.myPlayer, rotation, time);
                            }
                        }

                        npc.ai[1] += increment;         //more endlag than normal

                        if (npc.ai[1] < 90)
                        {
                            return(false);        //stop deerclops from turning around
                        }
                    }
                    else
                    {
                        npc.ai[1] += 0.33f;         //more endlag than normal

                        if (npc.ai[1] >= 89)
                        {
                            npc.ai[0]        = 2;  //force debris attack instead
                            npc.ai[1]        = 0;
                            npc.frameCounter = 0;
                            npc.netUpdate    = true;
                            break;
                        }
                    }

                    if (npc.ai[1] < 90)
                    {
                        return(false);        //stop deerclops from turning around
                    }
                }
            }
            break;

            case 6:     //trying to return home
                npc.TargetClosest();

                if (npc.ai[1] > 120 && (!npc.HasValidTarget || npc.Distance(Main.player[npc.target].Center) > 1600))
                {
                    if (Main.netMode != NetmodeID.MultiplayerClient)     //force despawn
                    {
                        npc.ai[0]      = 8f;
                        npc.ai[1]      = 0.0f;
                        npc.localAI[1] = 0.0f;
                        npc.netUpdate  = true;
                    }
                }
                break;

            default:
                break;
            }

            if (EnteredPhase3 && !(npc.ai[0] == 0 && npc.alpha > 0))
            {
                npc.localAI[3] += 3;
                if (npc.localAI[3] > 30)
                {
                    npc.localAI[3] = 30;
                }
            }

            //FargoSoulsUtil.PrintAI(npc);

            EModeUtils.DropSummon(npc, "DeerThing2", NPC.downedDeerclops, ref DroppedSummon);

            return(result);
        }