Poisoned Arrows (Arrows and potions)

Discussion in 'Plugin Development' started by valon750, Jan 3, 2013.

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

    valon750

    Hmm, alright then, so will it be possible to add in additional arrows? I was hoping to have ones such as slowness or nausea.

    Hmm, so will anything need to be changed for the ProjecticeLaunchEvent?

    I'm getting really pumped to start testing this plugin out on an actual server :D it's going to be such an awesome addition!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  2. Offline

    fireblast709

    valon750 that is why I advised you to use HashMaps earlier. You would something like:
    Code:java
    1. HashMap<UUID, String> arrowTypes = new HashMap<UUID, String>();
    2.  
    3. @EventHandler
    4. public void onLaunch(ProjectileLaunchEvent event)
    5. {
    6. if(event.getEntity().getShooter() instanceof Player == false)
    7. {
    8. return;
    9. }
    10. if(event.getEntity() instanceof Arrow)
    11. {
    12. Arrow a = event.getProjectile();
    13. String shooter = ((Player)a.getShooter()).getName();
    14. String type = usingArrow.containsKey(shooter) ? usingArrow.get(shooter) : "NORMAL";
    15. arrowTypes.put(a.getUniqueId(), type);
    16. }
    17. }
    18.  
    19. /*
    20. * This next event is just for cleanup, but it is neccesary
    21. **/
    22. @EventHandler
    23. public void onHit(final ProjectileHitEvent event)
    24. {
    25. final UUID uuid = event.getEntity().getUniqueId();
    26. if(arrowTypes.containsKey(uuid))
    27. {
    28. // Schedule the removal 1 tick later as this event is called before
    29. // the EntityDamageByEntityEvent
    30. new BukkitRunnable()
    31. {
    32. @Override
    33. public void run()
    34. {
    35. if(arrowTypes.containsKey(uuid))
    36. {
    37. arrowTypes.remove(uuid);
    38. }
    39. }
    40. }.runTaskLater(<plugin instance>, 1L);
    41. }
    42. }
    43.  
    44. @EventHandler
    45. public void onDamage(EntityDamageByEntityEvent event)
    46. {
    47. if(event.getDamager() instanceof Arrow && event.getEntity() instanceof LivingEntity)
    48. {
    49. Arrow a = (Arrow)event.getDamager();
    50. if(a.getShooter() instanceof Player)
    51. {
    52. String shooter = ((Player)a.getShooter()).getName();
    53. String type = usingArrow.containsKey(shooter) ? usingArrow.get(shooter) : "NORMAL";
    54. if(type.equals("NORMAL"))
    55. {
    56. // handle as you like, or ignore this
    57. }
    58. else
    59. {
    60. PotionEffect pe = /*Get the PotionEffect here*/
    61. ((LivingEntity)event.getEntity()).addPotionEffect(pe);
    62. }
    63. }
    64. }
    65. }
     
  3. Offline

    valon750

    fireblast709

    Right then, So out of what I have in the player listener at the moment, what do I and don't I need?

    Code:
        HashSet<UUID> poisonI = new HashSet<UUID>();
        public PotionPoint plugin;
        public PlayerListener(PotionPoint instance){
            plugin = instance;
        }
        private HashMap<String, String> usingArrow = new HashMap<String, String>();
       
        @EventHandler
        public void onInteract(PlayerInteractEvent e)
        {
            ItemStack hand = e.getPlayer().getItemInHand();
            if(hand == null || hand.getType() != Material.BOW)
            {
                return;
            }
            if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)
            {
                registerUsingArrow(e.getPlayer());
            }
        }
       
        @EventHandler
        public void onInteract(PlayerInteractEntityEvent e)
        {
            ItemStack hand = e.getPlayer().getItemInHand();
            if(hand == null || hand.getType() != Material.BOW)
            {
                return;
            }
            registerUsingArrow(e.getPlayer());
        }
       
        private void registerUsingArrow(Player player)
        {
            ItemStack[] iss = player.getInventory().getContents();
            for(ItemStack is : iss)
            {
                if(is == null)
                {
                    continue;
                }
                if(is.getType() == Material.ARROW)
                {
                    List<String> lore = is.getItemMeta().hasLore() ? is.getItemMeta().getLore() : new ArrayList<String>();
                    if(lore.size() < 1 || !is.getEnchantments().isEmpty())
                    {
                        usingArrow.put(player.getName(), "NORMAL");
                    }
                    else if(is.getEnchantments().isEmpty())
                    {
                        usingArrow.put(player.getName(), lore.get(0));
                    }
                    return;
                }
            }
        }
       
     
        @EventHandler(priority = EventPriority.HIGHEST)
        public void onArrowShoot(ProjectileLaunchEvent e){
            if(e.getEntity() instanceof Arrow) {
            if(poisonI.contains(arrow.getUniqueId())){
                poisonI.add(e.getEntity().getUniqueId());
            }
            }
            }
        @EventHandler(priority = EventPriority.HIGHEST)
        public void onMobHit(EntityDamageByEntityEvent e){
            Entity damager = e.getDamager();
            LivingEntity damagee = (LivingEntity) e.getEntity();
            if(e.getEntity() instanceof LivingEntity) // it lives
            {                   
                    damagee.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 200, 0));
                }
            }
        }
       
    
    Also, when I started adding in your code, I got a whole but of issues when it came to scheduling the removal 1 tick later, as in, there was just lines and lines of red?
     
  4. Offline

    fireblast709

    valon750
    Code:java
    1. HashMap<UUID, String> arrowTypes = new HashMap<UUID, String>();
    2. private HashMap<String, String> usingArrow = new HashMap<String, String>();
    3. public PotionPoint plugin;
    4.  
    5. public PlayerListener(PotionPoint instance){
    6. plugin = instance;
    7. }
    8.  
    9. @EventHandler
    10. public void onInteract(PlayerInteractEvent e)
    11. {
    12. ItemStack hand = e.getPlayer().getItemInHand();
    13. if(hand == null || hand.getType() != Material.BOW)
    14. {
    15. return;
    16. }
    17. if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)
    18. {
    19. registerUsingArrow(e.getPlayer());
    20. }
    21. }
    22.  
    23. @EventHandler
    24. public void onInteract(PlayerInteractEntityEvent e)
    25. {
    26. ItemStack hand = e.getPlayer().getItemInHand();
    27. if(hand == null || hand.getType() != Material.BOW)
    28. {
    29. return;
    30. }
    31. registerUsingArrow(e.getPlayer());
    32. }
    33.  
    34. private void registerUsingArrow(Player player)
    35. {
    36. ItemStack[] iss = player.getInventory().getContents();
    37. for(ItemStack is : iss)
    38. {
    39. if(is == null)
    40. {
    41. continue;
    42. }
    43. if(is.getType() == Material.ARROW)
    44. {
    45. List<String> lore = is.getItemMeta().hasLore() ? is.getItemMeta().getLore() : new ArrayList<String>();
    46. if(lore.size() < 1 || !is.getEnchantments().isEmpty())
    47. {
    48. usingArrow.put(player.getName(), "NORMAL");
    49. }
    50. else if(is.getEnchantments().isEmpty())
    51. {
    52. usingArrow.put(player.getName(), lore.get(0));
    53. }
    54. return;
    55. }
    56. }
    57. }
    58.  
    59. @EventHandler
    60. public void onLaunch(ProjectileLaunchEvent event)
    61. {
    62. if(event.getEntity().getShooter() instanceof Player == false)
    63. {
    64. return;
    65. }
    66. if(event.getEntity() instanceof Arrow)
    67. {
    68. Arrow a = event.getProjectile();
    69. String shooter = ((Player)a.getShooter()).getName();
    70. String type = usingArrow.containsKey(shooter) ? usingArrow.get(shooter) : "NORMAL";
    71. arrowTypes.put(a.getUniqueId(), type);
    72. }
    73. }
    74.  
    75. /*
    76. * This next event is just for cleanup, but it is neccesary
    77. **/
    78. @EventHandler
    79. public void onHit(final ProjectileHitEvent event)
    80. {
    81. final UUID uuid = event.getEntity().getUniqueId();
    82. if(arrowTypes.containsKey(uuid))
    83. {
    84. // Schedule the removal 1 tick later as this event is called before
    85. // the EntityDamageByEntityEvent
    86. new BukkitRunnable()
    87. {
    88. @Override
    89. public void run()
    90. {
    91. if(arrowTypes.containsKey(uuid))
    92. {
    93. arrowTypes.remove(uuid);
    94. }
    95. }
    96. }.runTaskLater(plugin, 1L);
    97. }
    98. }
    99.  
    100. @EventHandler
    101. public void onDamage(EntityDamageByEntityEvent event)
    102. {
    103. if(event.getDamager() instanceof Arrow && event.getEntity() instanceof LivingEntity)
    104. {
    105. Arrow a = (Arrow)event.getDamager();
    106. if(a.getShooter() instanceof Player)
    107. {
    108. String shooter = ((Player)a.getShooter()).getName();
    109. String type = usingArrow.containsKey(shooter) ? usingArrow.get(shooter) : "NORMAL";
    110. if(type.equals("NORMAL"))
    111. {
    112. // handle as you like, or ignore this
    113. }
    114. else if(type.equals("Poison I"))
    115. {
    116. PotionEffect pe = new PotionEffect(PotionEffectType.POISON, 200, 0);
    117. ((LivingEntity)event.getEntity()).addPotionEffect(pe);
    118. }
    119. }
    120. }
    121. }
    For the rest of the wriggly lines, you need to tell me what line and what message
     
  5. Offline

    valon750

    fireblast709

    Nice one! Now the only issue is:

    Code:
        @EventHandler
        public void onLaunch(ProjectileLaunchEvent event)
        {
            if(event.getEntity().getShooter() instanceof Player == false)
            {
                return;
            }
            if(event.getEntity() instanceof Arrow)
            {
                Arrow a = event.getProjectile();
                String shooter = ((Player)a.getShooter()).getName();
                String type = usingArrow.containsKey(shooter) ? usingArrow.get(shooter) : "NORMAL";
                arrowTypes.put(a.getUniqueId(), type);
            }
        }
    a.getShooter is apparently undefined for ProjectileLaunchEvent
     
  6. Offline

    fireblast709

    a.getShooter() gets called from Arrow (Arrow a = (Arrow)event.getProjectile())
     
  7. Offline

    valon750


    Hmm, how do you mean? Are you saying I need to alter something? Because I changed the bit that says,
    Arrow a = event.getProjectile(); to (Arrow a = (Arrow)event.getProjectile()), but then I got issues saying:

    if(event.getEntity() instanceof Arrow)
    {
    (Arrow a = (Arrow)event.getProjectile());
    String shooter = ((Player)a.getShooter()).getName();

    Picture the underlines and squiggly.

    Saying that everything up to the first "a" had a syntax error, misplaced constructs.

    then "a" couldn't be resolved, nor could the second "a" or third.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  8. Offline

    fireblast709

    Arrow a = (Arrow)event.getEntity();
    String shooter = ((Player)a.getShooter()).getName();
     
  9. Offline

    MinecraftSped I steal plugins as my own

    This is off topic but valon750
    Could you please send me this once your done? Looks promising :D
     
  10. Offline

    valon750

    Don't worry my friend, It'll be up on BukkitDev once it's at a point where it's ready :D

    Oh awesome! There's no errors at all now, is there anything else we need to cover?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
    MinecraftSped likes this.
  11. Offline

    fireblast709

    I would say test and we will see
     
  12. Offline

    valon750

    huh, now this really is odd.

    It applies the effect, so thanks so darn much for that. Issue is, the crafting process, only works when I spawn in a potion of poison.

    As in, if you spawn in the potion with data value.. 8196, it's a potion of poison lasting 45 seconds, when crafted with the arrow it makes the arrow with the potion effect, but grabbing the same potion from creative doesn't work with the arrow, so I assume they have different numbers?

    Also, I've noticed that potions of poison that last different times don't create an arrow.

    I was thinking of something also, this isn't related too much to coding but more of a playing stand point, do you think the arrow should give the player/mob the potion effect, with the duration of the initial potion? Because I could see that being quite OP, but also fun. :S

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  13. Offline

    fireblast709

    You could, or you could use like a constant duration. Or a config-defined duration if you want ;3

    Yes it is datavalue defined, so only that one specific potion works

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  14. Offline

    valon750

    Hmm, could you possibly supply an example on how I would add an additional potion arrow? I should be able to work out the crafting, but the rest will take me some time
     
  15. Offline

    fireblast709

    you would just have to register more recipes
     
  16. Offline

    valon750

    Oh yeah! Never thought of adding a config for it.
    I think what I may have is just a set amount, for each potion effect, but have them lower than the standard potion. If people ask why, I'll say that some is lost during flight, and that there's only a percentage of the potion actually on the arrow XD

    Oh, but what about the different potion effects and times?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  17. Offline

    fireblast709

    same, its all datavalues
     
  18. Offline

    valon750

    Wait, so I'm planning on adding a potion of slowness and sickness that can be used with the arrows, the crafting bit is easy but when it comes to it checking what name it is and everything I get lost
     
  19. Offline

    fireblast709

    add them to the HashMaps... like return an ItemStack with lore "Slowness I" and in the EntityDamageByEntityEvent check for type.equals("Slowness I")
     
  20. Offline

    valon750

    Oh I see, I'll get to that right now.

    Only one issue remains really, I'm not sure why the spawned in potion works and the regular potion taken from the creative inventory isn't working. They're both the same duration :S

    Any ideas? how do I get the item id's in game? couldn't you do that F3 + <key> and get the name with the item id next to it or something?

    fireblast709

    Right then! I've figured it out, the potion you get from the creative inventory actually has the id 16276

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  21. Offline

    fireblast709

    *Datavalue, I suppose
     
  22. Offline

    valon750

    That's so odd how they've done that :S

    Okay this is what confuses me a hell of a lot.

    In the creative inventory, the datavalue is 16276, but the potion you actually craft is 8196. Where on earth is the logic behind this?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 8, 2016
  23. Offline

    fireblast709

    It seems like creative randomly is setting bits to 1 after the 7th bit
     
  24. Offline

    trebitot

    Potions increase the data value to determine exactly what kind it is, like Splash, level 1 or 2, stuff like that.

    If you want to just get the base potion effect, you could find the data value's factors



    EDIT:
    Bit 14 (8192) and 15 (16384) determine whether the potion is a drinkable potion or a splash potion. If bit 14 is true and 15 false, it's drinkable. If 14 is false and 15 true, it's a splash potion.
    If bit 6 (32) is true, the potion is a level II potion (or, in some cases, a reverted potion).
    If bit 7 (64) is true, the potion is an extended potion (or, in some cases, a reverted potion).
    Potions with bit 6 and 7 set to 1 cannot legitimately be obtained, thus, there are no legitimate potions that are both extended and level II.
    Bits 1-4 (1, 2, 4 and 8) determine the potion effect. The highest legitimately available is currently 12decimal = 1100binary.

    If you want to just get the base potion effect, you could find the data value's factor.
    For example since the DV of regen is 1, you know that any potion with a DV of (2^x) + 1 is a potion of regen.
     
  25. Offline

    fireblast709

    Yes I have read that page. The only significant bits are bit 1, 2, 3, 4, 6, 7, 14 and 15
     
  26. Offline

    moo3oo3oo3

    .addIngredient(amount, Material.POTION, datavalue) is deprecated. We can't seem to add data value anymore
     
  27. Offline

    fireblast709

    moo3oo3oo3 Let the dead threads rest in peace :p. Also, it's deprecated but no better alternative has been offered yet (afaik - there are some ways like creating an ItemStack and using getData(), but in the end you do nothing aside avoiding the deprecation warning)
     
Thread Status:
Not open for further replies.

Share This Page