Jump to content

Weapon Attributes (Attack Speed, Less Knockback on hitting, initial fire, etc)?


Psychocrysma

Recommended Posts

Hi there! I'm new here, on both modding and on this forum. I don't have experience in Java programming (though I am quite experienced in C#)

 

Anyway, to get to the point, I've been trying to make a weapon that would have a decreased knockback (less than normal) and a Speed bonus that, for example, decrease the number of ticks between each hit. Though I don't really need it, I would also like to know about fire aspect without the enchant, which I think I have once seen in Netherrocks.

 

So, here's what I've tried to do using different resources (this forum post: http://www.minecraftforge.net/forum/index.php?topic=19914.0) and the decompilation of the Balkon Weapons Mod. All I've tried doesn't work.

AttackSpeed.class

import java.util.List;

import net.minecraft.item.ItemStack;

public class AttackSpeed
{
public static final String SPEED_NBT = "data:speed";
//20 ticks = 1 second

/**
 * Call this onUpdate() in your Item WARNING: you should check for
 * !world.isRemote
 * 
 * @param iStack
 *            stack to update
 * @param maxCooldown
 *            maximum speed
 */
public static void onUpdate(ItemStack iStack, int maxSpeed){
	DataHelper.checkNBT(iStack);
	if(!DataHelper.verifyKey(iStack, SPEED_NBT)){
		DataHelper.setInteger(iStack, SPEED_NBT, maxSpeed);
	}
	if(DataHelper.getInteger(iStack, SPEED_NBT) > 0){
		DataHelper.decreaseInteger(iStack, SPEED_NBT, 1);
	}
}

/**
 * Checks for speed. Call it when your item needs to be used
 * 
 * @param iStack
 *            Stack to check
 * @param maxCooldown
 *            Maximum speed
 * @return True if item's speed is zero, returns true and sets it to
 *         maximum, otherwise false
 */
public static boolean canUse(ItemStack iStack, int maxSpeed){
	DataHelper.checkNBT(iStack);
	if(DataHelper.getInteger(iStack, SPEED_NBT) > 0){
		return false;
	}else{
		DataHelper.setInteger(iStack, SPEED_NBT, maxSpeed);
		return true;
	}
}

/**
 * Call this addInformation() in your Item
 * 
 * @param iStack
 *            stack to update
 * @param info
 *            speed text
 */
public static void displaySpeed(ItemStack iStack, List info)
{
	DataHelper.checkNBT(iStack);
	if(DataHelper.getInteger(iStack, SPEED_NBT) > 0)
	{
		info.add("Speed: " + DataHelper.getInteger(iStack, SPEED_NBT));
	}else
	{
		info.add("Speed: " + DataHelper.getInteger(iStack, SPEED_NBT));
	}
}

}

DataHelper.class

import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;

public class DataHelper
{
/**
 * Used for null-safety
 * 
 * @param stack
 */
public static NBTTagCompound checkNBT(ItemStack stack){
	if(stack.stackTagCompound == null){
		stack.stackTagCompound = new NBTTagCompound();
	}
	return stack.stackTagCompound;
}

/**
 * Shortcut for NBTTagCompound.hasKey()
 */
public static boolean verifyKey(ItemStack stack, String name){
	return stack.stackTagCompound.hasKey(name);
}

public static void setInteger(ItemStack stack, String name, int value){
	stack.stackTagCompound.setInteger(name, value);
}

public static int getInteger(ItemStack stack, String name){
	return stack.stackTagCompound.getInteger(name);
}

public static void decreaseInteger(ItemStack stack, String name, int value){
	if(getInteger(stack, name) > 0){
		setInteger(stack, name, getInteger(stack, name) - value);
	}
}

public static void decreaseIntegerIgnoreZero(ItemStack stack, String name, int value){
	setInteger(stack, name, getInteger(stack, name) - value);
}

public static void setString(ItemStack stack, String name, String value){
	stack.stackTagCompound.setString(name, value);
}

public static String getString(ItemStack stack, String name){
	return stack.stackTagCompound.getString(name);
}

public static void setBoolean(ItemStack stack, String name, boolean value){
	stack.stackTagCompound.setBoolean(name, value);
}

public static boolean getBoolean(ItemStack stack, String name){
	return stack.stackTagCompound.getBoolean(name);
}

public static void invertBoolean(ItemStack stack, String name){
	setBoolean(stack, name, !getBoolean(stack, name));
}

public static void setByte(ItemStack stack, String name, byte value){
	stack.stackTagCompound.setByte(name, value);
}

public static byte getByte(ItemStack stack, String name){
	if(!verifyKey(stack, name)){
		setByte(stack, name, (byte)0);
	}
	return stack.stackTagCompound.getByte(name);
}
}

ItemKatanaCreation.class

import java.util.List;

import com.psychocrysma.invasionblock.AttackSpeed;
import com.psychocrysma.invasionblock.InvasionBlock;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.world.World;

public class ItemKatanaCreation extends ItemSword
{
public ItemKatanaCreation(ToolMaterial katanaMaterial)
{
	super(katanaMaterial);
	setUnlocalizedName("katanaCreation");
	setTextureName(InvasionBlock.modid + ":" + getUnlocalizedName().substring(5));
	setCreativeTab(CreativeTabs.tabCombat);
}

    public static final int SPEED = 200; // 1 sec - 20 ticks.

public void onUpdate(ItemStack iStack, World world, Entity entity, int dataInt, boolean dataBoolean)
{
	if(!world.isRemote)
	{
		AttackSpeed.onUpdate(iStack, SPEED);
	}
}

public ItemStack onItemRightClick(ItemStack iStack, World world, EntityPlayer player)
{
	if(AttackSpeed.canUse(iStack, SPEED))
	{
		player.motionY++;
	}
	return iStack;
}
}

 

I have also recovered this code, which I don't know how to use:

import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.BaseAttribute;
import net.minecraft.entity.ai.attributes.RangedAttribute;

public class WeaponAttributes extends SharedMonsterAttributes
{
public static final BaseAttribute IGNORE_ARMOR_DAMAGE = new RangedAttribute("weaponmod.ignoreArmour", 0.0D, 0.0D, 1.7976931348623157E308D);
public static final BaseAttribute WEAPON_KNOCKBACK = new RangedAttribute("weaponmod.knockback", 0.4D, 0.0D, 1.7976931348623157E308D);
public static final BaseAttribute ATTACK_SPEED = new RangedAttribute("weaponmod.attackSpeed", 0.0D, -1.7976931348623157E308D, 1.7976931348623157E308D);
public static final BaseAttribute RELOAD_TIME = new RangedAttribute("weaponmod.reloadTime", 0.0D, 0.0D, 1.7976931348623157E308D);
public static final BaseAttribute WEAPON_REACH = new RangedAttribute("weaponmod.reach", 0.0D, 0.0D, 1.7976931348623157E308D);
}

 

I hope you can help me understand something in it. I think it would be useful to lots of people :)

Link to comment
Share on other sites

The WeaponAttributes that you 'recovered' probably has a whole ton of code implementing the actual mechanics to get those things to work. Do you know how to use the various Forge Events yet? Those will go a long way in allowing custom mechanics to work in general for all mobs and players, rather than being limited to just your custom ones.

 

Fire is easy: override Item#hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) and use target.setFire(time).

 

Attack speed could be done in either of the following ways (and probably others that I haven't thought of):

1. Specifically, as in you implement it in each of your custom Item classes as a timer/cooldown (stored in the ItemStack NBT) and simply prevent the item from being used or swung, but not affecting the player/mob if they switch to a different item, OR

2. Generically, using events such as LivingAttackEvent and EntityLivingBase.attackTime or your own custom timer via IExtendedEntityProperties, in which case you can choose whether the timer affects only the specific Item used, or if no attacks can be made until the timer runs out

 

Knockback could be trickier, but you might try LivingHurtEvent and see if you can add velocity in the opposite direction (probably super buggy) or, probably a much better solution, grant the mob a temporary knockback resistance bonus (it's a SharedMonsterAttribute) when struck with your item (using Item#hitEntity from above and then LivingUpdateEvent or a tick event with a Map of affected mobs so you can remove the bonus in a timely fashion).

Link to comment
Share on other sites

Well, that was really helpful. Honestly, I haven't worked on Events in Java, so I'll try to find a way to make it work. Java is pretty much the same as C#, except for the link between classes and some code.

 

Thank you for answering. If you have some code for the timer (AttackSpeed), I'd be very grateful. I have no idea how to make a timer honestly, except if there's a variant of the "Thread.Sleep" of C# (though it would make the application temporarily stop from doing anything since it is not Asyncronous :/ )

Link to comment
Share on other sites

Well, that was really helpful. Honestly, I haven't worked on Events in Java, so I'll try to find a way to make it work. Java is pretty much the same as C#, except for the link between classes and some code.

 

Thank you for answering. If you have some code for the timer (AttackSpeed), I'd be very grateful. I have no idea how to make a timer honestly, except if there's a variant of the "Thread.Sleep" of C# (though it would make the application temporarily stop from doing anything since it is not Asyncronous :/ )

Whoa there, I'm talking about Minecraft Forge 'Events', not anything in Java; same goes for timing things - 99% of cases you don't want to use an actual Java Timer or sleep or any of that, but find methods that are called regularly (called a 'tick' in Minecraft), such as Entity#onUpdate, Item#onUpdate, etc. :P

 

If you want to learn more, you should check the many tutorials on the wiki here, The Grey Ghost's excellent blog, or for more on Forge Events / some information about various ticking methods and events, you can see my tutorial on that.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.