示例#1
0
        private static int SpawnCustomNPC(int x, int y, CustomNPCDefinition definition)
        {
            //DEBUG
            TShock.Log.ConsoleInfo("DEBUG Spawning Custom NPC at {0}, {1} with customID {2}", x, y, definition.customID);
            //DEBUG

            int npcid = NPC.NewNPC(x, y, definition.customBase.type);

            if (npcid == 200)
            {
                //DEBUG
                TShock.Log.ConsoleInfo("DEBUG Spawning FAILED (mobcap) at {0}, {1} for customID {2}", x, y, definition.customID);
                //DEBUG
                return(-1);
            }

            Data.ConvertNPCToCustom(npcid, definition);
            DateTime[] dt = null;
            if (definition.customProjectiles != null)
            {
                dt = Enumerable.Repeat(DateTime.Now, definition.customProjectiles.Count).ToArray();
            }
            NPCs[npcid] = new CustomNPCVars(definition, dt, Main.npc[npcid]);

            TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", npcid);
            return(npcid);
        }
示例#2
0
        /// <summary>
        /// For Custom Loot
        /// </summary>
        /// <param name="args"></param>
        private void OnLootDrop(NpcLootDropEventArgs args)
        {
            CustomNPCVars npcvar = NPCManager.GetCustomNPCByIndex(args.NpcArrayIndex);

            if (npcvar == null || npcvar.droppedLoot)
            {
                return;
            }

            args.Handled = npcvar.customNPC.overrideBaseNPCLoot;

            //Check if monster has been customized
            if (npcvar.customNPC.customNPCLoots != null)
            {
                foreach (CustomNPCLoot obj in npcvar.customNPC.customNPCLoots)
                {
                    if (obj.itemDropChance >= 100 || NPCManager.Chance(obj.itemDropChance))
                    {
                        int pre = 0;
                        if (obj.itemPrefix != null)
                        {
                            pre = obj.itemPrefix[rand.Next(obj.itemPrefix.Count)];
                        }

                        Item.NewItem((int)npcvar.mainNPC.position.X, (int)npcvar.mainNPC.position.Y, npcvar.mainNPC.width, npcvar.mainNPC.height, obj.itemID, obj.itemStack, false, pre, false);
                    }
                }
            }

            npcvar.isDead      = true;
            npcvar.droppedLoot = true;

            npcvar.OnDeath();
        }
示例#3
0
        /// <summary>
        /// Teleports a NPC to a specific location in a region
        /// </summary>
        /// <param name="region"></param>
        /// <param name="randompos"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void TeleportNPC(CustomNPCVars npcvar, string region, bool randompos = true, int x = 0, int y = 0)
        {
            Region obj = null;

            try
            {
                obj = TShock.Regions.GetRegionByName(region);
            }
            catch
            {
                TShock.Log.ConsoleError("Error: a defined region does not exist on this map \"{0}\"", region);
                return;
            }

            if (randompos)
            {
                TShock.Utils.GetRandomClearTileWithInRange(obj.Area.Left, obj.Area.Top, obj.Area.Width, obj.Area.Height, out x, out y);
            }
            else
            {
                x += obj.Area.Left;
                y += obj.Area.Top;
            }

            TeleportNPC(npcvar, x, y);
        }
示例#4
0
        /// <summary>
        /// (Attempts to) Spawn monsters randomly around the current x y position.
        /// </summary>
        /// <param name="npcvar">The Custom NPC to use to spawn children</param>
        /// <param name="amount">The amount to spawn</param>
        /// <param name="sethealth"></param>
        /// <param name="health"></param>
        public void Multiply(CustomNPCVars npcvar, int amount, bool sethealth = false, int health = 0)
        {
            // MainNPC is gone.
            if (mainNPC == null)
            {
                return;
            }

            if (npcvar == null)
            {
                return;
            }

            Multiply(npcvar.customNPC, amount, sethealth, health);
        }
示例#5
0
        /// <summary>
        /// Sends a message to all nearby players, distance define-able
        /// </summary>
        /// <param name="distance"></param>
        /// <param name="message"></param>
        /// <param name="color"></param>
        public void MessageNearByPlayers(CustomNPCVars npcvar, int distance, string message, Color color)
        {
            Vector2 temp       = ReturnPos(npcvar);
            int     squaredist = distance * distance;

            foreach (TSPlayer obj in TShock.Players)
            {
                if (obj == null || !obj.ConnectionAlive)
                {
                    continue;
                }

                if (Vector2.DistanceSquared(temp, obj.LastNetPosition) <= squaredist)
                {
                    obj.SendMessage(message, color);
                }
            }
        }
示例#6
0
        /// <summary>
        /// Fires a projectile given the target starting position and projectile class
        /// </summary>
        /// <param name="target"></param>
        /// <param name="origin"></param>
        /// <param name="projectile"></param>
        private void FireProjectile(TSPlayer target, CustomNPCVars origin, CustomNPCProjectiles projectile)
        {
            //Loop through all ShotTiles
            foreach (ShotTile obj in projectile.projectileShotTiles)
            {
                //Make sure target actually exists - at this point it should always exist
                if (target == null)
                {
                    continue;
                }

                //Calculate starting position
                Vector2 start = GetStartPosition(origin, obj);
                //Calculate speed of projectile
                Vector2 speed = CalculateSpeed(start, target);
                //Get the projectile AI
                Tuple <float, float> ai = Tuple.Create(projectile.projectileAIParams1, projectile.projectileAIParams2);

                // Create new projectile VIA Terraria's method, with all customizations
                int projectileIndex = Projectile.NewProjectile(
                    start.X,
                    start.Y,
                    speed.X,
                    speed.Y,
                    projectile.projectileID,
                    projectile.projectileDamage,
                    0,
                    255,
                    ai.Item1,
                    ai.Item2);

                // customize AI for projectile again, as it gets overwritten
                var proj = Main.projectile[projectileIndex];
                proj.ai[0] = ai.Item1;
                proj.ai[1] = ai.Item2;

                // send projectile as a packet
                NetMessage.SendData(27, -1, -1, null, projectileIndex);
            }
        }
示例#7
0
 /// <summary>
 /// Returns the current position of the monster
 /// </summary>
 /// <returns></returns>
 public Vector2 ReturnPos(CustomNPCVars npcvar)
 {
     return(new Vector2(npcvar.mainNPC.position.X, npcvar.mainNPC.position.Y));
 }
示例#8
0
 /// <summary>
 /// Properly teleports an NPC to a new location.
 /// </summary>
 /// <param name="npcvar"></param>
 /// <param name="x"></param>
 /// <param name="y"></param>
 public void TeleportNPC(CustomNPCVars npcvar, int x, int y)
 {
     npcvar.mainNPC.Teleport(new Vector2(x * 16, y * 16));
 }
示例#9
0
 /// <summary>
 /// Statically set x y based on the world coordinates, and teleport npc there
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 public void TeleportNPC_NoUpdate(CustomNPCVars npcvar, int x, int y)
 {
     npcvar.mainNPC.position = new Vector2(x * 16, y * 16);
 }
示例#10
0
        /// <summary>
        /// NPC MISC
        /// </summary>
        //internal CustomParticle customParticle { get; set; };

        public virtual void OnDeath(CustomNPCVars vars)
        {
        }
示例#11
0
        // Returns start position of projectile with shottile offset
        private Vector2 GetStartPosition(CustomNPCVars origin, ShotTile shottile)
        {
            Vector2 offset = new Vector2(shottile.X, shottile.Y);

            return(origin.mainNPC.frame.Center() + offset);
        }
示例#12
0
        private void OnNpcDamaged(TSPlayer player, int npcIndex, int damage, float knockback, byte direction, bool critical)
        {
            //DEBUG
            TShock.Log.ConsoleInfo("DEBUG [NPCDamage] NPCIndex {0}", npcIndex);
            //DEBUG

            NPC    npc        = Main.npc[npcIndex];
            double damageDone = Main.CalculateDamage(damage, npc.ichor ? npc.defense - 20 : npc.defense);

            if (critical)
            {
                damageDone *= 2;
            }

            //Damage event
            var e = new NpcDamageEvent
            {
                NpcIndex    = npcIndex,
                PlayerIndex = player.Index,
                Damage      = damage,
                Knockback   = knockback,
                Direction   = direction,
                CriticalHit = critical,
                NpcHealth   = Math.Max(0, npc.life - (int)damageDone)
            };

            eventManager.InvokeHandler(e, EventType.NpcDamage);

            //This damage will kill the NPC.
            if (npc.active && npc.life > 0 && damageDone >= npc.life)
            {
                CustomNPCVars npcvar = NPCManager.NPCs[npcIndex];
                if (npcvar != null)
                {
                    npcvar.markDead();
                }

                //Kill event
                var killedArgs = new NpcKilledEvent
                {
                    NpcIndex     = npcIndex,
                    PlayerIndex  = player.Index,
                    Damage       = damage,
                    Knockback    = knockback,
                    Direction    = direction,
                    CriticalHit  = critical,
                    LastPosition = npc.position
                };

                var SEconReward = new Money(npcvar.customNPC.SEconReward);

                // TODO: Improve Seconomy Code if needed
                // My Implementation of Seconomy Rewards, it's bountys for the last player who hits and kills the enemy, Not sure if this is the best way to do this
                // Remove when a actual fix is provide

                if (npcvar != null)
                {
                    var economyPlayer = SEconomyPlugin.Instance.GetBankAccount(TSPlayer.Server.User.ID);

                    if (!UsingSEConomy || !economyPlayer.IsAccountEnabled)
                    {
                        if (!economyPlayer.IsAccountEnabled)
                        {
                            TShock.Log.Error("You cannot gain any bounty because your account is disabled.");
                        }
                    }
                    else
                    {
                        if (npcvar.customNPC.SEconReward > 0)
                        {
                            IBankAccount Player = SEconomyPlugin.Instance.GetBankAccount(TSPlayer.Server.User.ID);
                            SEconomyPlugin.Instance.WorldAccount.TransferToAsync(Player, SEconReward,
                                                                                 BankAccountTransferOptions.AnnounceToReceiver,
                                                                                 npcvar.customNPC.customName + " Bountie",
                                                                                 "Custom Npc Kill");
                            SEconReward = 0;
                        }
                    }
                }

                eventManager.InvokeHandler(killedArgs, EventType.NpcKill);

                if (npcvar != null && npcvar.isInvasion)
                {
                    NPCManager.CustomNPCInvasion.WaveSize--;
                }
            }
        }