Jump to content

Make player not hit during Attack cooldown


BliX5

Recommended Posts

I’ve made an event so the player can’t damage entities during an attack cooldown, but whenever the player hits during a cooldown, it resets. How can I stop this from happening and make it so the player can’t punch at all? 

Link to comment
Share on other sites

Here's my code so far:

    @SubscribeEvent
    public static void onPlayerHit(final AttackEntityEvent event) {
        if(event.getPlayer().getCooledAttackStrength(0) < 1.0F) {
            event.setCanceled(true);
        }
    }

I want to make it so while on cooldown, the player cannot hit at all. With this code, the player can still hit, but it doesn't do damage to entities. Is there any other event I can use to cancel the left click entirely?

Link to comment
Share on other sites

7 hours ago, diesieben07 said:

AttackEntityEvent.

However note that if you cancel this, the attack timer will still count on the client. To avoid this, you can additionally cancel InputEvent.ClickInputEvent on the client. That alone is not enough, because it could be easily bypassed using cheating.

I tried it, but it doesn't work about half of the time. Is there a way to add some sort of delay between the events so the a value is recorded before onClickEvent is put into action?

    public static float a = 1;

    @SubscribeEvent
    public static void onPlayerHit(final AttackEntityEvent event) {
        ModClientEvents.a = event.getPlayer().getCooledAttackStrength(0);
        if(ModClientEvents.a < 1) {
            event.setCanceled(true);
            ModClientEvents.a = 1;
        }
    }

    @SubscribeEvent
    public static void onClickEvent(final InputEvent.ClickInputEvent event) {
        if(ModClientEvents.a < 1) {
            event.setCanceled(true);
            ModClientEvents.a = 1;
        }
    }

 

Edited by BliX5
Link to comment
Share on other sites

I tried to fix more of the code, and I got it to work most of the time, but it's still incredibly buggy. 

 

ModServerEvents:

@Mod.EventBusSubscriber(modid = BotwMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class ModServerEvents {

    public static float a;

    @SubscribeEvent
    public static void onPlayerHit(final AttackEntityEvent event) {
        ModServerEvents.a = event.getPlayer().getCooledAttackStrength(0);
        BotwMod.LOGGER.debug(String.valueOf(ModServerEvents.a) + " onPlayerHit");
        if(ModServerEvents.a < 1) {
            event.setCanceled(true);
        }
    }

    @SubscribeEvent
    public static void onClickEvent(final InputEvent.ClickInputEvent event) {
        BotwMod.LOGGER.debug(String.valueOf(ModServerEvents.a) + " onClickEvent");
        if(ModServerEvents.a < 1) {
            event.setCanceled(true);
        }
        ModServerEvents.a = 1;
    }

}

 

Main Class:

MinecraftForge.EVENT_BUS.register(this);
        MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGHEST, ModServerEvents::onPlayerHit);
        MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, ModServerEvents::onClickEvent);

 

Link to comment
Share on other sites

7 hours ago, diesieben07 said:

You cannot do this. There is more than one player, and this value would be shared between all of them. Additionally, in single player, this value would be shared between client and server thread, without proper synchronization.

 

Additionally, it seems you have not read my message in full. ClickInputEvent is a client-only event.

I've moved the ClickInputEvent to my client events and I've fixed the values. The problem now is that the method onClickEvent is running before onPlayerHit, which delays whether the hit is cancelled or not for the next left click, despite how I set the events' priority in my main class.

Link to comment
Share on other sites

Main Class:

@Mod("botw")
public class BotwMod
{
    public static final Logger LOGGER = LogManager.getLogger();
    public static final String MOD_ID = "botw";

    public BotwMod() {
        IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
        bus.addListener(this::setup);

        ModBlocks.BLOCKS.register(bus);
        ModItems.ITEMS.register(bus);
        ModEntityTypes.ENTITY_TYPES.register(bus);

        MinecraftForge.EVENT_BUS.register(this);

        MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGHEST, ModServerEvents::onPlayerHit);
        MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, ModClientEvents::onClickEvent);
    }

    private void setup(final FMLCommonSetupEvent event) {
        DeferredWorkQueue.runLater(() -> { });
    }

    private void doClientStuff(final FMLClientSetupEvent event) { }

 

ModClientEvents:

@Mod.EventBusSubscriber(modid = BotwMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
public class ModClientEvents {

    public static float a = 1;

    @SubscribeEvent
    public static void onClickEvent(InputEvent.ClickInputEvent event) {
        BotwMod.LOGGER.debug("ModClientEvents"); //used for debugging
        if(event.isAttack()) {
            if(ModClientEvents.a < 1) {
                ModClientEvents.a = 1;
                event.setCanceled(true);
            }
        }
    }

}

 

ModServerEvents:

@Mod.EventBusSubscriber(modid = BotwMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class ModServerEvents {

    @SubscribeEvent
    public static void onPlayerHit(AttackEntityEvent event) {
        BotwMod.LOGGER.debug("ModServerEvents"); //used for debugging
        ModClientEvents.a = event.getPlayer().getCooledAttackStrength(0);
    }

}

 

Link to comment
Share on other sites

20 minutes ago, diesieben07 said:

The two events do not need to interact at all. Just cancel both of them when it is relevant.

I need the AttackEntityEvent to determine when the player is on attack cooldown or not, unless there is another way to access that.

Link to comment
Share on other sites

2 minutes ago, diesieben07 said:

How is the event relevant to how you call a method?

Before when I called getCooledAttackStrenght, I was using AttackEntityEvent to call it. 

@SubscribeEvent
    public static void onPlayerHit(AttackEntityEvent event) {
        if(event.getPlayer().getCooledAttackStrength(0) < 1.0F) {
            event.setCanceled(true);
        }
    }

I couldn't find a way to call this method again with ClickInputEvent without my game crashing.

Link to comment
Share on other sites

9 minutes ago, diesieben07 said:

Show what you tried that crashed the game.

@SubscribeEvent
public static void onClickEvent(InputEvent.ClickInputEvent event, Entity entityIn) {
    PlayerEntity player = (PlayerEntity)entityIn;
    if(event.isAttack()) {
        if(player.getCooledAttackStrength(0) < 1) {
            event.setCanceled(true);
        }
    }
}

Pretty sure this doesn't work because events shouldn't have any other parameters, but this is the only way I could think of calling it. 

Link to comment
Share on other sites

Thanks, it works now! Here's my final code:

@SubscribeEvent
public static void onClickEvent(InputEvent.ClickInputEvent event) {
    PlayerEntity player = Minecraft.getInstance().player;
    if(event.isAttack()) {
        if(player.getCooledAttackStrength(0) < 1) {
            event.setCanceled(true);
        }
    }
}
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.