You could use IExtendedEntityProperties to add in an attack cooldown for the player, then use events to reduce or cancel damage from your heavy weapons when it hasn't fully recharged.
This is the most comprehensive way of achieving an attack cooldown. In fact, with a custom HUD you could make something pretty much identical to the 1.9 combat mechanics. It's not the easiest thing to do, but I would encourage you to have a go. IExtendedEntityProperties is a very useful tool anyway.
But as a tip for the spam clicking hammer, you could always call onUpdate() on your hammer and if it isSelected, you can create a mining fatigue potion effect preferably or a slowness effect. That might help you with one of the problems.
This is a simpler way of doing it, but I'm not 100% sure if mining fatigue affects attacks so give yourself mining fatigue in game and test it out first.
The first method is probably better and more flexible, but if you're having trouble with it the second way is easier to code.
See how far you can get with those, and ask if you need any pointers.
Edit: Just thought, there is a BreakSpeedEvent if I remember correctly. You could try doing a similar thing to the shortened reach: make a method in your event handler to handle that event, make an IAttackSpeed interface with a getSpeed method and have your hammer implement it, then in the event check if the player is holding an IAttackSpeed item and if so set event.newSpeed to the speed for that item.
Of course, both this and the mining fatigue method will cause the hammer to break blocks more slowly, whereas the first method will not - but you might want that, it's your decision!
The Meaning of Life, the Universe, and Everything.
Location:
Colorado
Join Date:
3/27/2016
Posts:
208
Location:
Colorado
Minecraft:
ProfessorOro
Discord:
gargatheoro
PMC:
GargatheOro
Member Details
I am attempting to create a modified version of shortened reach where it gets the speed of the item from IAttackSpeed getSpeed float in the weapons, check. Then if it hasn't been enough time, it cancels the event. I do not know how to do one thing: I can set something like this up: if (attacker.getDistanceToEntity(event.entity) > reach) { if (attacker.getDistanceToEntity(event.entity) > reach) { event.setCanceled(true);
Except I replace the reach with speed, but what do I put on the other side of the >?
EDIT: Figured it out somewhat - I need to put a timeSinceLastAttacked thing on there. Is there a preexisting method for that? If not, how do I go about creating it so it records the last time they dealt damage or drew the weapon? Note: The drew the weapon would be optimal so people aren't constantly swapping sword hammer and some other weapon for spam damage.
No, you'll have to use IExtendedEntityProperties to add a variable to the player which keeps track of the time since they last attacked. Have a look at this tutorial by CoolAlias, it explains how to use IExtendedEntityProperties to add data to players and other entities.
Alternatively, you could use the datawatcher to achieve the same result. In your case that might not be a bad idea because the variable will need updating often, just be aware that the datawatcher has limited space. The choice is yours.
Either way, the basic idea would be to add a cooldown variable which decrements by 1 each tick, then whenever you attack with or equip an IAttackSpeed weapon, set that variable to getSpeed. Then you can just cancel the event when the cooldown is greater than 0.
The Meaning of Life, the Universe, and Everything.
Location:
Colorado
Join Date:
3/27/2016
Posts:
208
Location:
Colorado
Minecraft:
ProfessorOro
Discord:
gargatheoro
PMC:
GargatheOro
Member Details
I am lost. I implemented the method pretty well I think, but how do I pull the time since last attacked? How do I get that data?
package com.GargatheOro.LichlandCore;package com.GargatheOro.LichlandCore;
import net.minecraft.entity.Entity;import net.minecraft.entity.player.EntityPlayer;import net.minecraft.nbt.NBTTagCompound;import net.minecraft.world.World;import net.minecraftforge.common.IExtendedEntityProperties;
public class ExtendedPlayer implements IExtendedEntityProperties {
public final static String EXT_PROP_NAME = "PlayerLastAttacked";
private final EntityPlayer player;
private float lastAttacked;
public ExtendedPlayer(EntityPlayer player) { this.player = player; this.lastAttacked = 0; }
public static final void register(EntityPlayer player) { player.registerExtendedProperties(ExtendedPlayer.EXT_PROP_NAME, new ExtendedPlayer(player)); }
public static final ExtendedPlayer get(EntityPlayer player) { return (ExtendedPlayer) player.getExtendedProperties(EXT_PROP_NAME); }
@Override public void saveNBTData(NBTTagCompound compound) { // We need to create a new tag compound that will save everything for our // Extended Properties NBTTagCompound properties = new NBTTagCompound();
// We only have 2 variables currently; save them both to the new tag properties.setFloat("lastAttacked", this.lastAttacked); compound.setTag(EXT_PROP_NAME, properties); }
@Override public void loadNBTData(NBTTagCompound compound) { NBTTagCompound properties = (NBTTagCompound) compound.getTag(EXT_PROP_NAME); this.lastAttacked = properties.getFloat("lastAttacked"); }
@Override public void init(Entity entity, World world) { } }
The Meaning of Life, the Universe, and Everything.
Location:
Colorado
Join Date:
3/27/2016
Posts:
208
Location:
Colorado
Minecraft:
ProfessorOro
Discord:
gargatheoro
PMC:
GargatheOro
Member Details
Summary of help needed:
How to convert regular seconds into ticks
How to record time since last attacked using IExtendedEntityProperties or datawatcher (Whichever is easier and effective enough to support cooldowns of 5 seconds or less)
Pretty sure I got everything else taken care of though.
2. Now I think about it, IExtendedEntityProperties is the way to go because you don't need to sync the cooldown with the client, unless you are planning on making a HUD for it. You've done the hard work, there are just a few other things to add:
Make lastAttacked public.
Add a new method in your ExtendedPlayer class:
public void update(){
if(lastAttacked > 0) lastAttacked--;
}
Add a PlayerTickEvent handler method in your event handler. Inside, put this:
// Retrieve the ExtendedPlayer instance for this player
ExtendedPlayer properties = ExtendedPlayer.get(event.player);
// Check it actually exists
if(properties != null){
// If so, update it
properties.update();
}
You could just do the updating directly in your event handler, but I like to use an update method because it keeps the event handler neater when you add more stuff to it. Now in your handler method for LivingAttackEvent, put the following:
if(event.source.getEntity() instanceof EntityPlayer){
EntityPlayer player = (EntityPlayer)event.source.getEntity();
// Retrieve the ExtendedPlayer instance for this player
ExtendedPlayer properties = ExtendedPlayer.get(player);
// Check it actually exists
if(properties != null){
// Test whether the cooldown is done yet
if(properties.lastAttacked > 0){
// If the cooldown hasn't finished, cancel the attack
event.setCanceled(true);
return;
}
// Test whether the player's held item is an IAttackSpeed
if(player.getHeldItem() != null && player.getHeldItem().getItem() instanceof IAttackSpeed){
// If so, set the attack cooldown
properties.lastAttacked = ((IAttackSpeed)player.getHeldItem().getItem()).getSpeed();
}
}
}
You might have bits of this already written from when you did shortened reach.
Hopefully that will work, and hopefully you can also see what's going on in those bits of code.
The Meaning of Life, the Universe, and Everything.
Location:
Colorado
Join Date:
3/27/2016
Posts:
208
Location:
Colorado
Minecraft:
ProfessorOro
Discord:
gargatheoro
PMC:
GargatheOro
Member Details
After a pause of coding, I have gotten all the above done. But one thing is still missing. It will not work because, and I predict that the getSpeed 40.0F doesn't know that it is supposed to wait 40 ticks to attack. The properties needs something that will register the ticks since last attacked. I just don't know how.
Took a while to look at this thread, but looks neat, I hope you fix your mod problems. I currently don't know how to help so sorry. I'm just here to support people atm.
Yes, that is exactly what's happening. I can't see anything in your CommonHandler that calls ExtendedPlayer's update method - you need to have a handler for PlayerTickEvent like I said earlier, with something like this inside it:
// Retrieve the ExtendedPlayer instance for this player
ExtendedPlayer properties = ExtendedPlayer.get(event.player);
// Check it actually exists
if(properties != null){
// If so, update it
properties.update();
}
Ah, sorry, I must have missed that. However, it's missing the @SubscribeEvent annotation, which means the event won't be fired.
Thread.sleep(...) will freeze your entire game for the amount of time you specify! If you want to delay things, you have to count ticks, which is what you're doing in ExtendedPlayer.update().
The Meaning of Life, the Universe, and Everything.
Location:
Colorado
Join Date:
3/27/2016
Posts:
208
Location:
Colorado
Minecraft:
ProfessorOro
Discord:
gargatheoro
PMC:
GargatheOro
Member Details
It dont work still
Edit: I dont see anywhere where it actually is supposed to turn IAttackSpeed into ticks and count them. Am I missing this?
Edit 2: My dad asked me how you did your spell cooldowns, if it would work the same way for weapons or at least the tick timing. Perhaps that might help.
The Meaning of Life, the Universe, and Everything.
Location:
Colorado
Join Date:
3/27/2016
Posts:
208
Location:
Colorado
Minecraft:
ProfessorOro
Discord:
gargatheoro
PMC:
GargatheOro
Member Details
Now it's acting like I am attacking with my fists. I really hope something didn't break. It started after I added your Wizardry Mod deobf and source to my mod libraries I removed them and my project has a big red ! on it, and there are no errors within the classes. Is something wrong with my mod?
Sometimes eclipse bugs out and displays the red ! even though it shouldn't be there any more. If there are no red ! icons on any of your packages it's probably fine, and it'll go away at some point.
If not I have no idea what's happening, but if you go to Window > Show View > Problems it will show you a list of the errors in the project.
I know this mod adds that, but I do not have the prerequisite knowledge to read that code. I am still learning so it looks like jumble to me.
https://github.com/Ckathode/balkons-weaponmod/tree/master/src/main/java/ckathode/weaponmod/item
An SF Towny server! Join our Discord: Click here
Have a look at the first page of this thread:
This is the most comprehensive way of achieving an attack cooldown. In fact, with a custom HUD you could make something pretty much identical to the 1.9 combat mechanics. It's not the easiest thing to do, but I would encourage you to have a go. IExtendedEntityProperties is a very useful tool anyway.
This is a simpler way of doing it, but I'm not 100% sure if mining fatigue affects attacks so give yourself mining fatigue in game and test it out first.
The first method is probably better and more flexible, but if you're having trouble with it the second way is easier to code.
See how far you can get with those, and ask if you need any pointers.
Edit: Just thought, there is a BreakSpeedEvent if I remember correctly. You could try doing a similar thing to the shortened reach: make a method in your event handler to handle that event, make an IAttackSpeed interface with a getSpeed method and have your hammer implement it, then in the event check if the player is holding an IAttackSpeed item and if so set event.newSpeed to the speed for that item.
Of course, both this and the mining fatigue method will cause the hammer to break blocks more slowly, whereas the first method will not - but you might want that, it's your decision!
I am attempting to create a modified version of shortened reach where it gets the speed of the item from IAttackSpeed getSpeed float in the weapons, check. Then if it hasn't been enough time, it cancels the event. I do not know how to do one thing: I can set something like this up: if (attacker.getDistanceToEntity(event.entity) > reach) { if (attacker.getDistanceToEntity(event.entity) > reach) { event.setCanceled(true);
Except I replace the reach with speed, but what do I put on the other side of the >?
EDIT: Figured it out somewhat - I need to put a timeSinceLastAttacked thing on there. Is there a preexisting method for that? If not, how do I go about creating it so it records the last time they dealt damage or drew the weapon? Note: The drew the weapon would be optimal so people aren't constantly swapping sword hammer and some other weapon for spam damage.
An SF Towny server! Join our Discord: Click here
No, you'll have to use IExtendedEntityProperties to add a variable to the player which keeps track of the time since they last attacked. Have a look at this tutorial by CoolAlias, it explains how to use IExtendedEntityProperties to add data to players and other entities.
Alternatively, you could use the datawatcher to achieve the same result. In your case that might not be a bad idea because the variable will need updating often, just be aware that the datawatcher has limited space. The choice is yours.
Either way, the basic idea would be to add a cooldown variable which decrements by 1 each tick, then whenever you attack with or equip an IAttackSpeed weapon, set that variable to getSpeed. Then you can just cancel the event when the cooldown is greater than 0.
Hope that helps!
Yes it does! Thank you.
An SF Towny server! Join our Discord: Click here
I am lost. I implemented the method pretty well I think, but how do I pull the time since last attacked? How do I get that data?
package com.GargatheOro.LichlandCore;package com.GargatheOro.LichlandCore;
import net.minecraft.entity.Entity;import net.minecraft.entity.player.EntityPlayer;import net.minecraft.nbt.NBTTagCompound;import net.minecraft.world.World;import net.minecraftforge.common.IExtendedEntityProperties;
public class ExtendedPlayer implements IExtendedEntityProperties {
public final static String EXT_PROP_NAME = "PlayerLastAttacked";
private final EntityPlayer player;
private float lastAttacked;
public ExtendedPlayer(EntityPlayer player) { this.player = player; this.lastAttacked = 0; }
public static final void register(EntityPlayer player) { player.registerExtendedProperties(ExtendedPlayer.EXT_PROP_NAME, new ExtendedPlayer(player)); }
public static final ExtendedPlayer get(EntityPlayer player) { return (ExtendedPlayer) player.getExtendedProperties(EXT_PROP_NAME); }
@Override public void saveNBTData(NBTTagCompound compound) { // We need to create a new tag compound that will save everything for our // Extended Properties NBTTagCompound properties = new NBTTagCompound();
// We only have 2 variables currently; save them both to the new tag properties.setFloat("lastAttacked", this.lastAttacked); compound.setTag(EXT_PROP_NAME, properties); }
@Override public void loadNBTData(NBTTagCompound compound) { NBTTagCompound properties = (NBTTagCompound) compound.getTag(EXT_PROP_NAME); this.lastAttacked = properties.getFloat("lastAttacked"); }
@Override public void init(Entity entity, World world) { } }
An SF Towny server! Join our Discord: Click here
Summary of help needed:
Pretty sure I got everything else taken care of though.
An SF Towny server! Join our Discord: Click here
1. 20 ticks = 1 second
2. Now I think about it, IExtendedEntityProperties is the way to go because you don't need to sync the cooldown with the client, unless you are planning on making a HUD for it. You've done the hard work, there are just a few other things to add:
Make lastAttacked public.
Add a new method in your ExtendedPlayer class:
Add a PlayerTickEvent handler method in your event handler. Inside, put this:
You could just do the updating directly in your event handler, but I like to use an update method because it keeps the event handler neater when you add more stuff to it. Now in your handler method for LivingAttackEvent, put the following:
You might have bits of this already written from when you did shortened reach.
Hopefully that will work, and hopefully you can also see what's going on in those bits of code.
After a pause of coding, I have gotten all the above done. But one thing is still missing. It will not work because, and I predict that the getSpeed 40.0F doesn't know that it is supposed to wait 40 ticks to attack. The properties needs something that will register the ticks since last attacked. I just don't know how.
An SF Towny server! Join our Discord: Click here
Took a while to look at this thread, but looks neat, I hope you fix your mod problems. I currently don't know how to help so sorry. I'm just here to support people atm.
Thank you. Tell me if you need help with modding ever. I know some things still
An SF Towny server! Join our Discord: Click here
The code I gave you should work... Could you update your github repository? Also, check you're registering your ExtendedPlayer.
It all works now, except when I attack once, it won't let me attack. I set the cooldown to 1.5F.
I don't think the time goes down once it is set.
Here is the updated repository: https://github.com/ArIlIlI/Modern-Mod
An SF Towny server! Join our Discord: Click here
Yes, that is exactly what's happening. I can't see anything in your CommonHandler that calls ExtendedPlayer's update method - you need to have a handler for PlayerTickEvent like I said earlier, with something like this inside it:
public void ElectRequest(PlayerTickEvent event) {public void ElectRequest(PlayerTickEvent event) { ExtendedPlayer properties = ExtendedPlayer.get(event.player); if(properties != null){ properties.update(); } }
I had it in there. In the common handler
Could
Thread.sleep(5000);or something like it work? If so, where would it go?[/pre]
An SF Towny server! Join our Discord: Click here
Ah, sorry, I must have missed that. However, it's missing the @SubscribeEvent annotation, which means the event won't be fired.
Thread.sleep(...) will freeze your entire game for the amount of time you specify! If you want to delay things, you have to count ticks, which is what you're doing in ExtendedPlayer.update().
It dont work still
Edit: I dont see anywhere where it actually is supposed to turn IAttackSpeed into ticks and count them. Am I missing this?
Edit 2: My dad asked me how you did your spell cooldowns, if it would work the same way for weapons or at least the tick timing. Perhaps that might help.
An SF Towny server! Join our Discord: Click here
Now it's acting like I am attacking with my fists. I really hope something didn't break. It started after I added your Wizardry Mod deobf and source to my mod libraries I removed them and my project has a big red ! on it, and there are no errors within the classes. Is something wrong with my mod?
An SF Towny server! Join our Discord: Click here
Someone please help.
An SF Towny server! Join our Discord: Click here
Sometimes eclipse bugs out and displays the red ! even though it shouldn't be there any more. If there are no red ! icons on any of your packages it's probably fine, and it'll go away at some point.
If not I have no idea what's happening, but if you go to Window > Show View > Problems it will show you a list of the errors in the project.