Exemplo n.º 1
0
        public override void ModifyHitByAnything(NPC npc, Player player, ref int damage, ref float knockback, ref bool crit)
        {
            base.ModifyHitByAnything(npc, player, ref damage, ref knockback, ref crit);

            if (Main.rand.NextBool(10) && npc.HasPlayerTarget && player.whoAmI == npc.target && player.active && !player.dead && !player.ghost)
            {
                bool doTheTeleport = true;

                Vector2 teleportTarget = player.Center;
                float   offset         = 100f * -player.direction;
                teleportTarget.X += offset;
                teleportTarget.Y -= 50f;
                if (!Collision.CanHit(teleportTarget, 1, 1, player.position, player.width, player.height))
                {
                    teleportTarget.X -= offset * 2f;
                    if (!Collision.CanHit(teleportTarget, 1, 1, player.position, player.width, player.height))
                    {
                        doTheTeleport = false;
                    }
                }

                if (doTheTeleport)
                {
                    FargoSoulsUtil.GrossVanillaDodgeDust(npc);
                    damage        = 0;
                    npc.Center    = teleportTarget;
                    npc.netUpdate = true;
                    FargoSoulsUtil.GrossVanillaDodgeDust(npc);
                }
            }
        }
        public override void HitEffect(int hitDirection, double damage)
        {
            if (NPC.life <= 0)
            {
                for (int i = 3; i <= 10; i++)
                {
                    Vector2 pos = NPC.position + new Vector2(Main.rand.NextFloat(NPC.width), Main.rand.NextFloat(NPC.height));
                    if (!Main.dedServ)
                    {
                        Gore.NewGore(NPC.GetSource_FromThis(), pos, NPC.velocity, ModContent.Find <ModGore>(Mod.Name, $"TimberGore{i}").Type, NPC.scale);
                    }
                }

                if (spawnPhase2)
                {
                    FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromAI(), NPC.Center, ModContent.NPCType <TimberChampionHead>(), NPC.whoAmI, target: NPC.target);
                }

                FargoSoulsUtil.GrossVanillaDodgeDust(NPC);

                for (int i = 0; i < 6; i++)
                {
                    ExplodeDust(NPC.position + new Vector2(Main.rand.Next(NPC.width), Main.rand.Next(NPC.height)));
                }
            }
        }
        public override void AI()
        {
            if (!spawned)
            {
                spawned = true;

                NPC.TargetClosest(false);

                if (Main.netMode != NetmodeID.MultiplayerClient)
                {
                    head = FargoSoulsUtil.NPCExists(FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromThis(), NPC.Center, ModContent.NPCType <TrojanSquirrelHead>(), NPC.whoAmI, target: NPC.target));
                    arms = FargoSoulsUtil.NPCExists(FargoSoulsUtil.NewNPCEasy(NPC.GetSource_FromThis(), NPC.Center, ModContent.NPCType <TrojanSquirrelArms>(), NPC.whoAmI, target: NPC.target));
                }

                //drop summon
                if (FargoSoulsWorld.EternityMode && !FargoSoulsWorld.downedBoss[(int)FargoSoulsWorld.Downed.TrojanSquirrel] && Main.netMode != NetmodeID.MultiplayerClient)
                {
                    Item.NewItem(NPC.GetSource_Loot(), Main.player[NPC.target].Hitbox, ModContent.ItemType <SquirrelCoatofArms>());
                }

                //start by jumping
                NPC.ai[0] = 1f;
                NPC.ai[3] = 1f;

                for (int i = 0; i < 80; i++)
                {
                    int d = Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 4f);
                    Main.dust[d].velocity.Y -= 1.5f;
                    Main.dust[d].velocity   *= 1.5f;
                    Main.dust[d].noGravity   = true;
                }

                FargoSoulsUtil.GrossVanillaDodgeDust(NPC);

                SoundEngine.PlaySound(SoundID.Roar, Main.player[NPC.target].Center);
            }

            Player player = Main.player[NPC.target];

            NPC.direction = NPC.spriteDirection = NPC.Center.X < player.Center.X ? 1 : -1;

            bool despawn = false;

            switch ((int)NPC.ai[0])
            {
            case 0:     //mourning wood movement
            {
                Vector2 target = player.Bottom - Vector2.UnitY;
                if (NPC.localAI[0] > 0)         //doing running attack
                {
                    NPC.localAI[0] -= 1f;

                    float distance     = NPC.Center.X - target.X;
                    bool  passedTarget = Math.Sign(distance) == NPC.localAI[1];
                    if (passedTarget && Math.Abs(distance) > 160)
                    {
                        NPC.localAI[0] = 0f;
                    }

                    target = new Vector2(NPC.Center.X + 256f * NPC.localAI[1], target.Y);

                    if (NPC.localAI[0] == 0f)
                    {
                        NPC.TargetClosest(false);
                    }

                    if (FargoSoulsWorld.EternityMode && head == null && NPC.localAI[0] % 3 == 0 && Main.netMode != NetmodeID.MultiplayerClient)
                    {
                        int p = Projectile.NewProjectile(NPC.GetSource_FromThis(), NPC.Top.X, NPC.Top.Y, Main.rand.NextFloat(-5, 5), Main.rand.NextFloat(-5),
                                                         Main.rand.Next(326, 329), FargoSoulsUtil.ScaledProjectileDamage(NPC.damage), 0f, Main.myPlayer);
                        if (p != Main.maxProjectiles)
                        {
                            Main.projectile[p].timeLeft = 90;
                        }
                    }
                }
                else if (!NPC.HasValidTarget || NPC.Distance(player.Center) > (FargoSoulsWorld.EternityMode ? 1600 : 2400))
                {
                    target = NPC.Center + new Vector2(256f * Math.Sign(NPC.Center.X - player.Center.X), -128);

                    NPC.TargetClosest(false);

                    despawn = true;
                }

                if (Math.Abs(NPC.velocity.Y) < 0.05f && NPC.localAI[3] >= 2)
                {
                    if (NPC.localAI[3] == 2)
                    {
                        NPC.localAI[3] = 0f;
                    }
                    else
                    {
                        NPC.localAI[3] -= 1;
                        NPC.ai[0]       = 1f;
                        NPC.ai[3]       = 1f;
                    }

                    SoundEngine.PlaySound(SoundID.Item14, NPC.Center);

                    ExplodeAttack();
                }

                bool goFast = despawn || NPC.localAI[0] > 0;
                Movement(target, goFast);

                if (arms != null && (NPC.localAI[3] == -1 || NPC.localAI[3] == 1))         //from arms
                {
                    NPC.direction = NPC.spriteDirection = (int)NPC.localAI[3];
                }

                bool canDoAttacks = FargoSoulsWorld.EternityMode && !goFast;
                if (canDoAttacks)         //decide next action
                {
                    float increment = 1f;
                    if (head == null)
                    {
                        increment += 0.5f;
                    }
                    if (arms == null)
                    {
                        increment += 0.5f;
                    }
                    if (FargoSoulsWorld.MasochistModeReal)
                    {
                        increment += 1f;
                    }
                    if (NPC.dontTakeDamage)
                    {
                        increment /= 2;
                    }

                    if (target.Y > NPC.Top.Y)
                    {
                        NPC.ai[1] += increment;
                    }
                    else
                    {
                        NPC.ai[2] += increment;
                    }

                    if (Math.Abs(NPC.velocity.Y) < 0.05f)
                    {
                        //its structured like this to ensure body picks the right attack for the situation after being delayed by head/arms
                        bool canProceed = !(head != null && head.ai[0] != 0) && !(arms != null && arms.ai[0] != 0);

                        int threshold = 300;
                        if (NPC.ai[1] > threshold)
                        {
                            if (canProceed)
                            {
                                NPC.ai[0] = 1f;
                                NPC.ai[1] = 0f;
                                //NPC.ai[2] = 0f;
                                NPC.ai[3]      = 0f;
                                NPC.localAI[0] = 0f;
                                NPC.netUpdate  = true;
                            }
                            else
                            {
                                NPC.ai[1] -= 10f;
                            }
                        }

                        if (NPC.ai[2] > threshold)
                        {
                            if (canProceed)
                            {
                                NPC.ai[0] = 1f;
                                //NPC.ai[1] = 0f;
                                NPC.ai[2]      = 0f;
                                NPC.ai[3]      = 1f;
                                NPC.localAI[0] = 0f;
                                NPC.netUpdate  = true;
                            }
                            else
                            {
                                NPC.ai[2] -= 10f;
                            }
                        }
                    }
                }
            }
            break;

            case 1:     //telegraph something
            {
                NPC.velocity.X *= 0.9f;

                TileCollision(player.Bottom.Y - 1 > NPC.Bottom.Y, Math.Abs(player.Center.X - NPC.Center.X) < NPC.width / 2 && NPC.Bottom.Y < player.Bottom.Y - 1);

                int threshold = 120;
                if (FargoSoulsWorld.EternityMode)
                {
                    if (head == null)
                    {
                        threshold -= 20;
                    }
                    if (arms == null)
                    {
                        threshold -= 20;
                    }
                    if (head == null && arms == null)
                    {
                        threshold -= 30;
                    }
                    if (NPC.localAI[3] >= 2)
                    {
                        threshold -= 20;
                    }
                }
                if (FargoSoulsWorld.MasochistModeReal)
                {
                    threshold -= 20;
                }

                if (++NPC.localAI[0] > threshold)
                {
                    NPC.localAI[0] = 0f;
                    NPC.netUpdate  = true;

                    if (NPC.ai[3] == 0f)
                    {
                        NPC.ai[0] = 0f;

                        NPC.localAI[0] = 300f;
                        NPC.localAI[1] = Math.Sign(player.Center.X - NPC.Center.X);
                        NPC.localAI[2] = player.Center.X;
                    }
                    else
                    {
                        NPC.ai[0] = 2f;
                    }
                }
            }
            break;

            case 2:     //jump
            {
                const float gravity = 0.4f;
                float       time    = FargoSoulsWorld.EternityMode && arms == null ? 60f : 90f;

                if (NPC.localAI[0]++ == 0)
                {
                    Vector2 distance = player.Top - NPC.Bottom;

                    if (FargoSoulsWorld.EternityMode && arms == null)
                    {
                        distance.X += NPC.width * Math.Sign(player.Center.X - NPC.Center.X);

                        if (NPC.localAI[3] < 2)
                        {
                            NPC.localAI[3] = 2;         //flag to stomp again on landing
                            if (head == null)
                            {
                                NPC.localAI[3] += 2;         //flag to do more stomps
                            }
                        }

                        ExplodeAttack();
                    }

                    distance.X   = distance.X / time;
                    distance.Y   = distance.Y / time - 0.5f * gravity * time;
                    NPC.velocity = distance;

                    NPC.netUpdate = true;

                    SoundEngine.PlaySound(SoundID.Item14, NPC.Center);
                }
                else
                {
                    NPC.velocity.Y += gravity;
                }

                if (NPC.localAI[0] > time)
                {
                    NPC.TargetClosest(false);

                    NPC.velocity.X = Utils.Clamp(NPC.velocity.X, -20, 20);
                    NPC.velocity.Y = Utils.Clamp(NPC.velocity.Y, -10, 10);

                    NPC.ai[0]      = 0f;
                    NPC.localAI[0] = 0f;
                    NPC.netUpdate  = true;
                }
            }
            break;

            default:
                NPC.ai[0] = 0;
                goto case 0;
            }

            if (despawn)
            {
                if (NPC.timeLeft > 60)
                {
                    NPC.timeLeft = 60;
                }
            }
            else
            {
                if (NPC.timeLeft < 600)
                {
                    NPC.timeLeft = 600;
                }
            }

            if (head == null)
            {
                Vector2 pos = NPC.Top;
                pos.X += 2f * 16f * NPC.direction;
                pos.Y -= 8f;

                int width  = 4 * 16;
                int height = 2 * 16;

                pos.X -= width / 2f;
                pos.Y -= height / 2f;

                for (int i = 0; i < 3; i++)
                {
                    int d = Dust.NewDust(pos, width, height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 2.5f);
                    Main.dust[d].velocity.Y -= 1.5f;
                    Main.dust[d].velocity   *= 1.5f;
                    Main.dust[d].noGravity   = true;
                }

                if (Main.rand.NextBool(3))
                {
                    int d = Dust.NewDust(pos, width, height, DustID.Torch, NPC.velocity.X * 0.4f, NPC.velocity.Y * 0.4f, 100, default(Color), 2.5f);
                    Main.dust[d].noGravity   = true;
                    Main.dust[d].velocity.Y -= 3f;
                    Main.dust[d].velocity   *= 1.5f;
                }
            }
            else
            {
                lifeMaxHead = head.lifeMax;
                head        = FargoSoulsUtil.NPCExists(head.whoAmI, ModContent.NPCType <TrojanSquirrelHead>());
            }

            if (arms == null)
            {
                Vector2 pos = NPC.Center;
                pos.X -= 16f * NPC.direction;
                pos.Y -= 3f * 16f;

                int width  = 2 * 16;
                int height = 2 * 16;

                pos.X -= width / 2f;
                pos.Y -= height / 2f;

                for (int i = 0; i < 2; i++)
                {
                    int d = Dust.NewDust(pos, width, height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 1.5f);
                    Main.dust[d].noGravity = true;
                }

                if (Main.rand.NextBool())
                {
                    int d2 = Dust.NewDust(pos, width, height, DustID.Torch, NPC.velocity.X * 0.4f, NPC.velocity.Y * 0.4f, 100, default(Color), 3f);
                    Main.dust[d2].noGravity = true;
                }
            }
            else
            {
                lifeMaxArms = arms.lifeMax;
                arms        = FargoSoulsUtil.NPCExists(arms.whoAmI, ModContent.NPCType <TrojanSquirrelArms>());
            }

            if (NPC.life < NPC.lifeMax / 2 && Main.rand.NextBool(3))
            {
                int d = Dust.NewDust(NPC.position, NPC.width, NPC.height, DustID.Smoke, NPC.velocity.X, NPC.velocity.Y, 50, default(Color), 4f);
                Main.dust[d].velocity.Y -= 1.5f;
                Main.dust[d].velocity   *= 1.5f;
                Main.dust[d].noGravity   = true;
            }

            if (FargoSoulsWorld.EternityMode)
            {
                bool wasImmune = NPC.dontTakeDamage;
                NPC.dontTakeDamage = NPC.life < NPC.lifeMax / 2 && (head != null || arms != null);

                if (wasImmune != NPC.dontTakeDamage)
                {
                    for (int i = 0; i < 6; i++)
                    {
                        ExplodeDust(NPC.position + new Vector2(Main.rand.Next(NPC.width), Main.rand.Next(NPC.height)));
                    }
                }
            }
            else
            {
                NPC.dontTakeDamage = false;
            }
        }