Rework Root Target.

This commit completely reworks the Root Target ability implementation by
replacing the repeated teleportation code with potion effects.

The old implementation relied on teleporting the target every tick for a
given duration, but because teleporting also involves pitch and yaw, the
result was a constant "snapping back in place" experience.

The new implementation works by applying the following potion effects
with a very large amplification:

- Slowness, to prevent the player from moving out of place.
- Slow falling, to negate fall damage.
- Negative jump boost, to prevent the player from jumping around.

Note that the jump boost uses a _negative_ amplification to make it have
the inverse effect, i.e. a much worse jump ability. It is still possible
to jump an arguably negligible amount away from the root location.

Fixes #490
This commit is contained in:
Nesseley 2020-05-04 07:49:20 +02:00 committed by Andreas Troelsen
parent e8cce8e620
commit 7e37d93a0e
2 changed files with 10 additions and 54 deletions

View File

@ -15,6 +15,7 @@ These changes will (most likely) be included in the next version.
- Arena signs now support dynamic list entry variables for 4 different player lists. As an example, `<notready-1>` results in the name of a player in the lobby who hasn't readied up yet. This is useful for visualizing who is holding up the lobby. Check the wiki for details. - Arena signs now support dynamic list entry variables for 4 different player lists. As an example, `<notready-1>` results in the name of a player in the lobby who hasn't readied up yet. This is useful for visualizing who is holding up the lobby. Check the wiki for details.
- Elytra are now supported chest pieces in class chests. - Elytra are now supported chest pieces in class chests.
- Boss names now support color codes. - Boss names now support color codes.
- The Root Target ability now uses potion effects (slowness, slow falling, and negative jump boost) instead of repeated teleports. This should make for a smoother root experience.
- Config-files with missing `pet-items` nodes no longer errors. A missing `pet-items` node in `global-settings` is treated as empty, i.e. no pet items will be registered. - Config-files with missing `pet-items` nodes no longer errors. A missing `pet-items` node in `global-settings` is treated as empty, i.e. no pet items will be registered.
## [0.104.2] - 2020-01-03 ## [0.104.2] - 2020-01-03

View File

@ -1,16 +1,14 @@
package com.garbagemule.MobArena.waves.ability.core; package com.garbagemule.MobArena.waves.ability.core;
import com.garbagemule.MobArena.framework.Arena; import com.garbagemule.MobArena.framework.Arena;
import com.garbagemule.MobArena.region.ArenaRegion;
import com.garbagemule.MobArena.waves.MABoss; import com.garbagemule.MobArena.waves.MABoss;
import com.garbagemule.MobArena.waves.ability.Ability; import com.garbagemule.MobArena.waves.ability.Ability;
import com.garbagemule.MobArena.waves.ability.AbilityInfo; import com.garbagemule.MobArena.waves.ability.AbilityInfo;
import com.garbagemule.MobArena.waves.ability.AbilityUtils; import com.garbagemule.MobArena.waves.ability.AbilityUtils;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
/** /**
* DISCLAIMER: The Ability source code is provided as-is, and the creator(s) of * DISCLAIMER: The Ability source code is provided as-is, and the creator(s) of
@ -36,16 +34,14 @@ import org.bukkit.entity.Player;
public class RootTarget implements Ability public class RootTarget implements Ability
{ {
/** /**
* How many times the player will be warped back to his original position. * How long the the potions last (in ticks).
* Must be greater than 0.
*/ */
private static final int ITERATIONS = 30; private static final int DURATION = 30;
/** /**
* How many server ticks between each iteration of * The amplifier for the potions.
* Must be greater than 0.
*/ */
private static final int TICKS = 1; private static final int AMPLIFIER = 100;
@Override @Override
public void execute(Arena arena, MABoss boss) { public void execute(Arena arena, MABoss boss) {
@ -54,49 +50,8 @@ public class RootTarget implements Ability
return; return;
Player player = (Player) target; Player player = (Player) target;
ArenaRegion region = arena.getRegion(); player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, DURATION, AMPLIFIER));
player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, DURATION, AMPLIFIER));
Block block = player.getLocation().getBlock(); player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, DURATION, -AMPLIFIER));
Block solid = findSolidBlockBelow(region, block);
Location location = player.getLocation();
location.setY(solid.getLocation().getY() + 1);
rootTarget(arena, player, location, ITERATIONS);
}
private Block findSolidBlockBelow(ArenaRegion region, Block block) {
Block below = block.getRelative(BlockFace.DOWN);
// If the block below is not in the region, return the block itself
if (!region.contains(below.getLocation())) {
return block;
}
// If the block below is solid, return it
if (below.getType().isSolid()) {
return below;
}
// Otherwise, recurse downwards
return findSolidBlockBelow(region, below);
}
private void rootTarget(final Arena arena, final Player p, final Location loc, final int counter) {
// If the counter is 0, we're done.
if (counter <= 0) {
return;
}
arena.scheduleTask(new Runnable() {
public void run() {
if (!arena.isRunning() || !arena.inArena(p)) {
return;
}
p.teleport(loc);
rootTarget(arena, p, loc, counter - 1);
}
}, TICKS);
} }
} }