Hey guys, Had no Idea how to propperly name the Thread so sorry for that My Issue is as follows. I want that a player regenerates health slowly underwater. [Ignore the fact with the air since that is working] Code:java @EventHandlerpublic final void onDrownEvent(final PlayerMoveEvent event) {final Player p = event.getPlayer();int foodLevel;if (p.getRemainingAir() < p.getMaximumAir()) {p.setRemainingAir(p.getMaximumAir());foodLevel = p.getFoodLevel() + 1;p.setFoodLevel(foodLevel);} } Here the issue is that he regenerates TOO fast. Problem is that the FoodLevel within bukkit only accepts values of the type Integer. This means I cannot go ahaed and let it regenerate it 0.1 every time the event is triggered. Now I need to find a solution to either store a certain ammount / after a certain ammounts of triggering the event the food level raises by one.. The issue is if I try something like this it won't work Code:java @EventHandlerpublic final void onDrownEvent(final PlayerMoveEvent event) {final Player p = event.getPlayer();int foodLevel;int delay = 0;if (p.getRemainingAir() < p.getMaximumAir()) {p.setRemainingAir(p.getMaximumAir());delay += 1;if (delay == 5) {foodLevel = p.getFoodLevel() + 1;p.setFoodLevel(foodLevel);delay = 0;}}} I can totaly understand why this does not work. So. How would I do it that it counts for each individual player how often he triggered that event and how to set that to 0 then again once destinated point is arrived so the player gets the foodRegeneration. Or would anyone suggest me using a different way to solve this issue?
If you want them to regenerate health/hunger slower, you will have to use a scheduler. If that's what you're wanting, I can give an example.
chasechocolate thanks :3 Never worked with scheduler. But this should do the trick or? Code:java @EventHandlerpublic final void onDrownEvent(final PlayerMoveEvent event) {if (p.getRemainingAir() < p.getMaximumAir()) {p.setRemainingAir(p.getMaximumAir());plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {public void run() {p.setFoodLevel(p.getFoodLevel() + 1);}}, 10L);}} Edit: Ok. It does work semi. This is the current status.. If the player moves underwater it waits the 10 ticks and then it keeps repeating the p.setFoodLevel(p.getFoodLevel() + 1); How can I make it that it waits the 10 ticks, run it ONCE, wait the 10 ticks again run it ONCE, and so on?
To make it so it runs less often, make it so the player has to lose more air before incrementing the player's food level. Code: @EventHandler public final void onDrownEvent(final PlayerMoveEvent event) { if (p.getRemainingAir() < p.getMaximumAir() - 20) { p.setRemainingAir(p.getMaximumAir()); p.setFoodLevel(p.getFoodLevel() + 1); } } The change is at Code: p.getRemainingAir() < p.getMaximumAir() - 20 Set - 20 higher or lower until you're satisfied.
kabbage Ok. your adjustment is good. Will need to work a bit on that until it satisfy my need However I entered a Code:java p.sentMessage("ok"); in the run() method and I figured out once started it runs endless, even if I am above the water D: Edit: Never mind what I posted above. It runs it in total the ammount of the breath was set to maximum again. Means if the delay is so big that the breath was set 7times back to maximum the regenerate event will run 7 times no matter if I am not underwater anymore. I will see if I can fix that :3 If someone has an Idea how it satisfies my needs then He/She is welcome to post.
If you tell me how that works that would be great? Thats why I did the "workarround" with the remaining health to check if he is underwater or not
Code:java Location loc = player.getLocation();Block feet = player.getLocation().getBlock();Block head = player.getLocation().add(0, 1, 0).getBlock(); if((feet.getType() == Material.WATER || feet.getType() == Material.STATIONARY_WATER) && (head.getType() == Material.WATER || head.getType() == Material.STATIONARY_WATER)){ //They are in water}
Wow thanks :3 Now after looking at it I feel somehow stupid not comming up with that Idea but making the breath work arround. lol. Thanks! Ok. Sorry to bother again. It's not solved yet.. Now it gets when I am underwater. But the code withing the run() runs for the first time after the delay is over. BUT continues from there on WITHOUT delay as often as the event was triggered.. What I want (and I have no Idea how to do it) everything within Code:java public void run() {} should run after the delay ONCE, then get a delay again then run again ONCE and ONLY if the player is under water. However. Following Code makes as descriped at the top of this post. It "stacks" up and then run even outside of the water Code:java @EventHandlerpublic final void onDrownEvent(final PlayerMoveEvent event) {final int delay = 100;final Player p = event.getPlayer();final Location loc = p.getLocation();final Block feet = loc.getBlock();final Block head = loc.add(0, 1, 0).getBlock(); if ((feet.getType() == Material.WATER|| feet.getType() == Material.STATIONARY_WATER)&& (head.getType() == Material.WATER|| head.getType() == Material.STATIONARY_WATER)) {//They are in waterp.setRemainingAir(p.getMaximumAir());plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {public void run() {p.setFoodLevel(p.getFoodLevel() + 1);}}, delay);}} I got the feeling that I most likely need to use a different Event than PlayerMoveEvent. If I do it as mentioned earlyer only if certain amount of air is gone it makes the delay between each usage. But However. it will still run while the player is outside the water (without affecting the foodbar though). Is there a way to prevent that or do I have to live with it? Ok. To bump it I will not edit my Post. This is my current situation now. I got it to work that between each of the run() method is a delay that way Code:java @EventHandler public void underWaterFoodRegeneration(final PlayerMoveEvent event) { final Player player = event.getPlayer(); final long delay = 200; final Location loc = player.getLocation(); final Block feet = loc.getBlock(); final Block head = loc.add(0, 1, 0).getBlock(); if ((feet.getType() == Material.WATER || feet.getType() == Material.STATIONARY_WATER) && (head.getType() == Material.WATER || head.getType() == Material.STATIONARY_WATER)) { // They are in water plugin.getServer().getScheduler() .runTaskTimer(plugin, new Runnable() { public void run() { player.setFoodLevel(player.getFoodLevel() + 1); plugin.getServer().getScheduler() .cancelTasks(plugin); } }, delay, delay); } } Now it would be great, that all scheduled tasks get canceled in the second the player is NOT underneath the water anymore. Is that possible? EDIT by Moderator: merged posts, please use the edit button instead of double posting.