Check and see if damage is from arrow, if so, who shot it?

Discussion in 'Plugin Development' started by NerdsWBNerds, Mar 2, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    NerdsWBNerds

    How can I check if a players damage come from an arrow, and if it did who shot the arrow, and if it was the player, who was the player?
     
  2. to get the Shooter:
    Code:java
    1. public void onEntityShootBowzBroLol(EntityShootBowEvent event) {
    2. if(event.isCancelled()) { // We don't want to make any of our plugin-friends mad :D
    3. return;
    4. }
    5. if(!(event.getEntity() instanceof Player)) {
    6. return;
    7. }
    8. Player shooter = (Player) event.getEntity();
    9. "DO WHAT YOU WANT!"
    10. }
    11. }


    to get the damager:
    Code:java
    1. public void onBla(EntityDamageByEntityEvent event){
    2. if(event.getCause().equals(DamageCause.PROJECTILE)){
    3. int dmg = event.getDamage();
    4. BLAH
    5. }
    6.  
    7.  
     
  3. You can just use @EventHandler()'s ignore option to skip cancelled events.

    However, checking if it's a projectile doesn't guarantee it's an arrow... it could be a snowball for all we know... there has to be a way to get the entity that did the damage (the arrow) and check if instanceof Arrow... for the shooter of the arrow I think it's a event method that gets that, the attacker.
     
  4. Offline

    Sorroko

    Digi you do exactly what you said, check if the projectile is an instance of Arrow
     
  5. Offline

    ShadowDrakken

    Does this work if there's several shooters at once, or if there's multiple dispensers shooting at the same time? It seems like with only one tracking variable being used, the tracking variable could get overwritten before the arrow impact...
     
  6. ShadowDrakken yes that would be the case for manniL 's code, but try what I said by getting attacker....
    However, you can't know who shot the arrow in a dispenser, it could be anyone from the guy that placed the dispenser, the guy that placed the arrows inside or the guy that flipped the switch which you can't detect.
     
  7. Offline

    ShadowDrakken

    the dispenser would be the who ;)

    Anyway, I tried the code, it doesn't work... I found other code that looks more accurate, but it doesn't work either. I haven't setup any of my debugging to test exactly why though. There's no need to keep track of who shot it from what I can see, the arrow actually keeps track of the shooter itself.

    In the EntityDamagedByEntity event you can get the projectile and the projectile itself has getShooter() you just have to cast it to the correct type, the problem I'm running into appears to be (I'll know for sure once I write my debugging) that getShooter() is returning LivingEntity not Player so I'm not sure how to tell if the LivingEntity is a player or a skeleton so that I can ignore or use it properly based on that.
     
  8. entity instanceof Player and then cast.
     
  9. Offline

    ShadowDrakken

    Ok, finally got it all working :) I haven't tested with magic (not sure if there even is any), but this works for melee (tested), archery (tested) and should work for thrown potions (untested, but follows projectile rules) as well

    Code:java
    1.  
    2. public void onEntityDeath (final EntityDeathEvent event) {
    3. EntityDamageByEntityEvent damageEvent;
    4.  
    5. try {
    6. damageEvent = (EntityDamageByEntityEvent) event.getEntity().getLastDamageCause();
    7. } catch (Exception e) {
    8. return;
    9. }
    10.  
    11. DamageCause damageCause = damageEvent.getCause();
    12. Entity attacker = null;
    13.  
    14. switch (damageCause) {
    15. case MAGIC:
    16. case ENTITY_ATTACK:
    17. attacker = damageEvent.getDamager();
    18. break;
    19. case PROJECTILE:
    20. // Only certain projectiles are player originating
    21. if (damageEvent.getDamager().getType() == EntityType.ARROW) {
    22. Projectile arrow = (Arrow) damageEvent.getDamager();
    23. attacker = arrow.getShooter();
    24. } else if (damageEvent.getDamager().getType() == EntityType.SPLASH_POTION) {
    25. Projectile potion = (ThrownPotion) damageEvent.getDamager();
    26. attacker = potion.getShooter();
    27. } else {
    28. return;
    29. }
    30. break;
    31. }
    32.  
    33. // If the attacker isn't a player, there's nothing to do
    34. if (attacker.getType() != EntityType.PLAYER) return;
    35.  
    36. Entity target = damageEvent.getEntity();
    37.  
    38. // Now you have your attacker and target!
    39. }
    40.  
     
  10. Offline

    boduzapho

    Splash Potions return as Magic not Projectile
     
  11. Offline

    Courier

    You guys seem to have gotten pretty far off from the OP's original request...
    Code:java
    1. @EventHandler(ignoreCancelled = true)
    2. public void onHit(EntityDamageByEntityEvent event)
    3. {
    4. if(event.getCause() == DamageCause.PROJECTILE)
    5. {
    6. Projectile proj = (Projectile)event.getDamager();
    7. LivingEntity shooter = proj.getShooter();
    8. String shooterName = getName(shooter);
    9. String targetName = getName(event.getEntity());
    10. Bukkit.broadcastMessage(String.format("%1$s shot %2$s for %3$d damage!", shooterName, targetName, event.getDamage()));
    11. }
    12. }
    13.  
    14. private static String getName(Entity ent)
    15. {
    16. if(ent instanceof Player)
    17. return ((Player)ent).getName();
    18. return ent.getClass().getSimpleName();
    19. }
    "Courier shot CraftSkeleton for 8 damage!" etc.
    This probably also works with snowballs, but it will say 0 damage.
     
  12. Doesn't Entity class have a getName() method that gets automatically filled with player's name, mob name or whatever the entity's name is ? :} Not sure, you should test.
     
  13. Offline

    Courier

    Nope.
     
  14. Google is so unreliable there because the page that they have cached might be outdated xD you'd be better off in-page searching.

    Anyway, it would've been better to have a getName() tough.

    Still, ent.getType().getName() would print a better mob/entity instead of the class name :p
     
  15. Offline

    Courier

    I did in-page search first, but I can't exactly link to my Ctrl+F :p.
    True... I didn't think of that.
     
Thread Status:
Not open for further replies.

Share This Page