Go to Second Post for Raytrace/recharging item tutorial
I'm going to show you how to create a custom bow (with animation) and arrow. My goal is not to give you code to copy for your own uses but to actually have you understand how it works. I'm going to show you how to make the bow I have in an upcoming mod of mine, a fire bow (creative name, I know), which can light blocks and mobs on fire. I assume you have some knowledge of modding already and have been stuck, like many, at how to create a custom bow. All textures I use in this tutorial can be found here, I only ask that you don't use them in any released work.
Since we're using ModLoader we're going to start out with the usual mod_ file to add our new bow as well as a recipe for it.
package net.minecraft.src;
public class mod_Tutorial extends BaseMod
{
public static final Item FireBow = new ItemFireBow(2042).setItemName("FireBow");
public void load()
{
ModLoader.AddName(FireBow, "Fire Bow");
FireBow.iconIndex = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow.png");
ModLoader.AddRecipe(new ItemStack(FireBow, 1), new Object[] {
"#$ ", "# $", "#$ ", Character.valueOf('#'), Item.bucketLava, Character.valueOf('$'), Block.obsidian});
}
public String getVersion() {
return "27.9387";
}
}
Next step is to create the file ItemFireBow for our bow. We're just going to copy all the code from ItemBow and I'm going to explain how it works as well as make some changes to it.
Most of the code is fairly simple to understand and simply defines some characteristics of the item.
This part is the same as any item and is fairly self-explanatory. Sets the item ID, stacksize and that you can use it 384 times before it breaks.
public ItemFireBow(int i)
{
super(i);
maxStackSize = 1;
setMaxDamage(384);
}
Again, fairly simply. Tells it not to change when you try to eat the bow.
public ItemStack onFoodEaten(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
return itemstack;
}
This part tells the game how long you can draw back the bow and is used to calculate things like the changing textures of the bow and whether or not the arrow is critical. Avoid changing this.
public int getMaxItemUseDuration(ItemStack itemstack)
{
return 0x11940;
}
This tells the game what the item is going to do when you use it, which in this case is "draw back" and the game will stretch the texture.
public EnumAction getItemUseAction(ItemStack itemstack)
{
return EnumAction.bow;
}
Again, a fairly self-explanatory piece of code. When you right click with the item it checks to see if you have any arrows in your inventory and if you do it tells the game to set the item in use, which is the use that we defined above. However, I want my bow to not consume arrows and instead create it's own fire arrow when you shoot it (the bow is made of lava) so I am going to remove the if function and leave the line inside of it.
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
if(entityplayer.capabilities.depleteBuckets || entityplayer.inventory.hasItem(Item.arrow.shiftedIndex))
{
entityplayer.setItemInUse(itemstack, getMaxItemUseDuration(itemstack));
}
return itemstack;
}
Now the important piece of code in our bow is this method. It is the part that actually creates the arrow. I'm going to break it down and explain it again and it is fairly simple when looked at in parts.
Very simple again. This method is called when the player stops using the item and the if function tells it to only continue if the player is on creative mode or has arrows in his inventory. Again, since my bow is not going to consume arrows I'm just going to remove this if function and allow the code to run regardless of whether or not the player has an arrow.
public void onPlayerStoppedUsing(ItemStack itemstack, World world, EntityPlayer entityplayer, int i)
{
if(entityplayer.capabilities.depleteBuckets || entityplayer.inventory.hasItem(Item.arrow.shiftedIndex))
{
This part of the above method is used to determine whether or not the arrow will be critical. The int i that is given when this method is called is how long the player was using the item for. This just does some math that determines if the player held the item for a certain amount of time.
int j = getMaxItemUseDuration(itemstack) - i;
float f = (float)j / 20F;
f = (f * f + f * 2.0F) / 3F;
if((double)f < 0.10000000000000001D)
{
return;
}
if(f > 1.0F)
{
f = 1.0F;
}
This part is initially the same as spawning any other type of Entity such as a mob if you have done that before. It tells the game that you are creating a new instance of the class EntityArrow. However, we want it to spawn our custom arrow so we're going to change the names to match. Notice that in the parameters of EntityFireArrow it includes the value 'f' which was calculated based on how long the bow was held. That is used in the bow to calculate the initial velocity of the arrow that spawns. However, I don't want my fire arrow to have a critical hit because that trails brown particles behind it, but I want mine to give off fire and that would just conflict so I am going to remove the if function that sets arrowCritical to true.
EntityArrow entityarrow = new EntityArrow(world, entityplayer, f * 2.0F);
if(f == 1.0F)
{
entityarrow.arrowCritical = true;
}
The remainder of the code in this method is fairly simple. It damages the item by 1 each time you fire an arrow, plays a sound effect for shooting a bow, consumes an arrow from your inventory and then finally tells the game that our new arrow has been created. Since our bow is not using up arrows I'm going to remove the line that consumes an arrow from the player's inventory. We also need to change any mention of entityarrow to entityfirearrow to match the rest of our code.
That's all of ItemBow's default code now, but we have to add something ourselves to it. Usually a bow's texture changes as you draw it back but that code is all inside of EntityPlayer, which is a huge base file that we don't want to edit because then your mod doesn't work with a lot other mods. There is a way around this though that we can do inside of our ItemFireBow. Inside of our bow's code we are going to update the texture based on what state the bow is in. Unfortunately, it means that when you are holding and using your bow it changes the texture of every single instance of that bow in your inventory. It can look silly sometimes, but I prefer it to not having a changing animation. You can skip this if you choose. We're going to create a new method that is called for our item every single tick in game (20 ticks per second) inside of which it will change it's texture if it needs to.
public void onUpdate(ItemStack itemstack, World world, Entity entity, int i, boolean flag)
{
}
Now we're going to start adding code to the above method to accomplish what we want. This part converts the Entity that the method gives us into EntityPlayer so that we can use it in some code. It then checks to see if the player is A: using an item and B: holding the bow because we only want to change the texture if the bow is actually being used.
Now we can add the actual code for changing textures into the above if function. This is nearly the same as the code that calculates the changing textures for the default bow. It checks the difference between the item's max use time and how long the player has been using it for and then changes the texture based on that difference.
However we need to define these values that we are referring it to inside of our mod_ file so we need to add this to our mod_ file outside of the load() method.
public static int fireBow1 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow1.png");
public static int fireBow2 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow2.png");
public static int fireBow3 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow3.png");
public static int fireBow4 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow4.png");
Now we have to create the actual arrow that our new bow is firing. Start out with a new EntityFireArrow and copy all code from EntityArrow. First thing we need to do is change all instances of EntityArrow to EntityFireArrow. Now we can start changing things in it. First thing is to find this method and then delete it entirely. Since this bow is "conjuring" up a fire arrow we don't want the player to pick up an arrow from this.
The next thing we want to add is the code to light the ground on fire. Inside the onUpdate method find the part where it says if(inGround). In the beginning of that if function add the following code. The first part determines what block the arrow is on based on the arrows coordinates. Then it checks that the block it is in is air (we don't want to turn water into fire) and if it is it sets that block to fire. It also sets the entity to dead because we don't want our arrow sticking around after we've lit the ground on fire.
if(inGround)
{
int i1 = MathHelper.floor_double(posX);
int j1 = MathHelper.floor_double(posY);
int k1 = MathHelper.floor_double(posZ);
if(worldObj.getBlockId(i1, j1, k1) == 0)
{
worldObj.setBlockWithNotify(i1, j1, k1, Block.fire.blockID);
}
setEntityDead();
Now we also want our fire arrow to look fiery so let's add some particles to it. Find the very end of the method onUpdate and add the following code. This creates a new flame particle where the arrow is and gives it a small amount of reverse motion.
Leaving a trail of fire and lighting the ground on fire isn't good enough for me. I want it to light mobs on fire too, so find the following if function inside of onUpdate and make it look like this. The line we added will set the entity that it hits on fire for 6 total points of fire damage. Change the number at the end to whatever you want.
Now we're almost done with this file but one last part will give us an error unless we change it. Find both places within the code (they should be next to each other) that say "DamageSource.causeArrowDamage" and change it to "causeFireArrowDamage". Now that we told it to refer to a different method, we have to create this new method. So anywhere inside of your EntityFireArrow class add the following method.
public static DamageSource causeFireArrowDamage(EntityFireArrow entityarrow, Entity entity)
{
return (new EntityDamageSourceIndirect("fireball", entityarrow, entity)).setFireDamage().setProjectile();
}
Now we're almost finished. The last file we need to create is RenderFireArrow so that we can actually see it in game rather than just a white blob. Copy all the code from RenderArrow and change any instance of Arrow to FireArrow and arrow to firearrow (watch your capitals!). Also inside of this file is the code that tells it what texture to load. Simply change it to our texture like so, with no ModLoader code needed.
loadTexture("/tutorial/arrows.png");
The last thing we need to do is tell the game that our new RenderFireArrow file goes with our EntityFireArrow which we do through ModLoader. Inside your mod_ file add this line just below the package statement.
import java.util.*;
And somewhere outside of load() place this new method which relates our render file to our entity file.
public void AddRenderer(Map map)
{
map.put(EntityFireArrow.class, new RenderFireArrow());
}
That should be the last of it. If anything isn't working for you just post and I'll help where I can. The final versions of all the files are below.
mod_Tutorial
package net.minecraft.src;
import java.util.*;
public class mod_Tutorial extends BaseMod
{
public static final Item FireBow = new ItemFireBow(2042).setItemName("FireBow");
public void load()
{
ModLoader.AddName(FireBow, "Fire Bow");
FireBow.iconIndex = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow.png");
ModLoader.AddRecipe(new ItemStack(FireBow, 1), new Object[] {
"#$ ", "# $", "#$ ", Character.valueOf('#'), Item.bucketLava, Character.valueOf('$'), Block.obsidian});
}
public void AddRenderer(Map map)
{
map.put(EntityFireArrow.class, new RenderFireArrow());
}
public static int fireBow1 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow1.png");
public static int fireBow2 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow2.png");
public static int fireBow3 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow3.png");
public static int fireBow4 = ModLoader.addOverride("/gui/items.png", "/tutorial/firebow4.png");
public String getVersion() {
return "27.9387";
}
}
ItemFireBow
package net.minecraft.src;
import java.util.Random;
public class ItemFireBow extends Item
{
public ItemFireBow(int i)
{
super(i);
maxStackSize = 1;
setMaxDamage(384);
}
public void onUpdate(ItemStack itemstack, World world, Entity entity, int i, boolean flag)
{
EntityPlayer entityplayer = (EntityPlayer)entity;
ItemStack itemstack1 = entityplayer.inventory.getCurrentItem();
if(entityplayer.isUsingItem() && itemstack1.itemID == mod_Tutorial.FireBow.shiftedIndex)
{
int k = itemstack.getMaxItemUseDuration() - entityplayer.func_35205_Y();
if(k >= 18)
{
iconIndex = mod_Tutorial.fireBow4;
}else
if(k > 13)
{
iconIndex = mod_Tutorial.fireBow3;
}else
if(k > 0)
{
iconIndex = mod_Tutorial.fireBow2;
}else
iconIndex = mod_Tutorial.fireBow1;
}
}
public void onPlayerStoppedUsing(ItemStack itemstack, World world, EntityPlayer entityplayer, int i)
{
int j = getMaxItemUseDuration(itemstack) - i;
float f = (float)j / 20F;
f = (f * f + f * 2.0F) / 3F;
if((double)f < 0.10000000000000001D)
{
return;
}
if(f > 1.0F)
{
f = 1.0F;
}
EntityFireArrow entityfirearrow = new EntityFireArrow(world, entityplayer, f * 2.0F);
itemstack.damageItem(1, entityplayer);
world.playSoundAtEntity(entityplayer, "random.bow", 1.0F, 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + f * 0.5F);
world.spawnEntityInWorld(entityfirearrow);
}
public ItemStack onFoodEaten(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
return itemstack;
}
public int getMaxItemUseDuration(ItemStack itemstack)
{
return 0x11940;
}
public EnumAction getItemUseAction(ItemStack itemstack)
{
return EnumAction.bow;
}
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
entityplayer.setItemInUse(itemstack, getMaxItemUseDuration(itemstack));
return itemstack;
}
}
I'm going to show you how to do a few things in this tutorial. We're going to create an item that finds the exact coordinates of where the player is looking (at any range), spawns lightning there, and has a cooldown.
Your mod_* file should look the same as any other that adds an item so I won't bother explaining it.
For our actual item I'm going to first show the part that gives our item a cooldown whenever we use it. The way we do that is using damage on an item, and it's fairly simple to do. Just like any other item we need to declare that our item can take damage by setting its max damage in the constructor. Whatever you choose to set that to, divide it by 20 and that is how many seconds it takes to recharge before you can use it again.
package net.minecraft.src;
import java.util.Random;
public class ItemLightningWand extends Item
{
public ItemLightningWand(int i)
{
super(i);
setMaxDamage(100);
}
Now we want to set it so that the item will only perform its function whenever it's damage is at 0 (it's fully recharged) so we do that with a simple if statement. Then when it is used, we set the damage of the item to one less than max (max would break the item) so that it is fully on cooldown. This is also where we will add our code later to spawn lightning where the player is looking.
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
if(itemstack.getItemDamage() == 0)
{
// we'll add code here next
itemstack.setItemDamage(99);
}
return itemstack;
}
This is how we make our item actually recharge. Everytime the game ticks this item will reduce it's damage by one, but only if it is above 0 in order to avoid having an item with negative damage. This onUpdate method is called 20 times every second which is why 99 damage would be approximately 5 seconds.
public void onUpdate(ItemStack itemstack, World world, Entity entity, int i, boolean flag)
{
if(itemstack.getItemDamage() > 0)
{
itemstack.damageItem(-1, (EntityLiving)entity);
}
}
}
Now our item should have a full red durability bar on use and then recharge over several seconds. Next step is to add the code to find where the player is looking and then spawn lightning. Everything we're adding next goes inside the if function inside of the onItemRightClick method.
Now this is where the magic happens. The very first part references a method inside of EntityLiving which does the very complicated math for us and returns something called a MovingObjectPosition which we can get a plethora of info from (like coordinates, or if you selected a monster). The value '75.0D' is the maximum distance away that this will work, so change that to whatever max range you want your item to have. The if function that checks if our MovingObjectPosition is null is needed because if there was no block/entity within our maximum distance than it will have a null value, and if we try to do something with our null value the game will get upset with us and crash. If you happen to be doing this in a piece of code that doesn't provide an instance of EntityPlayer then see the spoiler below.
Now we can start pulling information from that MovingObjectPosition. First we convert it to a 3d vector which we can get the actual coordinates from, then we get the x, y and z coordinates of that. Those are specific coordinates (to the decimal) of where we will spawn our entity, but a decimal value can't be used as a block coordinate. The final three lines here convert those doubles into integers that are basically rounded off to the nearest block.
Vec3D vec3d = movingobjectposition.hitVec;
double x = vec3d.xCoord;
double y = vec3d.yCoord;
double z = vec3d.zCoord;
int i = MathHelper.floor_double(x);
int j = MathHelper.floor_double(y);
int k = MathHelper.floor_double(z);
Personally I decided to run another check here to only spawn the lightning bolt if it has a view of the sky (lightning in caves, anyone?) but you can choose to not add this part if you want. This part is very self-explanatory, and it is why we needed to convert to block coordinates above.
Now we actually spawn the lightning bolt if the code has made it all three of the checks so far. Spawning a lightning bolt is the same as spawning any other entity, such as a creeper, and we do so using those specific coordinates we got above. If you use the i, j, k rounded off values then it will be in the corner of whatever block you look at.
EntityLightningBolt entitybolt = new EntityLightningBolt(world, 0D, 0D, 0D);
entitybolt.setLocationAndAngles(x, y, z, 0, 0.0F);
world.entityJoinedWorld(entitybolt);
Also, would you perhaps know how to make a block use a Custom model? I want to make just a campfire. I have the model for it, I just don't know how to implement it. All I want is just a nice campfire, that doesn't set **** on fire, maybe emits fire and smoke particles and just glows like a torch. Could you help me out ?
Also, would you perhaps know how to make a block use a Custom model? I want to make just a campfire. I have the model for it, I just don't know how to implement it. All I want is just a nice campfire, that doesn't set **** on fire, maybe emits fire and smoke particles and just glows like a torch. Could you help me out ?
I haven't tried any custom block rendering yet but there is a good tutorial on it here.
I still think I wrote too much but I guess you can skim over most of it if you already know it. If anyone has any ideas for other tutorials they would like, I'm open to hear them. I don't see the point in rehashing the same tutorials that everyone has done over and over.
The damage for the bow is calculated inside of the actual arrow entity. I don't know of any easy way to change it because of the way damage is handled.
As to why your code isn't working, I have no idea. So it doesn't return any recompile errors?
Any other form to place bowFire1, bowFire2... in entityPlayer without modifying it??
I'm not entirely sure what you mean. Are you asking if I can basically get it to only change texture in your hand, like the regular bow, without modifying EntityPlayer?
Also, would anyone want a tutorial on how to get where the player is looking at? I would do it in the context of an example of how to summon lightning where the player is looking.
The damage for the bow is calculated inside of the actual arrow entity. I don't know of any easy way to change it because of the way damage is handled.
i wasn't aware it was based on arrows, i could try making tiered arrows that only work with specific bows i suppose
As to why your code isn't working, I have no idea. So it doesn't return any recompile errors?
none. i've tried dozens of different things, the bow just pulls back slightly as if that bit of code wasn't even there. to verify: image1-4, 1 is default and 4 is max pullback? 2 and 3 being the other images found in the /gui/items file?
i wasn't aware it was based on arrows, i could try making tiered arrows that only work with specific bows i suppose
none. i've tried dozens of different things, the bow just pulls back slightly as if that bit of code wasn't even there. to verify: image1-4, 1 is default and 4 is max pullback? 2 and 3 being the other images found in the /gui/items file?
I found that the image 1 referred to in your onUpdate code has to be a different file than the defile image. If they aren't different copies of the same image it doesn't work.
I found that the image 1 referred to in your onUpdate code has to be a different file than the defile image. If they aren't different copies of the same image it doesn't work.
this still returns nothing, perhaps the error lays somewhere else in my item file?
kind of embarrassing not being able to figure out something so simple :sad.gif:
package net.minecraft.src;
import java.util.Random;
public class ItemcopperBow extends Item
{
public ItemcopperBow(int i)
{
super(i);
maxStackSize = 1;
setMaxDamage(384);
}
public void onUpdate(ItemStack itemstack, World world, Entity entity, int i, boolean flag)
{
EntityPlayer entityplayer = (EntityPlayer)entity;
ItemStack itemstack1 = entityplayer.inventory.getCurrentItem();
if(entityplayer.isUsingItem() && itemstack1.itemID == mod_bows.copperBow.shiftedIndex)
{
int k = itemstack1.getMaxItemUseDuration() - entityplayer.func_35205_Y();
if(k >= 18)
{
iconIndex = mod_bows.copperBow4;
} else
if(k > 13)
{
iconIndex = mod_bows.copperBow3;
} else
if(k > 0)
{
iconIndex = mod_bows.copperBow2;
} else
iconIndex = mod_bows.copperBow1;
}}
public void onPlayerStoppedUsing(ItemStack itemstack, World world, EntityPlayer entityplayer, int i)
{
if(entityplayer.capabilities.depleteBuckets || entityplayer.inventory.hasItem(Item.arrow.shiftedIndex))
{
int j = getMaxItemUseDuration(itemstack) - i;
float f = (float)j / 20F;
f = (f * f + f * 2.0F) / 3F;
if((double)f < 0.10000000000000001D)
{
return;
}
if(f > 1.0F)
{
f = 1.0F;
}
EntityArrow entityarrow = new EntityArrow(world, entityplayer, f * 2.0F);
if(f == 1.0F)
{
entityarrow.arrowCritical = true;
}
itemstack.damageItem(1, entityplayer);
world.playSoundAtEntity(entityplayer, "random.bow", 1.0F, 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + f * 0.5F);
entityplayer.inventory.consumeInventoryItem(Item.arrow.shiftedIndex);
if(!world.multiplayerWorld)
{
world.spawnEntityInWorld(entityarrow);
}}
}
public ItemStack onFoodEaten(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
return itemstack;
}
public int getMaxItemUseDuration(ItemStack itemstack)
{
return 0x11940;
}
public EnumAction getItemUseAction(ItemStack itemstack)
{
return EnumAction.bow;
}
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
{
if(entityplayer.capabilities.depleteBuckets || entityplayer.inventory.hasItem(Item.arrow.shiftedIndex))
{
entityplayer.setItemInUse(itemstack, getMaxItemUseDuration(itemstack));
}
return itemstack;
}
}
Hi! For the render part of the arrow, is there any way to make it not render like in an arrow shape? like say for a bullet could i render it to look like a bullet instead of an arrow?
Hi! For the render part of the arrow, is there any way to make it not render like in an arrow shape? like say for a bullet could i render it to look like a bullet instead of an arrow?
It's fairly complicated to change the shape it's rendering. If you can understand the RenderArrow file then feel free to play with the shape but otherwise I recommend you just use a different texture and have some empty space when it renders.
Also, would anyone want a tutorial on how to get where the player is looking at? I would do it in the context of an example of how to summon lightning where the player is looking.
@StewieCraft: I was looking for a tutorial like this. Some thing that didn't just GIVE me the code. Now I got it. And Hell yes, I would LOVE to have a tutorial like that under my belt so I understood how to spawn these types of things.
Rollback Post to RevisionRollBack
Did I help you? There's a little white plus down the bottom. I hope your confused!
I'm going to show you how to create a custom bow (with animation) and arrow. My goal is not to give you code to copy for your own uses but to actually have you understand how it works. I'm going to show you how to make the bow I have in an upcoming mod of mine, a fire bow (creative name, I know), which can light blocks and mobs on fire. I assume you have some knowledge of modding already and have been stuck, like many, at how to create a custom bow. All textures I use in this tutorial can be found here, I only ask that you don't use them in any released work.
Since we're using ModLoader we're going to start out with the usual mod_ file to add our new bow as well as a recipe for it.
Next step is to create the file ItemFireBow for our bow. We're just going to copy all the code from ItemBow and I'm going to explain how it works as well as make some changes to it.
Most of the code is fairly simple to understand and simply defines some characteristics of the item.
This part is the same as any item and is fairly self-explanatory. Sets the item ID, stacksize and that you can use it 384 times before it breaks.
Again, fairly simply. Tells it not to change when you try to eat the bow.
This part tells the game how long you can draw back the bow and is used to calculate things like the changing textures of the bow and whether or not the arrow is critical. Avoid changing this.
This tells the game what the item is going to do when you use it, which in this case is "draw back" and the game will stretch the texture.
Again, a fairly self-explanatory piece of code. When you right click with the item it checks to see if you have any arrows in your inventory and if you do it tells the game to set the item in use, which is the use that we defined above. However, I want my bow to not consume arrows and instead create it's own fire arrow when you shoot it (the bow is made of lava) so I am going to remove the if function and leave the line inside of it.
Now the important piece of code in our bow is this method. It is the part that actually creates the arrow. I'm going to break it down and explain it again and it is fairly simple when looked at in parts.
Very simple again. This method is called when the player stops using the item and the if function tells it to only continue if the player is on creative mode or has arrows in his inventory. Again, since my bow is not going to consume arrows I'm just going to remove this if function and allow the code to run regardless of whether or not the player has an arrow.
This part of the above method is used to determine whether or not the arrow will be critical. The int i that is given when this method is called is how long the player was using the item for. This just does some math that determines if the player held the item for a certain amount of time.
This part is initially the same as spawning any other type of Entity such as a mob if you have done that before. It tells the game that you are creating a new instance of the class EntityArrow. However, we want it to spawn our custom arrow so we're going to change the names to match. Notice that in the parameters of EntityFireArrow it includes the value 'f' which was calculated based on how long the bow was held. That is used in the bow to calculate the initial velocity of the arrow that spawns. However, I don't want my fire arrow to have a critical hit because that trails brown particles behind it, but I want mine to give off fire and that would just conflict so I am going to remove the if function that sets arrowCritical to true.
The remainder of the code in this method is fairly simple. It damages the item by 1 each time you fire an arrow, plays a sound effect for shooting a bow, consumes an arrow from your inventory and then finally tells the game that our new arrow has been created. Since our bow is not using up arrows I'm going to remove the line that consumes an arrow from the player's inventory. We also need to change any mention of entityarrow to entityfirearrow to match the rest of our code.
That's all of ItemBow's default code now, but we have to add something ourselves to it. Usually a bow's texture changes as you draw it back but that code is all inside of EntityPlayer, which is a huge base file that we don't want to edit because then your mod doesn't work with a lot other mods. There is a way around this though that we can do inside of our ItemFireBow. Inside of our bow's code we are going to update the texture based on what state the bow is in. Unfortunately, it means that when you are holding and using your bow it changes the texture of every single instance of that bow in your inventory. It can look silly sometimes, but I prefer it to not having a changing animation. You can skip this if you choose. We're going to create a new method that is called for our item every single tick in game (20 ticks per second) inside of which it will change it's texture if it needs to.
Now we're going to start adding code to the above method to accomplish what we want. This part converts the Entity that the method gives us into EntityPlayer so that we can use it in some code. It then checks to see if the player is A: using an item and B: holding the bow because we only want to change the texture if the bow is actually being used.
Now we can add the actual code for changing textures into the above if function. This is nearly the same as the code that calculates the changing textures for the default bow. It checks the difference between the item's max use time and how long the player has been using it for and then changes the texture based on that difference.
However we need to define these values that we are referring it to inside of our mod_ file so we need to add this to our mod_ file outside of the load() method.
Now we have to create the actual arrow that our new bow is firing. Start out with a new EntityFireArrow and copy all code from EntityArrow. First thing we need to do is change all instances of EntityArrow to EntityFireArrow. Now we can start changing things in it. First thing is to find this method and then delete it entirely. Since this bow is "conjuring" up a fire arrow we don't want the player to pick up an arrow from this.
The next thing we want to add is the code to light the ground on fire. Inside the onUpdate method find the part where it says if(inGround). In the beginning of that if function add the following code. The first part determines what block the arrow is on based on the arrows coordinates. Then it checks that the block it is in is air (we don't want to turn water into fire) and if it is it sets that block to fire. It also sets the entity to dead because we don't want our arrow sticking around after we've lit the ground on fire.
Now we also want our fire arrow to look fiery so let's add some particles to it. Find the very end of the method onUpdate and add the following code. This creates a new flame particle where the arrow is and gives it a small amount of reverse motion.
Leaving a trail of fire and lighting the ground on fire isn't good enough for me. I want it to light mobs on fire too, so find the following if function inside of onUpdate and make it look like this. The line we added will set the entity that it hits on fire for 6 total points of fire damage. Change the number at the end to whatever you want.
Now we're almost done with this file but one last part will give us an error unless we change it. Find both places within the code (they should be next to each other) that say "DamageSource.causeArrowDamage" and change it to "causeFireArrowDamage". Now that we told it to refer to a different method, we have to create this new method. So anywhere inside of your EntityFireArrow class add the following method.
Now we're almost finished. The last file we need to create is RenderFireArrow so that we can actually see it in game rather than just a white blob. Copy all the code from RenderArrow and change any instance of Arrow to FireArrow and arrow to firearrow (watch your capitals!). Also inside of this file is the code that tells it what texture to load. Simply change it to our texture like so, with no ModLoader code needed.
The last thing we need to do is tell the game that our new RenderFireArrow file goes with our EntityFireArrow which we do through ModLoader. Inside your mod_ file add this line just below the package statement.
And somewhere outside of load() place this new method which relates our render file to our entity file.
That should be the last of it. If anything isn't working for you just post and I'll help where I can. The final versions of all the files are below.
mod_Tutorial
Your mod_* file should look the same as any other that adds an item so I won't bother explaining it.
For our actual item I'm going to first show the part that gives our item a cooldown whenever we use it. The way we do that is using damage on an item, and it's fairly simple to do. Just like any other item we need to declare that our item can take damage by setting its max damage in the constructor. Whatever you choose to set that to, divide it by 20 and that is how many seconds it takes to recharge before you can use it again.
Now we want to set it so that the item will only perform its function whenever it's damage is at 0 (it's fully recharged) so we do that with a simple if statement. Then when it is used, we set the damage of the item to one less than max (max would break the item) so that it is fully on cooldown. This is also where we will add our code later to spawn lightning where the player is looking.
This is how we make our item actually recharge. Everytime the game ticks this item will reduce it's damage by one, but only if it is above 0 in order to avoid having an item with negative damage. This onUpdate method is called 20 times every second which is why 99 damage would be approximately 5 seconds.
Now our item should have a full red durability bar on use and then recharge over several seconds. Next step is to add the code to find where the player is looking and then spawn lightning. Everything we're adding next goes inside the if function inside of the onItemRightClick method.
Now this is where the magic happens. The very first part references a method inside of EntityLiving which does the very complicated math for us and returns something called a MovingObjectPosition which we can get a plethora of info from (like coordinates, or if you selected a monster). The value '75.0D' is the maximum distance away that this will work, so change that to whatever max range you want your item to have. The if function that checks if our MovingObjectPosition is null is needed because if there was no block/entity within our maximum distance than it will have a null value, and if we try to do something with our null value the game will get upset with us and crash. If you happen to be doing this in a piece of code that doesn't provide an instance of EntityPlayer then see the spoiler below.
Now we can start pulling information from that MovingObjectPosition. First we convert it to a 3d vector which we can get the actual coordinates from, then we get the x, y and z coordinates of that. Those are specific coordinates (to the decimal) of where we will spawn our entity, but a decimal value can't be used as a block coordinate. The final three lines here convert those doubles into integers that are basically rounded off to the nearest block.
Personally I decided to run another check here to only spawn the lightning bolt if it has a view of the sky (lightning in caves, anyone?) but you can choose to not add this part if you want. This part is very self-explanatory, and it is why we needed to convert to block coordinates above.
Now we actually spawn the lightning bolt if the code has made it all three of the checks so far. Spawning a lightning bolt is the same as spawning any other entity, such as a creeper, and we do so using those specific coordinates we got above. If you use the i, j, k rounded off values then it will be in the corner of whatever block you look at.
Also, would you perhaps know how to make a block use a Custom model? I want to make just a campfire. I have the model for it, I just don't know how to implement it. All I want is just a nice campfire, that doesn't set **** on fire, maybe emits fire and smoke particles and just glows like a torch. Could you help me out ?
I haven't tried any custom block rendering yet but there is a good tutorial on it here.
I still think I wrote too much but I guess you can skim over most of it if you already know it. If anyone has any ideas for other tutorials they would like, I'm open to hear them. I don't see the point in rehashing the same tutorials that everyone has done over and over.
anyone know how to make this work?
also, how do you set a damage for a specific bow? i see durability, but no mention of how hard it'll hit.
As to why your code isn't working, I have no idea. So it doesn't return any recompile errors?
I'm not entirely sure what you mean. Are you asking if I can basically get it to only change texture in your hand, like the regular bow, without modifying EntityPlayer?
Also, would anyone want a tutorial on how to get where the player is looking at? I would do it in the context of an example of how to summon lightning where the player is looking.
i wasn't aware it was based on arrows, i could try making tiered arrows that only work with specific bows i suppose
none. i've tried dozens of different things, the bow just pulls back slightly as if that bit of code wasn't even there. to verify: image1-4, 1 is default and 4 is max pullback? 2 and 3 being the other images found in the /gui/items file?
I found that the image 1 referred to in your onUpdate code has to be a different file than the defile image. If they aren't different copies of the same image it doesn't work.
this still returns nothing, perhaps the error lays somewhere else in my item file?
kind of embarrassing not being able to figure out something so simple :sad.gif:
Any clue whats wrong?
It's fairly complicated to change the shape it's rendering. If you can understand the RenderArrow file then feel free to play with the shape but otherwise I recommend you just use a different texture and have some empty space when it renders.
Is this wanted?
Did I help you? There's a little white plus down the bottom. I hope your confused!
Now, I tryed by myself, didn't work. 25 errors.
now I tryed your code and I've got this:
Any idea what's wrong?
help please :sad.gif: