[Resource & Tutorial] Rope Thrower

Discussion in 'Resources' started by TeeePeee, Mar 9, 2014.

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

    TeeePeee

    Hi all,

    In my search of this subforum, I found an awesome resource by Desle on how to make ropes out of leads. Reading the thread, I was inspired by Goblom and others to create throwable ropes that players can use to rappel, grapple, etc. After a bit of messing around, this was the result.

    Code:java
    1. import java.util.ArrayList;
    2. import java.util.List;
    3.  
    4. import org.bukkit.Bukkit;
    5. import org.bukkit.Location;
    6. import org.bukkit.entity.Arrow;
    7. import org.bukkit.entity.Entity;
    8. import org.bukkit.entity.Item;
    9. import org.bukkit.entity.Player;
    10. import org.bukkit.scheduler.BukkitTask;
    11.  
    12. import net.minecraft.server.v1_7_R1.EntityBat;
    13. import net.minecraft.server.v1_7_R1.PacketPlayOutAttachEntity;
    14. import net.minecraft.server.v1_7_R1.PacketPlayOutEntityDestroy;
    15. import net.minecraft.server.v1_7_R1.PacketPlayOutSpawnEntityLiving;
    16. import net.minecraft.server.v1_7_R1.WorldServer;
    17.  
    18. import org.bukkit.craftbukkit.v1_7_R1.CraftWorld;
    19. import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
    20. import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer;
    21.  
    22. /**
    23.  * Credits to [USER=90856537]Desle[/USER] for the original resource. (Uses entities, not packets)
    24.  *
    25.  * @author Goblom
    26.  * @author Jordan
    27.  */
    28. public class Rope {
    29.  
    30. private static final List<Rope> ropes = new ArrayList<Rope>();
    31.  
    32. private Location endLocation;
    33. private EntityBat batLocation;
    34. private Entity holder, hook;
    35. private RopeResult result;
    36.  
    37. public static enum RopeResult {
    38. MOB, ITEM, GROUND, AIR;
    39. }
    40.  
    41. /**
    42.   * Make a rope with a specified endpoint and holder.
    43.   *
    44.   * @param end
    45.   * The endpoint of the rope.
    46.   * @param holder
    47.   * The entity that should hold the rope.
    48.   */
    49. public Rope(Location end, Entity holder) {
    50. this.endLocation = end;
    51. this.holder = holder;
    52. for (Rope r : new ArrayList<Rope>(ropes)) {
    53. if (r.holder != null && r.holder.equals(holder)) {
    54. r.holder = null;
    55. r.despawn();
    56. }
    57. }
    58. ropes.add(this);
    59.  
    60. spawn();
    61. }
    62.  
    63. /**
    64.   * Set the end location of the rope. Will cause issues if the end of the
    65.   * rope is attached to a mobile creature.
    66.   *
    67.   * @param end
    68.   * The end location.
    69.   */
    70. public void setEnd(Location end) {
    71. this.endLocation = end;
    72. spawn();
    73. }
    74.  
    75. /**
    76.   * Get the end location of this rope.
    77.   *
    78.   * @return The end location of the rope.
    79.   */
    80. public Location getEnd() {
    81. return endLocation;
    82. }
    83.  
    84. /**
    85.   * Make the entities and connections necessary for this rope.
    86.   */
    87. private void makeEnt() {
    88. WorldServer world = ((CraftWorld) endLocation.getWorld()).getHandle();
    89.  
    90. if (batLocation == null) {
    91. this.batLocation = new EntityBat(world);
    92. batLocation.setInvisible(true);
    93. }
    94.  
    95. this.batLocation.setLocation(endLocation.getX(), endLocation.getY(), endLocation.getZ(), 0, 0);
    96.  
    97. batLocation.setLeashHolder(((CraftEntity) holder).getHandle(), true);
    98. }
    99.  
    100. /**
    101.   * Make this Rope appear in the world. Despawns if there is no rope holder.
    102.   */
    103. public void spawn() {
    104. if (holder == null) {
    105. despawn();
    106. return;
    107. }
    108. makeEnt();
    109. PacketPlayOutSpawnEntityLiving bat_end = new PacketPlayOutSpawnEntityLiving(batLocation);
    110. PacketPlayOutAttachEntity attach = new PacketPlayOutAttachEntity(1, batLocation, ((CraftPlayer) holder).getHandle());
    111.  
    112. for (Player player : Bukkit.getOnlinePlayers()) {
    113. CraftPlayer cP = (CraftPlayer) player;
    114. cP.getHandle().playerConnection.sendPacket(bat_end);
    115. cP.getHandle().playerConnection.sendPacket(attach);
    116. }
    117. }
    118.  
    119. /**
    120.   * Remove all the ropes/packets that are glued.
    121.   *
    122.   * @see despawn()
    123.   */
    124. public static void removeAll() {
    125. for (Rope r : new ArrayList<Rope>(ropes)) {
    126. r.despawn();
    127. }
    128. }
    129.  
    130. /**
    131.   * Remove this rope and clean up the packets.
    132.   */
    133. public void despawn() {
    134. holder = null;
    135. PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(batLocation.getId());
    136.  
    137. for (Player player : Bukkit.getOnlinePlayers()) {
    138. CraftPlayer cP = (CraftPlayer) player;
    139. cP.getHandle().playerConnection.sendPacket(destroy);
    140. }
    141. ropes.remove(this);
    142. }
    143.  
    144. /**
    145.   * Glue the end of the rope to an entity.
    146.   *
    147.   * @param toAttachTo
    148.   * The entity to glue to.
    149.   */
    150. public void glueEndTo(Entity toAttachTo) {
    151. PacketPlayOutAttachEntity attach = new PacketPlayOutAttachEntity(0, batLocation, ((CraftEntity) toAttachTo).getHandle());
    152. for (Player player : Bukkit.getOnlinePlayers()) {
    153. CraftPlayer cP = (CraftPlayer) player;
    154. cP.getHandle().playerConnection.sendPacket(attach);
    155. }
    156.  
    157. GlueUpdater u = new GlueUpdater(toAttachTo);
    158. u.task = Bukkit.getServer().getScheduler().runTaskTimer(PLUGIN, u, 0L, 1L);
    159. }
    160.  
    161. private class GlueUpdater implements Runnable {
    162. BukkitTask task;
    163. Entity glued;
    164.  
    165. public GlueUpdater(Entity glued) {
    166. this.glued = glued;
    167. }
    168.  
    169. public void run() {
    170. if (holder == null || glued == null || glued.isDead() || (glued instanceof Arrow && ((Arrow) glued).isOnGround())) {
    171. if (holder == null && glued != null) {
    172. glued.remove();
    173. }
    174. task.cancel();
    175. result = RopeResult.GROUND;
    176. if (glued != null) {
    177. for (Entity e : glued.getNearbyEntities(1, 0.5, 1))
    178. if (!e.equals(glued)) {
    179. if (e instanceof Item)
    180. result = RopeResult.ITEM;
    181. else
    182. result = RopeResult.MOB;
    183.  
    184. hook = e;
    185. glueEndTo(e);
    186. return;
    187. }
    188. }
    189.  
    190. return;
    191. }
    192.  
    193. endLocation = glued.getLocation().subtract(0,
    194. result == RopeResult.ITEM || (result == RopeResult.MOB && hook instanceof Arrow) ? 0 : 2, 0);
    195. if (glued instanceof Arrow) {
    196. setEnd(endLocation);
    197. }
    198. }
    199. }
    200.  
    201. /**
    202.   * Get a rope held by a certain entity.
    203.   *
    204.   * @param holder
    205.   * The entity that might be holding a rope.
    206.   * @return The rope the holder is holding or null if there is no rope
    207.   * associated with.
    208.   */
    209. public static Rope getRope(Entity holder) {
    210. for (Rope r : ropes) {
    211. if (r.holder != null && r.holder.equals(holder)) { return r; }
    212. }
    213. return null;
    214. }
    215.  
    216. /**
    217.   * The result of the hook.
    218.   *
    219.   * @return The hook result.
    220.   */
    221. public RopeResult getResult() {
    222. return result;
    223. }
    224.  
    225. /**
    226.   * Get the item on the hook end of the rope.
    227.   *
    228.   * @return The hook item.
    229.   */
    230. public Entity getHook() {
    231. return hook;
    232. }
    233.  
    234. /**
    235.   * Whether or not the player should be able to pull in the line.
    236.   *
    237.   * @return True if the hook landed or hit an entity/item.
    238.   */
    239. public boolean canPull() {
    240. return result != RopeResult.AIR;
    241. }
    242. }
    243.  


    With this, the possibilities are endless. In this example, we will use the ProjectileLaunchEvent to see when a player fires an arrow. If an arrow is fired, we'll glue a rope to the arrow.

    Code:java
    1. @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    2. private void onShootArrow(ProjectileLaunchEvent e) {
    3. if (e.getEntity().getShooter() instanceof Player && e.getEntity() instanceof Arrow) {
    4. launchRope(e.getEntity().getShooter(), (Arrow) e.getEntity());
    5. }
    6. }
    7.  
    8. private void launchRope(Entity thrower, Arrow glue) {
    9. Rope rope = new Rope(glue.getLocation(), thrower);
    10. rope.glueEndTo(glue);
    11. }


    Now that we've glued our rope to the arrow, we just need to do something with it. Why not use it as a grapple?

    Let's listen for the interact event. If a player right clicked with a rope out and bow in hand, we'll launch the player to the location of the arrow!

    Code:java
    1. @EventHandler(priority = EventPriority.LOWEST)
    2. private void onClick(PlayerInteractEvent e) {
    3. if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK
    4. && e.getItem().getType() == Material.BOW) {
    5. Rope r = Rope.getRope(e.getPlayer());
    6. if (r != null) {
    7. e.setCancelled(true);
    8. if (r.canPull()) {
    9. pullTo(e.getPlayer(), r.getEnd());
    10. r.despawn();
    11. }
    12. }
    13. }
    14.  
    15. public static void pullTo(Entity e, Location loc) {
    16. // This code written by [USER=90696604]SnowGears[/USER]
    17. Location l = e.getLocation();
    18.  
    19. if (l.distanceSquared(loc) < 9) {
    20. if (loc.getY() > l.getY()) {
    21. e.setVelocity(new Vector(0, 0.25, 0));
    22. return;
    23. }
    24. Vector v = loc.toVector().subtract(l.toVector());
    25. e.setVelocity(v);
    26. return;
    27. }
    28.  
    29. l.setY(l.getY() + 0.5);
    30. e.teleport(l);
    31.  
    32. double d = loc.distance(l);
    33. double g = -0.08;
    34. double x = (1.0 + 0.07 * d) * (loc.getX() - l.getX()) / d;
    35. double y = (1.0 + 0.03 * d) * (loc.getY() - l.getY()) / d - 0.5 * g * d;
    36. double z = (1.0 + 0.07 * d) * (loc.getZ() - l.getZ()) / d;
    37.  
    38. Vector v = e.getVelocity();
    39. v.setX(x);
    40. v.setY(y);
    41. v.setZ(z);
    42. e.setVelocity(v);
    43. }


    Great! Now all arrows we shoot are automatically glued to a rope that can be used to reel the player in. This is only one use for the resource. Feel free to post ideas or any way you used it below!
     
  2. Offline

    unenergizer

    Awesome job!
     
  3. Offline

    Ape101

    Will this work with 1.6.4? if i convert the craftbukkit imports?
     
  4. Offline

    Goblom

    Ape101 Possibly yes, but you will also need to change the packets as names changed with 1.6.4 --> 1.7
     
  5. Offline

    Ape101

    Any idea what they used to be in 1.6? or where i could find what they were called?
     
  6. Offline

    Goblom

    Ape101 All i remember is Packet18SpawnMob, but alas there are 4 different packets being used in this library
     
  7. Offline

    Ape101

    Oh dayum. Thats a nice spreadsheet.
    Thanks!

    Few errors i've got since changing the packages:
    all of the (CraftWorld) and (CraftEntity) and such can't be resolved as a type?
    and
    Code:java
    1. Packet29DestroyEntity destroy = new Packet29DestroyEntity(
    2. batLocation.getId());

    getID() is undefined for EntityBat

    Hopefully this can be fixed! Really need this to work with 1.6.4 haha :p

    EDIT 2: fixed the CraftEntity, but i don't think there is CraftWorld in 1.6.4? that or it's not letting me import it lol. Still can't figure out the getID() the only similar method is getUniqueID()
     
  8. Offline

    97WaterPolo

    TeeePeee

    Not to sure, but when I shoot the arrow, the first one immediately dissapears, then when I shoot the second one its like it hits an invisibly target right in front of me then drops down. After the second arrow is fired, it creates a rope starting right where the second arrow went to me, the arrow doesn't seem to actually be moving, just staying right where the player is. Any ideas? Using your exact code, thought this error was due to the way I implemented it, yet it seems to do this with the example as well.
     
  9. Offline

    TeeePeee

    97waterpolo I've revised the code since posting this (a little bit). Here's the updated one, for sake of ruining the original post format:
    Code:java
    1. import java.util.ArrayList;
    2. import java.util.List;
    3.  
    4. import net.minecraft.server.v1_7_R1.EntityBat;
    5. import net.minecraft.server.v1_7_R1.PacketPlayOutAttachEntity;
    6. import net.minecraft.server.v1_7_R1.PacketPlayOutEntityDestroy;
    7. import net.minecraft.server.v1_7_R1.PacketPlayOutSpawnEntityLiving;
    8. import net.minecraft.server.v1_7_R1.WorldServer;
    9.  
    10. import org.bukkit.Bukkit;
    11. import org.bukkit.Location;
    12. import org.bukkit.craftbukkit.v1_7_R1.CraftWorld;
    13. import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
    14. import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer;
    15. import org.bukkit.entity.Arrow;
    16. import org.bukkit.entity.Entity;
    17. import org.bukkit.entity.Item;
    18. import org.bukkit.entity.Player;
    19. import org.bukkit.scheduler.BukkitTask;
    20.  
    21. /**
    22. * Credits to [USER=90856537]Desle[/USER] for the original resource. (Uses entities, not packets)
    23. *
    24. * @author Goblom
    25. * @author Jordan
    26. */
    27. public class Rope {
    28.  
    29. private static final List<Rope> ropes = new ArrayList<Rope>();
    30.  
    31. private Location endLocation;
    32. private EntityBat batLocation;
    33. private Entity holder, hook;
    34. private RopeResult result;
    35.  
    36. public static enum RopeResult {
    37. MOB, ITEM, GROUND, AIR;
    38. }
    39.  
    40. /**
    41.   * Make a rope with a specified endpoint and holder.
    42.   *
    43.   * @param end
    44.   * The endpoint of the rope.
    45.   * @param holder
    46.   * The entity that should hold the rope.
    47.   */
    48. public Rope(Location end, Entity holder) {
    49. endLocation = end;
    50. this.holder = holder;
    51. for (Rope r : new ArrayList<Rope>(ropes))
    52. if (r.holder != null && r.holder.equals(holder)) {
    53. r.holder = null;
    54. r.despawn();
    55. }
    56. ropes.add(this);
    57.  
    58. spawn();
    59. }
    60.  
    61. /**
    62.   * Set the end location of the rope. Will cause issues if the end of the
    63.   * rope is attached to a mobile creature.
    64.   *
    65.   * @param end
    66.   * The end location.
    67.   */
    68. public void setEnd(Location end) {
    69. endLocation = end;
    70. spawn();
    71. }
    72.  
    73. /**
    74.   * Get the end location of this rope.
    75.   *
    76.   * @return The end location of the rope.
    77.   */
    78. public Location getEnd() {
    79. return endLocation;
    80. }
    81.  
    82. /**
    83.   * Make the entities and connections necessary for this rope.
    84.   */
    85. private void makeEnt() {
    86. WorldServer world = ((CraftWorld) endLocation.getWorld()).getHandle();
    87.  
    88. if (batLocation == null) {
    89. batLocation = new EntityBat(world);
    90. batLocation.setInvisible(true);
    91. }
    92.  
    93. batLocation.setLocation(endLocation.getX(), endLocation.getY(), endLocation.getZ(), 0, 0);
    94.  
    95. batLocation.setLeashHolder(((CraftEntity) holder).getHandle(), true);
    96. }
    97.  
    98. /**
    99.   * Make this Rope appear in the world. Despawns if there is no rope holder.
    100.   */
    101. public void spawn() {
    102. if (holder == null) {
    103. despawn();
    104. return;
    105. }
    106. makeEnt();
    107. PacketPlayOutSpawnEntityLiving bat_end = new PacketPlayOutSpawnEntityLiving(batLocation);
    108. PacketPlayOutAttachEntity attach = new PacketPlayOutAttachEntity(1, batLocation, ((CraftPlayer) holder).getHandle());
    109.  
    110. for (Player player : Bukkit.getOnlinePlayers()) {
    111. CraftPlayer cP = (CraftPlayer) player;
    112. cP.getHandle().playerConnection.sendPacket(bat_end);
    113. cP.getHandle().playerConnection.sendPacket(attach);
    114. }
    115. }
    116.  
    117. /**
    118.   * Remove all the ropes/packets that are glued.
    119.   *
    120.   * @see despawn()
    121.   */
    122. public static void removeAll() {
    123. for (Rope r : new ArrayList<Rope>(ropes))
    124. r.despawn();
    125. }
    126.  
    127. /**
    128.   * Remove this rope and clean up the packets.
    129.   */
    130. public void despawn() {
    131. holder = null;
    132. PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(batLocation.getId());
    133.  
    134. for (Player player : Bukkit.getOnlinePlayers()) {
    135. CraftPlayer cP = (CraftPlayer) player;
    136. cP.getHandle().playerConnection.sendPacket(destroy);
    137. }
    138. ropes.remove(this);
    139. }
    140.  
    141. /**
    142.   * Glue the end of the rope to an entity.
    143.   *
    144.   * @param toAttachTo
    145.   * The entity to glue to.
    146.   */
    147. public void glueEndTo(Entity toAttachTo) {
    148. glueEndTo(toAttachTo, 0);
    149. }
    150.  
    151. public void glueEndTo(Entity toAttachTo, int count) {
    152. PacketPlayOutAttachEntity attach = new PacketPlayOutAttachEntity(0, batLocation, ((CraftEntity) toAttachTo).getHandle());
    153. for (Player player : Bukkit.getOnlinePlayers()) {
    154. CraftPlayer cP = (CraftPlayer) player;
    155. cP.getHandle().playerConnection.sendPacket(attach);
    156. }
    157.  
    158. GlueUpdater u = new GlueUpdater(toAttachTo, count);
    159. u.task = Bukkit.getServer().getScheduler().runTaskTimer(PLUGIN, u, 0L, 1L);
    160. }
    161.  
    162. private class GlueUpdater implements Runnable {
    163. BukkitTask task;
    164. Entity glued;
    165. int glueCount;
    166.  
    167. public GlueUpdater(Entity glued, int glueCount) {
    168. this.glued = glued;
    169. this.glueCount = glueCount;
    170. }
    171.  
    172. @Override
    173. public void run() {
    174. if (holder == null || glued == null || glued.isDead() || glued instanceof Arrow && ((Arrow) glued).isOnGround()) {
    175. task.cancel();
    176. result = RopeResult.GROUND;
    177. if (glued != null && glueCount < 3)
    178. for (Entity e : glued.getNearbyEntities(1, 0.5, 1))
    179. if (!e.equals(glued)) {
    180. if (e instanceof Item)
    181. result = RopeResult.ITEM;
    182. else
    183. result = RopeResult.MOB;
    184.  
    185. hook = e;
    186. glueEndTo(e, glueCount + 1);
    187. return;
    188. }
    189.  
    190. return;
    191. }
    192.  
    193. endLocation = glued.getLocation().subtract(0,
    194. result == RopeResult.ITEM || result == RopeResult.MOB && hook instanceof Arrow ? 0 : 2, 0);
    195. if (glued instanceof Arrow)
    196. setEnd(endLocation);
    197. }
    198. }
    199.  
    200. /**
    201.   * Get a rope held by a certain entity.
    202.   *
    203.   * @param holder
    204.   * The entity that might be holding a rope.
    205.   * @return The rope the holder is holding or null if there is no rope
    206.   * associated with.
    207.   */
    208. public static Rope getRope(Entity holder) {
    209. for (Rope r : ropes)
    210. if (r.holder != null && r.holder.equals(holder))
    211. return r;
    212. return null;
    213. }
    214.  
    215. /**
    216.   * The result of the hook.
    217.   *
    218.   * @return The hook result.
    219.   */
    220. public RopeResult getResult() {
    221. return result;
    222. }
    223.  
    224. /**
    225.   * Get the item on the hook end of the rope.
    226.   *
    227.   * @return The hook item.
    228.   */
    229. public Entity getHook() {
    230. return hook;
    231. }
    232.  
    233. /**
    234.   * Whether or not the player should be able to pull in the line.
    235.   *
    236.   * @return True if the hook landed or hit an entity/item.
    237.   */
    238. public boolean canPull() {
    239. return result != RopeResult.AIR;
    240. }
    241. }
    242.  
     
    97waterpolo likes this.
  10. Offline

    97WaterPolo

    TeeePeee
    Thanks, will try this tomorrow!
     
  11. Offline

    Ape101

  12. Offline

    TeeePeee

    Ape101
    There's definitely a CraftWorld class (as evidenced here) so that shouldn't cause a problem.
    For the Bat ID, I'd have to recommend trying the integer field 'id'.
     
  13. Offline

    97WaterPolo

    TeeePeee
    Getting "Caused by: java.lang.IllegalArgumentException: Plugin cannot be null"

    Says line 166 of RopePull, which is 'u.task = Bukkit.getServer().getScheduler().runTaskTimer(plugin, u, 0L, 1L);"

    I have plugin defined in a constructor, any idea why it is saying it is null?
     
  14. Offline

    TeeePeee

    97waterpolo
    Hard to say without seeing where plugin is initialized and where the rope object is initialized. If the plugin is null, it's simply that. Make sure you define the plugin before the rope.
     
  15. Offline

    97WaterPolo

  16. Offline

    TeeePeee

    97waterpolo
    Are you passing a null instance to the Whip constructor?
     
  17. Offline

    97WaterPolo

  18. Offline

    TeeePeee

    97waterpolo
    Sorry, only read through the Whip class.

    In your ropePull class, you made a constructor with the plugin. But when you actually create the RopePull, you use the constructor with location, entity. Change your RopePull(Location, Entity) to RopePull(Location, Entity, Core) and add the plugin initializer there.
     
  19. Offline

    97WaterPolo

    TeeePeee
    Thanks! Will try that when home!

    TeeePeee
    There is no ropePull method? Only thing I saw as well as cntrl f found was canPull?

    Only method I saw, was "public Rope(Location end, Entity holder)" that had location and entity. If so, should I change it to "public Rope(Location end, Entity holder, Plugin core)"

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

    TeeePeee

  21. Offline

    97WaterPolo

    TeeePeee
    Getting an error on "Rope rope = new Rope(glue.getLocation(), thrower);" in the class I am using this resource in. Wants me to add the plugin argument.
    This is your resource, I edited it so it has your original name.
    http://hastebin.com/limeregaku.java

    Any ideas?

    EDIT: I tried it with it, I added it to it, tried it multiple ways, it still has not worked. I added "Plugin core" to it yet it still does not work :L
     
  22. Offline

    TeeePeee

    97waterpolo
    I'll try to explain this the best I can to you.
    You created a constructor for the Rope that accepts only the plugin instance as the parameter. However, when you create the Rope, you don't use that constructor. You use the original constructor that accepts a location and an entity. By doing this, the Rope has no knowledge of the plugin instance.
    I told you to modify the original constructor so that it also accepts the plugin as a parameter. Here's your version of the file, fixed. As you can see, I removed the constructor with only the plugin and added an initializer to the plugin instance.

    Now, just change
    Code:java
    1. Rope rope = new Rope(glue.getLocation(), thrower);

    to
    Code:java
    1. Rope rope = new Rope(glue.getLocation(), thrower, PLUGIN);
     
  23. Offline

    97WaterPolo

    TeeePeee
    Thanks, I see what you are trying to say! Thank you for explaining it! :D

    Works, shoots the arrow with the rope atacked, problem is, every other arrow shoots. Every other arrow just dissapears, nothing is shot, no drawback, it seems to dissapear? Could it be due to the player interact event with right click?

    Did some more testing, not losing the arrow, it makes a ghost arrow, basically doesn't fire the first one, but it does the second. After second is fired, the original arrow re-appears>?
     
  24. Offline

    TeeePeee

    97waterpolo
    Could be that in your tests, the rope listing got out of sync. The Rope class keeps a static list of each rope that exists in the world. That way, it knows if a player already has a rope out.
    Either way, try restarting the server and re-testing.
     
  25. Offline

    97WaterPolo

    TeeePeee
    Thanks! Thanks for all the help and advice! ^_^
     
  26. Offline

    born2kill_

    Could someone please make this a plugin! I'd love to have a leash as a grappling hook!
     
  27. Any chance of someone making a Reflection based one? I hate updating plugins every bukkit version as if people want to stick to the previous version of Bukkit but still want the updated features of the plugin...
     
Thread Status:
Not open for further replies.

Share This Page