예제 #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));
        }
예제 #2
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);
        }