tModLoader Mod Help: How can I detect when a player clicks on a specific tile with a specific item, and Confusion with tile drops.

HalcyonCashew24

Terrarian
Hi, I'm having trouble creating this tile that will hold a Water Bolt like an item frame or weapon rack. When the player right clicks on the Water Bolt Pedestal with a Water Bolt the style is supposed to change to an "active" Water Bolt Pedestal and, the Water Bolt is supposed to be taken from the player's hand. When the player right clicks on the active Water Bolt Pedestal with an empty hand the Water Bolt will be given back and the style will be changed to an "inactive" Water Bolt Pedestal. I don't know how to detect when a player clicks on the tile, how to change the style, and how to take the Water Bolt from the player, visa versa. I also can't get the correct items to drop. I can get the Water Bolt Pedestal to drop but when I try to get two items it drops 167 water Bolt Pedestals.

The code is as follows:
C#:
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Terraria.ObjectData;

namespace LegendOfWaterbolt.Tiles
{
    public class WaterBoltPedestal : ModTile
    {
        public override void SetDefaults()
        {
            Main.tileSolidTop[Type] = true;
            Main.tileBlockLight[Type] = false;
            Main.tileLighted[Type] = false;
            Main.tileLavaDeath[Type] = true;
            Main.tileWaterDeath[Type] = true;
            Main.tileNoAttach[Type] = true;
            Main.tileFrameImportant[Type] = true;
            dustType = 279; ;
            TileObjectData.newTile.CopyFrom(TileObjectData.Style3x4);
            TileObjectData.newTile.CoordinateHeights = new int[] { 16, 16, 16, 18 };
            TileObjectData.newTile.CoordinateWidth = 16;
            TileObjectData.newTile.CoordinatePadding = 2;
            TileObjectData.newTile.StyleHorizontal = true;
            TileObjectData.addTile(Type);
            ModTranslation name = CreateMapEntryName();
            name.SetDefault("Water Bolt Pedistal");
            AddMapEntry(new Color(67, 73, 62));
        }
        public override void KillMultiTile(int i, int j, int frameX, int frameY)
        {
            Item.NewItem(i * 16, j * 16, 48, 64, mod.ItemType("WaterBoltPedestal"));
            Item.NewItem(i * 16, j * 16, 96, 64, mod.ItemType("WaterBoltPedestal"), ItemID.WaterBolt);
        }
    }
}

This is the texture:
WaterBoltPedistal.png
 
If you look at the signature of this particular overload of Item.NewItem:
C#:
public static int NewItem(int X, int Y, int Width, int Height, int Type, int Stack = 1, bool noBroadcast = false, int pfix = 0, bool noGrabDelay = false, bool reverseLookup = false)
You can see that the 6th argument is the number of items to drop. (1 by default.)
Your code currently drops one WaterBoltPedestal and then 165 WaterBoltPedestals. (The item ID of WaterBolt is 165.) What you actually want is:
C#:
Item.NewItem(i * 16, j * 16, 48, 64, mod.ItemType("WaterBoltPedestal"));
Item.NewItem(i * 16, j * 16, 48, 64, ItemID.WaterBolt);

To make a tile clickable like this, you need to do two things.

First, you need to make the tile actually do something, by overriding ModTile.RightClick. In this case, here you would check the frameX of the clicked tile, to see if it's the empty or the filled variant.
If it's empty, you need to check the player's held item (Main.LocalPlayer.inventory[Main.LocalPlayer.selectedItem]), and if it's the correct one, turn it into air, then shift the frameX of the appropriate tiles to the filled variant. You also need to somehow store the properties of the water bolt item in the tile.
If you right click on a filled pedestal, you just drop the stored water bolt and turn into an empty pedestal.

Now, actually storing the water bolt might be a bit tricky. If you are OK with possibly loosing modded GlobalItem data you could go with the item rack style hack. Where you store the prefix of the stored item in the tile's frameY... But I'd recommend going with a tile entity instead.

The second thing you need to make a tile clickable, is making sure the player won't use or throw away the item they are holding, instead of interacting with your tile. Basically you just need to do this:
C#:
public override void MouseOver(int i, int j)
{
    Main.LocalPlayer.noThrow = 2;
}
 
Thank you for the help. The drop is now the correct item(s). I used if() {} else {} to determine which items to drop based on which frameX. I still can't get the activation though. I don't know how to change the item to air, and I can't change the frameX because it doesn't exist in the context of RightClick(int i, int j). Also, I don't need to store the Water Bolt, I can do the opposite of "placing" the Water Bolt into the pedestal by changing the style of the tile and the player's empty hand into a Water Bolt.

Here's what the RightClick(int i, int j) looks like:
C#:
public override void RightClick(int i, int j)
{
    if (Main.LocalPlayer.inventory[Main.LocalPlayer.selectedItem].modItem.mod.ItemType("WaterBolt") == 1)
    {
        if (frameX <= 48)
        {
            frameX = 96; //changes the style
        }
        else
        {
            return; //does nothing
        }
    }
    else
    {
        return; // not implemented yet, but its going to do the opposite of the if
    }
}
 
Back
Top Bottom