Ejemplo n.º 1
0
        public static bool RebuildTooltip_SetItemTooltip(Terraria.Item __instance)
        {
            // The specially named __instance parameter is automatically filled in by Harmony to reference the Item instance that is calling this method.

            if (!PluginLoadedSuccessfully)       // If there was a problem loading things for our plugin, we will abort this stub method so we dont crash Terraria.
            {
                return(true);                    // Allow the original method to execute
            }
            if (__instance.type == WeaponItemID) // Only apply our weapon's tooltip if the item that had RebuildTooltip called on it actually is our weapon.
            {
                // Terraria.UI.ItemTooltip does not have a public constructor, so we must use Activator to create an ItemTooltip instance
                var tooltip = (Terraria.UI.ItemTooltip)Activator.CreateInstance(typeof(Terraria.UI.ItemTooltip), true);

                // Terraria.Localization.LocalizedText also does not have a public constructor, so we need to use Reflection
                Type localizedTextType    = typeof(Terraria.Localization.LocalizedText);
                var  localizedTooltipText = (Terraria.Localization.LocalizedText)HHelpers.ActivateInstanceUsingFirstConstructor(localizedTextType, new object[] { "", WeaponItemTooltipText }); // This type has only one constructor
                // By using the ActivateInstanceUsingFirstConstructor() helper method, we avoid directly using Reflection and thus don't violate plugin Security Level 4

                // Also, Terraria.UI.ItemTooltip._text is a private field, so we need to use Reflection to set its value.
                HHelpers.SetFieldValueWithReflection("_text", tooltip, localizedTooltipText);
                // The recommended way to do this is to use HHelpers.SetFieldValueWithReflection(), which is compliant with all security levels.
                // You can, of course, use reflection yourself, but then your plugin will violate plugin Security Level 4.

                __instance.ToolTip = tooltip; // Assign the newly-created tooltip to the Item
                WeaponItemTooltip  = tooltip; // And hold onto it for later

                return(false);                // Don't allow the original method to execute
            }

            return(true); // Allow the original method to execute
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a new patch operation using the supplied target type name, target method name, target method parameter count, stub method name, and patch location.
        /// </summary>
        /// <param name="targetTypeFullName">The full name of target type (in Terraria) that contains the target method, e.g. "Terraria.Main".</param>
        /// <param name="targetMethodName">The name of the target method.</param>
        /// <param name="targetMethodParamCount">The number of parameters in the target method. Can be used to help discern between method overloads.</param>
        /// <param name="stubMethodName">The name of the stub method IN THIS CLASS that will be either prepended or appended to the target method. Must be a static method!</param>
        /// <param name="patchLocation">Whether the stub method will be prepended as a prefix or appended as a postfix to the target method.</param>
        /// <param name="patchPriority">The priority of this patch, as used by Harmony to order multiple patches on the same method. Patches with higher numbers go first. Set to -1 to use default priority (typically = 400).</param>
        protected void CreateHPatchOperation(string targetTypeFullName, string targetMethodName, int targetMethodParamCount, string stubMethodName, HPatchLocation patchLocation, int patchPriority = -1)
        {
            Type targetType = null;

            if (!HHelpers.TryGetTerrariaType(targetTypeFullName, out targetType))
            {
                throw new Exception("Invalid targetTypeFullName. Terraria does not contain a type named \"" + targetTypeFullName + "\".");
            }

            // First look in normal methods
            MethodBase targetMethod = targetType.GetRuntimeMethods().Where(x =>
                                                                           x.Name == targetMethodName &&
                                                                           x.GetParameters().Count() == targetMethodParamCount).FirstOrDefault();

            if (targetMethod == null) // If nothing was found, look in constructors next
            {
                targetMethod = targetType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(x =>
                                                                                                                                                            x.Name == targetMethodName &&
                                                                                                                                                            x.GetParameters().Count() == targetMethodParamCount).FirstOrDefault();
            }
            if (targetMethod == null)
            {
                throw new Exception("Invalid target method. The target type does not contain a method or constructor named \"" + stubMethodName + "\" with " + targetMethodParamCount + " parameters.");
            }

            CreateHPatchOperation(targetMethod, stubMethodName, patchLocation, patchPriority);
        }
Ejemplo n.º 3
0
        public static bool SetDefaults_SetItemDefaults(Terraria.Item __instance, int Type)
        {
            // The specially named __instance parameter is automatically filled in by Harmony to reference the Item instance that is calling this method.
            // The type parameter is automatically filled in by Harmony to be the same value as the type parameter that was passed to the original method.

            if (!PluginLoadedSuccessfully) // If there was a problem loading things for our plugin, we will abort this stub method so we dont crash Terraria.
            {
                return(true);              // By returning true, we tell Harmony to allow the original method to execute
            }
            if (Type == WeaponItemID)      // Only apply our weapon's Item defaults if the item that had SetDefaults called on it actually is our weapon.
            {
                // We need to do the same things that SetDefaults() does, since we will prevent the original SetDefaults() from running after our prefix here is done.

                if (Terraria.Main.netMode == 1 || Terraria.Main.netMode == 2)
                {
                    __instance.playerIndexTheItemIsReservedFor = 255;
                }
                else
                {
                    __instance.playerIndexTheItemIsReservedFor = Terraria.Main.myPlayer;
                }

                __instance.ResetStats(Type);

                __instance.damage       = 64;                                                          // How much damage projectiles from this weapon will do
                __instance.mana         = 10;                                                          // How much mana is required to use this weapon
                __instance.shoot        = 3001;                                                        // ID of the Projectile to shoot when used (which is our custom projectile)
                __instance.shootSpeed   = 5f;                                                          // Speed of the Projectile that this weapon shoots
                __instance.knockBack    = 1.5f;                                                        // Amount of knockback dealt when this weapon's Projectile hits something
                __instance.value        = Terraria.Item.sellPrice(0, 2, 4, 8);                         // How much this item is worth
                __instance.magic        = true;                                                        // Whether or not this item is a magic weapon (and is thus affected by magic dmg/crit/etc stat boosters)
                __instance.noMelee      = true;                                                        // Whether or not this item has a melee hitbox and melee effects when used
                __instance.rare         = 9;                                                           // Rarity factor, which affects the color of the item's text
                __instance.autoReuse    = true;                                                        // Allows continuous use while left mouse is held down
                __instance.useTime      = 13;                                                          // How long it takes to use this item one time (in frames)
                __instance.useAnimation = 13;                                                          // How long the item stays on screen for (in frames) when it is used
                __instance.width        = 42;                                                          // Width of the weapon
                __instance.height       = 42;                                                          // Height of the weapon
                __instance.useStyle     = 5;                                                           // How the item is swung/held when used
                __instance.UseSound     = Terraria.ID.SoundID.Item158;                                 // Sound to play when the item is used

                __instance.RebuildTooltip();                                                           // Generate the item's tooltip text

                HHelpers.SetFieldValueWithReflection("_nameOverride", __instance, WeaponItemNameText); // Set item's name

                // Also, in case the async texture loading replaced our weapon's texture with something else, let's make sure the right texture is in our item's slot
                if (ItemGraphicAsset != null)
                {
                    Terraria.GameContent.TextureAssets.Item[WeaponItemID] = ItemGraphicAsset; // Reassign the field with the asset we created earlier
                }
                return(false);                                                                // By returning false, we tell Harmony to skip over the original method
            }

            return(true); // Tell Harmony to allow the original method to execute
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates a new patch operation using the supplied target type name, target method name, stub method name, and patch location.
        /// </summary>
        /// <param name="targetTypeFullName">The full name of target type (in Terraria) that contains the target method, e.g. "Terraria.Main".</param>
        /// <param name="targetMethodName">The name of the target method.</param>
        /// <param name="stubMethodName">The name of the stub method IN THIS CLASS that will be either prepended or appended to the target method. Must be a static method!</param>
        /// <param name="patchLocation">Whether the stub method will be prepended as a prefix or appended as a postfix to the target method.</param>
        /// <param name="patchPriority">The priority of this patch, as used by Harmony to order multiple patches on the same method. Patches with higher numbers go first. Set to -1 to use default priority (typically = 400).</param>
        protected void CreateHPatchOperation(string targetTypeFullName, string targetMethodName, string stubMethodName, HPatchLocation patchLocation, int patchPriority = -1)
        {
            Type targetType = null;

            if (!HHelpers.TryGetTerrariaType(targetTypeFullName, out targetType))
            {
                throw new Exception("Invalid targetTypeFullName. Terraria does not contain a type named \"" + targetTypeFullName + "\".");
            }

            CreateHPatchOperation(targetType, targetMethodName, stubMethodName, patchLocation, patchPriority);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates a new patch operation using the supplied target type name, target method name, target method parameter count, target method last parameter type, stub method name, and patch location.
        /// </summary>
        /// <param name="targetTypeFullName">The full name of target type (in Terraria) that contains the target method, e.g. "Terraria.Main".</param>
        /// <param name="targetMethodName">The name of the target method.</param>
        /// <param name="targetMethodParamCount">The number of parameters in the target method. Can be used to help discern between method overloads.</param>
        /// <param name="targetMethodLastParamType">The type of the target method's last parameter. Can be used to help discern between method overloads.</param>
        /// <param name="stubMethodName">The name of the stub method IN THIS CLASS that will be either prepended or appended to the target method. Must be a static method!</param>
        /// <param name="patchLocation">Whether the stub method will be prepended as a prefix or appended as a postfix to the target method.</param>
        /// <param name="patchPriority">The priority of this patch, as used by Harmony to order multiple patches on the same method. Patches with higher numbers go first. Set to -1 to use default priority (typically = 400).</param>
        protected void CreateHPatchOperation(string targetTypeFullName, string targetMethodName, int targetMethodParamCount, Type targetMethodLastParamType, string stubMethodName, HPatchLocation patchLocation, int patchPriority = -1)
        {
            Type targetType = null;

            if (!HHelpers.TryGetTerrariaType(targetTypeFullName, out targetType))
            {
                throw new Exception("Invalid targetTypeFullName. Terraria does not contain a type named \"" + targetTypeFullName + "\".");
            }

            MethodInfo targetMethod = targetType.GetRuntimeMethods().Where(x =>
                                                                           x.Name == targetMethodName &&
                                                                           x.GetParameters().Count() == targetMethodParamCount &&
                                                                           x.GetParameters().Count() > 0 &&
                                                                           x.GetParameters()[x.GetParameters().Count() - 1].ParameterType == targetMethodLastParamType).FirstOrDefault();

            if (targetMethod == null)
            {
                throw new Exception("Invalid target method. The target type does not contain a method named \"" + stubMethodName + "\" with " + targetMethodParamCount + " parameters and a final parameter of type \"" + targetMethodLastParamType.FullName + "\"");
            }

            CreateHPatchOperation(targetMethod, stubMethodName, patchLocation, patchPriority);
        }
Ejemplo n.º 6
0
        public static void LoadContent_LoadProjectileAssets(Terraria.Main __instance)
        {
            // The specially named __instance parameter is automatically filled in by Harmony to reference the Main instance that is calling this method.

            // We'll do all our setup in a try-catch so we don't crash Terraria if something goes wrong.
            try
            {
                // Load our custom projectile's texture from the embedded resource bytes we extracted in ConfigurationLoaded()
                ProjectileGraphic = HHelpers.AssetHandling.CreateTexture2DFromImageBytes(ProjectileGraphicBytes, __instance.GraphicsDevice, true, new Vector4(1f, 1f, 1f, 1f / 2.2f));
                // The PNG used in this example was written with an alpha channel gamma space that does not look good in Terraria, hence the use of the final parameter (gammaCorrection) to do some correction.
                // NOTE: Only use the gammaCorrection parameter if you know what you are doing, otherwise just skip it (or set to default value of null)

                // Just like with creating new items, we need to expand a bunch of projectile design data arrays to reach up to our projectile's ID.
                // We will fill the placeholder spaces between the last vanilla ID and our custom ID with default values.
                Helper_ExpandArray(ref Terraria.Main.projFrames, ProjectileID, 0);
                Terraria.Main.projFrames[ProjectileID] = 8;     // Our custom projectile has 8 frames of animation
                Helper_ExpandArray(ref Terraria.Main.projHook, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.Main.projHostile, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.Main.projPet, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.CanDistortWater, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.CountsAsHoming, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.DismountsPlayersOnHit, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.DontApplyParryDamageBuff, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.DontAttachHideToAlpha, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.DrawScreenCheckFluff, ProjectileID, 480);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.ExtendedCanHitCheckRange, ProjectileID, 0f);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.ExtendedCanHitCheckSearch, ProjectileID, null);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.ForcePlateDetection, ProjectileID, null);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.ImmediatelyUpdatesNPCBuffFlags, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.IsADD2Turret, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.IsAGolfBall, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.IsAMineThatDealsTripleDamageWhenStationary, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.IsARocketThatDealsDoubleDamageToPrimaryEnemy, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.IsAWhip, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.LightPet, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.MinionSacrificable, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.MinionShot, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.MinionTargettingFeature, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.NeedsUUID, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.NoLiquidDistortion, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.RocketsSkipDamageForPlayers, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.SentryShot, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.StardustDragon, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.StormTiger, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.TrailCacheLength, ProjectileID, 10);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.TrailingMode, ProjectileID, -1);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.TurretFeature, ProjectileID, false);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.WindPhysicsImmunity, ProjectileID, null);
                Terraria.ID.ProjectileID.Sets.WindPhysicsImmunity[ProjectileID] = true;     // We want our custom projectile to be immune to wind since it is an energy ball
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.YoyosLifeTimeMultiplier, ProjectileID, -1f);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.YoyosMaximumRange, ProjectileID, 200f);
                Helper_ExpandArray(ref Terraria.ID.ProjectileID.Sets.YoyosTopSpeed, ProjectileID, 10f);

                // Next we need to extend the Terraria.GameContent.TextureAssets.Projectile array to reach our Projectile's ID in size and include our Projectile's texture
                Helper_ExpandArray(ref Terraria.GameContent.TextureAssets.Projectile, ProjectileID, Terraria.GameContent.TextureAssets.Projectile[0]); // Use the first texture in the list as a default placeholder
                // Now create a ReLogic.Content.Asset<Texture2D> to hold our projectile's graphic
                Type assetType = typeof(ReLogic.Content.Asset <Texture2D>);
                ProjectileGraphicAsset = (ReLogic.Content.Asset <Texture2D>)HHelpers.ActivateInstanceUsingFirstConstructor(assetType, new object[] { "Projectile_WeaponProcessorOnAStick_ElectricBall" }); // This type has only one constructor
                // By using the ActivateInstanceUsingFirstConstructor() helper method, we avoid directly using Reflection and thus don't violate plugin Security Level 4
                HHelpers.SetPropertyValueWithReflection("Value", ProjectileGraphicAsset, ProjectileGraphic);                                                                                               // Set the Value (which is of type Texture2D)
                HHelpers.SetPropertyValueWithReflection("State", ProjectileGraphicAsset, ReLogic.Content.AssetState.Loaded);                                                                               // Set the loaded state to Loaded
                Terraria.GameContent.TextureAssets.Projectile[ProjectileID] = ProjectileGraphicAsset;                                                                                                      // Assign the newly created asset to our projectile's slot in the array
            }
            catch (Exception e)
            {
                // Something went wrong, so we will set PluginLoadedSuccessfully to false and thus disable the rest of our plugin code.
                // If you are debugging a plugin, however, you probably DONT want to do this, or you might miss thrown exceptions.
                PluginLoadedSuccessfully = false;
                return;
            }
        }
Ejemplo n.º 7
0
        public static void LoadContent_LoadWeaponAssets(Terraria.Main __instance)
        {
            // The specially named __instance parameter is automatically filled in by Harmony to reference the Main instance that is calling this method.

            // We'll do all our setup in a try-catch so we don't crash Terraria if something goes wrong.
            try
            {
                // Load our weapon's texture from the embedded resource bytes we extracted in ConfigurationLoaded()
                ItemGraphic = HHelpers.AssetHandling.CreateTexture2DFromImageBytes(ItemGraphicBytes, __instance.GraphicsDevice);
                // Using CreateTexture2DFromImageBytes() is compliant with all security levels and is the recommended way to create Texture2Ds.
                // You could use your own Streams, but using Streams (or any other type in System.IO) will make your plugin violate Security Level 3.

                // We will also modify some necessary arrays here (this method will only be called once, so this is a good time to modify these arrays).
                // There are many arrays which are indexed using the item's type (aka ID). We need to expand all those arrays to reach up to our item's ID.
                // We will fill the placeholder spaces between the last vanilla ID and our new ID with default values.
                Helper_ExpandArray(ref Terraria.Item.cachedItemSpawnsByType, WeaponItemID, -1);
                Helper_ExpandArray(ref Terraria.Item.claw, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.Item.staff, WeaponItemID, false);
                Terraria.Item.staff[WeaponItemID] = true;     // Our item is a staff, so we set this to true for our slot
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.AlsoABuildingItem, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.AnimatesAsSoul, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.BonusMeleeSpeedMultiplier, WeaponItemID, 1f);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.CanBePlacedOnWeaponRacks, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.CanBeQuickusedOnGamepad, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.CanGetPrefixes, WeaponItemID, false);
                Terraria.ID.ItemID.Sets.CanGetPrefixes[WeaponItemID] = true;     // Our item is a weapon & we want to it be able to get prefixes, so we set this to true for our slot
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.Deprecated, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.DrinkParticleColors, WeaponItemID, new Color[0]);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ExtractinatorMode, WeaponItemID, -1);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.FoodParticleColors, WeaponItemID, new Color[0]);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ForceConsumption, WeaponItemID, null);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.GamepadExtraRange, WeaponItemID, 0);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.GamepadSmartQuickReach, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.GamepadWholeScreenUseRange, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.gunProj, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.HasAProjectileThatHasAUsabilityCheck, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IgnoresEncumberingStone, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsAKite, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsAMaterial, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsAPickup, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsChainsaw, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsDrill, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsFishingCrate, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsFishingCrateHardmode, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsFood, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsLavaBait, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.IsPaintScraper, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ItemIconPulse, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ItemNoGravity, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ItemSpawnDecaySpeed, WeaponItemID, 1);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ItemsThatAllowRepeatedRightClick, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ItemsThatCountAsBombsForDemolitionistToSpawn, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.KillsToBanner, WeaponItemID, 50);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.LockOnAimAbove, WeaponItemID, 0);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.LockOnIgnoresCollision, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.NebulaPickup, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.NeverAppearsAsNewInInventory, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.NewItemSpawnPriority, WeaponItemID, 0);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.SingleUseInGamepad, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.SkipsInitialUseSound, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.SummonerWeaponThatScalesWithAttackSpeed, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.TextureCopyLoad, WeaponItemID, -1);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.ToolTipDamageMultiplier, WeaponItemID, 1f);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.Torches, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.TrapSigned, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.UsesCursedByPlanteraTooltip, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.WaterTorches, WeaponItemID, false);
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.Yoyo, WeaponItemID, false);

                // We also need to expand Terraria.Main.itemAnimations to reach up to our item's ID and include a Terraria.DataStructures.DrawAnimation for our weapon's Item
                Helper_ExpandArray(ref Terraria.Main.itemAnimations, WeaponItemID, null); // Add null DrawAnimations in the dummy slots (and in our weapon's slot as well, since the sprite has a single frame and no animations)

                // We also need to expand Terraria.ID.ItemID.Sets.TextureCopyLoad to reach up to our item's ID
                Helper_ExpandArray(ref Terraria.ID.ItemID.Sets.TextureCopyLoad, WeaponItemID, 0); // We will have all the empty placeholder spots set to 0 so that they mirror load the texture in index 0 (as opposed to crashing from trying to load an out-of-range texture index)

                // Next we need to extend the Terraria.GameContent.TextureAssets.Item array to reach our item's ID in size and include our Item's texture
                Helper_ExpandArray(ref Terraria.GameContent.TextureAssets.Item, WeaponItemID, Terraria.GameContent.TextureAssets.Item[0]); // Use the first texture in the list as a default placeholder
                // Now create a ReLogic.Content.Asset<Texture2D> to hold our item graphic
                Type assetType = typeof(ReLogic.Content.Asset <Texture2D>);
                ItemGraphicAsset = (ReLogic.Content.Asset <Texture2D>)HHelpers.ActivateInstanceUsingFirstConstructor(assetType, new object[] { "Item_WeaponProcessorOnAStick" }); // This type has only one constructor
                // By using the ActivateInstanceUsingFirstConstructor() helper method, we avoid directly using Reflection and thus don't violate plugin Security Level 4
                HHelpers.SetPropertyValueWithReflection("Value", ItemGraphicAsset, ItemGraphic);                                                                                  // Set the Value (which is of type Texture2D)
                HHelpers.SetPropertyValueWithReflection("State", ItemGraphicAsset, ReLogic.Content.AssetState.Loaded);                                                            // Set the loaded state to Loaded
                Terraria.GameContent.TextureAssets.Item[WeaponItemID] = ItemGraphicAsset;                                                                                         // Assign the newly created asset to our item's slot in the array

                // We also need to create a LocalizedText to hold our weapon Item's name
                Type localizedTextType = typeof(Terraria.Localization.LocalizedText);
                WeaponItemName = (Terraria.Localization.LocalizedText)HHelpers.ActivateInstanceUsingFirstConstructor(localizedTextType, new object[] { "", WeaponItemNameText }); // This type has only one constructor
                // By using the ActivateInstanceUsingFirstConstructor() helper method, we avoid directly using Reflection and thus don't violate plugin Security Level 4
            }
            catch (Exception e)
            {
                // Something went wrong, so we will set PluginLoadedSuccessfully to false and thus disable the rest of our plugin code.
                // If you are debugging a plugin, however, you probably DONT want to do this, or you might miss thrown exceptions.
                PluginLoadedSuccessfully = false;
                return;
            }
        }