1.8.8 How do i make a custom damage event?

Discussion in 'Spigot Plugin Development' started by Stitchie, Jun 13, 2021.

  1. I want to make a custom damage event called PlayerHitEvent. Its called if two players hit each other and it has the damager, damaged (as Players) and damage value as double. Now my problem is that when i change the damage from the EntityDamageByEntityEvent (the bukkit event) then it actually reflects the damage change ingame, aka when i get 2 damage and i multiply the damage of that event by 2 then i actually get 4 damage ingame. However when i call my custom PlayerHitEvent nothing happens ingame when i change the damage value of it. Of course i understand why it happens but i don't understand how i would get it to work like the bukkit event. What is the difference between bukkit's events and custom events? How can i connect my events to actually reflect ingame events? Or alternatively how can i get back the damage from the PlayerHitEvent and set it as the damage of the real event. Or is there a better way? Please help. Btw currently im extending the Event Class in PlayerHitEvent and not the EntityDamageByEntityEvent. Would it work if i extended the EntityDamageByEntityEvent Class instead of the Event Class? Thanks.
     
    • Agree Agree x 1
  2. He usually gives useless answers like that.

    can you show your current code?
     
    • Like Like x 1
    • Agree Agree x 1
  3. I don't have anything in particular to show. Like it's pretty simple, if i have a custom event with a damage variable then surprisingly it doesn't actually change the damage of the event ingame. In other words i want the functionality of the entitydamagebyentityevent that it has ingame but for my custom event. So if i change the damage, it actually changes the damage of the attack ingame, you get it? So far i tried extending the Event Class, the EntityDamageByEntityEvent class, i tried using the super methods from it like setDamage but nothing worked.

    Code (Java):
        @EventHandler(priority = EventPriority.LOW)
        private void onEntityHit(final EntityDamageByEntityEvent event) {
            final Entity damager = event.getDamager();
            final Entity damaged = event.getEntity();
            final double damage = event.getFinalDamage();

            if (damager instanceof Player && damaged instanceof Player) {
                final PlayerHitEvent playerHitEvent = new PlayerHitEvent((Player) damager, (Player) damaged, damage, event.getCause());
                Bukkit.getServer().getPluginManager().callEvent(playerHitEvent);
            }
        }

        @EventHandler
        private void onPlayerHit(final PlayerHitEvent event) {
            event.addDamage(10, DamageType.ADDITIVE);
            Bukkit.broadcastMessage("PlayerHitEvent registered.");
        }
    This is the code from my random listener class to test it.
     
  4. Can you also show your PlayerHitEvent class? From what I see right now, it shouldn't do anything when modifying the PlayerHitEvent because you do not update the values in the original event.
     
    • Optimistic Optimistic x 1
  5. I know. How do i make my custom event behave like original bukkit events?? I just tried this but i know it shouldn't work.
    Code (Java):
    public class PlayerHitEvent extends EntityDamageByEntityEvent implements Cancellable {

        private static final HandlerList handlers = new HandlerList();
        private boolean cancelled;
        private final Player damager;
        private final Player damaged;
        private double damage;

        public PlayerHitEvent(final Player damager, final Player damaged, final double damage, final DamageCause cause) {
            super(damager, damaged, cause, damage);
            this.damager = damager;
            this.damaged = damaged;
            this.damage = damage;
        }

        public void addDamage(final double amount, final DamageType type) {
            if (type == DamageType.MULTIPLICATIVE) {
                super.setDamage(this.damage *= amount);
            } else {
                super.setDamage(this.damage += amount);
            }
        }

        @Override
        public HandlerList getHandlers() {
            return handlers;
        }

        public static HandlerList getHandlerList() {
            return handlers;
        }
    The only way to do it would be to inject the original event instance into this class and modify that instead would be my guess.
     
  6. The problem is that you never set back the damage to the players. Sure you update the variables in your event, but those are not linked to the players. What Spigot does (internally, by having edited the source code using patches) is read out the values of the event after it has happened and apply those to the parties that have changed. Currently you are not even able to get those values from your event, so I would start with adding a couple of getters.

    After you have done that, you can get the final damage from your own event by doing something like playerHitEvent.getDamage() after you have called the event. Now you can set the damage from the EntityDamageByEntityEvent to this value and Spigot will make sure that after its event is done, it actually changes the health values of the players. Alternatively, you could cancel the EntityDamageByEntityEvent and use the damage from your PlayerHitEvent to damage the players with, but I don't see any benefits with this.
     
    • Agree Agree x 1
  7. You are trying to create an eventhandler within an eventhandler which isn't possible. How would i get the playerhitevent inside of the entitydamageevent? The only real solution i found is by adding the entitydamageevent as a field in my playerhitevent so i can directly modify the event. Also i know what a getter is i just didn't add one yet.. I use lombok usually.
     
    • Funny Funny x 1
  8. Strahan

    Benefactor

    You don't create an eventhandler in an eventhandler, you trigger it. You have to; how else is the system to know when you fire your event unless you make your own custom Spigot?

    Personally, I don't see the need really. What you describe of your custom event's parameters could be accomplished with the default event and a simple guard clause. If it was something really specific, maybe I could see it, but all you are doing is saving yourself one line of code vs the default event.
     
  9. Obviously I am not. You say you know what a getter is, your question says otherwise. You get the damage by using said getter ;).

    In your onEntityHit event, you need you set the damage to that of your custom event, using a getter (or Lombok). You can do this like so:
    Code (Java):
    final PlayerHitEvent playerHitEvent = new PlayerHitEvent((Player) damager, (Player) damaged, damage, event.getCause());
    Bukkit.getServer().getPluginManager().callEvent(playerHitEvent);
    event.setDamage(playerHitEvent.getDamage()); // this does exactly what I mentioned above