Skip to content

Commit

Permalink
[BREAKING] Fix fall damage with jump effect (for most).
Browse files Browse the repository at this point in the history
Only count the fall height below the set back y from lift-off (rather).

Breaking:
* Adjust method signatures and public visibility / interface for NoFall.
  • Loading branch information
asofold committed Feb 6, 2018
1 parent f6519ef commit ad87137
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 15 deletions.
Expand Up @@ -683,8 +683,10 @@ else if (cc.creativeFlyCheck

// TODO: More adaptive margin / method (bounding boxes).
final boolean useBlockChangeTracker;
final double previousSetBackY;

if (checkSf || checkCf) {
previousSetBackY = data.hasSetBack() ? data.getSetBackY() : Double.NEGATIVE_INFINITY;
// Ensure we have a set back set.
MovingUtil.checkSetBack(player, pFrom, data, this);

Expand Down Expand Up @@ -771,6 +773,7 @@ && onPreparedBounceSupport(player, from, to, thisMove, lastMove, tick, data)
else {
// TODO: Might still allow block change tracker with only passable enabled.
useBlockChangeTracker = false;
previousSetBackY = Double.NEGATIVE_INFINITY;
}

// Check passable first to prevent set back override.
Expand Down Expand Up @@ -826,12 +829,12 @@ && onPreparedBounceSupport(player, from, to, thisMove, lastMove, tick, data)
}
// NoFall.
if (checkNf) {
noFall.check(player, pFrom, pTo, data, cc);
noFall.check(player, pFrom, pTo, previousSetBackY, data, cc);
}
}
else {
if (checkNf && cc.sfSetBackPolicyFallDamage) {
if (noFall.estimateDamage(player, from.getY(), data) < 1.0) {
if (!noFall.willDealFallDamage(player, from.getY(), previousSetBackY, data)) {
// TODO: Consider making this / damage amount configurable.
mightSkipNoFall = true;
}
Expand Down Expand Up @@ -2160,8 +2163,9 @@ else if (noFallVL(player, "fakefall", data, cc)) {
}
}
aux.returnPlayerMoveInfo(moveInfo);
// Fall-back check.
final double maxD = NoFall.getDamage(Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance))) + (allowReset ? 0.0 : Magic.FALL_DAMAGE_DIST);
// Fall-back check (skip with jump amplifier).
final double maxD = data.jumpAmplifier > 0.0 ? NoFall.getDamage((float) NoFall.getApplicableFallHeight(player, loc.getY(), data))
: NoFall.getDamage(Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance))) + (allowReset ? 0.0 : Magic.FALL_DAMAGE_DIST);
if (maxD > damage) {
// TODO: respect dealDamage ?
BridgeHealth.setDamage(event, maxD);
Expand Down
Expand Up @@ -96,6 +96,8 @@ public class Magic {

/** The lower bound of fall distance for taking fall damage. */
public static final double FALL_DAMAGE_DIST = 3.0;
/** The minimum damage amount that actually should get applied. */
public static final double FALL_DAMAGE_MINIMUM = 1.0;

/**
* The maximum distance that can be achieved with bouncing back from slime
Expand Down
Expand Up @@ -66,11 +66,17 @@ public static final double getDamage(final float fallDistance) {
* @param mcPlayer
* @param data
* @param y
* @param previousSetBackY
* The set back y from lift-off. If not present:
* Double.NEGATIVE_INFINITY.
*/
private void handleOnGround(final Player player, final double y, final boolean reallyOnGround, final MovingData data, final MovingConfig cc) {
private void handleOnGround(final Player player, final double y, final double previousSetBackY,
final boolean reallyOnGround, final MovingData data, final MovingConfig cc) {
// Damage to be dealt.
final double maxD = estimateDamage(player, y, data);
if (maxD >= 1.0) {
final float fallDist = (float) getApplicableFallHeight(player, y, previousSetBackY, data);
final double maxD = getDamage(fallDist);

if (maxD >= Magic.FALL_DAMAGE_MINIMUM) {
// Check skipping conditions.
if (cc.noFallSkipAllowFlight && player.getAllowFlight()) {
data.clearNoFallData();
Expand All @@ -95,15 +101,54 @@ private void handleOnGround(final Player player, final double y, final boolean r
}

/**
* Convenience method to estimate fall damage at a certain y-level, checking data and mc-fall-distance.
* Estimate the applicable fall height for the given data.
*
* @param player
* @param y
* @param previousSetBackY
* The set back y from lift-off. If not present:
* Double.NEGATIVE_INFINITY.
* @param data
* @return
*/
public double estimateDamage(final Player player, final double y, final MovingData data) {
private static double getApplicableFallHeight(final Player player, final double y,
final double previousSetBackY, final MovingData data) {
//return getDamage(Math.max((float) (data.noFallMaxY - y), Math.max(data.noFallFallDistance, player.getFallDistance())));
return getDamage(Math.max((float) (data.noFallMaxY - y), data.noFallFallDistance));
final double yDistance = Math.max(data.noFallMaxY - y, data.noFallFallDistance);
if (yDistance > 0.0 && data.jumpAmplifier > 0.0
&& previousSetBackY != Double.NEGATIVE_INFINITY) {
// Fall height counts below previous set-back-y.
// TODO: Likely updating the amplifier after lift-off doesn't make sense.
// TODO: In case of velocity... skip too / calculate max exempt height?
final double correction = data.noFallMaxY - previousSetBackY;
if (correction > 0.0) {
final float effectiveDistance = (float) Math.max(0.0, yDistance - correction);
return effectiveDistance;
}
}
return yDistance;
}

public static double getApplicableFallHeight(final Player player, final double y, final MovingData data) {
return getApplicableFallHeight(player, y,
data.hasSetBack() ? data.getSetBackY() : Double.NEGATIVE_INFINITY, data);
}

/**
* Test if fall damage would be dealt accounting for the given data.
*
* @param player
* @param y
* @param previousSetBackY
* The set back y from lift-off. If not present:
* Double.NEGATIVE_INFINITY.
* @param data
* @return
*/
public boolean willDealFallDamage(final Player player, final double y,
final double previousSetBackY, final MovingData data) {
return getDamage((float) getApplicableFallHeight(player, y,
previousSetBackY, data)) - Magic.FALL_DAMAGE_DIST >= Magic.FALL_DAMAGE_MINIMUM;
}

/**
Expand Down Expand Up @@ -158,8 +203,12 @@ private void dealFallDamage(final Player player, final double damage) {
* the from
* @param to
* the to
* @param previousSetBackY
* The set back y from lift-off. If not present:
* Double.NEGATIVE_INFINITY.
*/
public void check(final Player player, final PlayerLocation pFrom, final PlayerLocation pTo,
final double previousSetBackY,
final MovingData data, final MovingConfig cc) {

final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
Expand Down Expand Up @@ -211,7 +260,7 @@ public void check(final Player player, final PlayerLocation pFrom, final PlayerL
}
else if (fromOnGround || !toOnGround && thisMove.touchedGround) {
// Check if to deal damage (fall back damage check).
touchDown(player, minY, data, cc); // Includes the current y-distance on descend!
touchDown(player, minY, previousSetBackY, data, cc); // Includes the current y-distance on descend!
// Ensure very big/strange moves don't yield violations.
if (toY - fromY <= -Magic.FALL_DAMAGE_DIST) {
data.noFallSkipAirCheck = true;
Expand All @@ -227,7 +276,7 @@ else if (toOnGround) {
// In this case the player has traveled further: add the difference.
data.noFallFallDistance -= yDiff;
}
touchDown(player, minY, data, cc);
touchDown(player, minY, previousSetBackY, data, cc);
}
else {
// Ensure fall distance is correct, or "anyway"?
Expand Down Expand Up @@ -272,14 +321,19 @@ else if (cc.noFallAntiCriticals && (toReset || toOnGround || (fromReset || fromO

/**
* Called during check.
*
* @param player
* @param minY
* @param previousSetBackY
* The set back y from lift-off. If not present:
* Double.NEGATIVE_INFINITY.
* @param data
* @param cc
*/
private void touchDown(final Player player, final double minY, final MovingData data, final MovingConfig cc) {
private void touchDown(final Player player, final double minY, final double previousSetBackY,
final MovingData data, final MovingConfig cc) {
if (cc.noFallDealDamage) {
handleOnGround(player, minY, true, data, cc);
handleOnGround(player, minY, previousSetBackY, true, data, cc);
}
else {
adjustFallDistance(player, minY, true, data, cc);
Expand Down Expand Up @@ -336,7 +390,8 @@ public void onLeave(final Player player) {
public void checkDamage(final Player player, final MovingData data, final double y) {
final MovingConfig cc = MovingConfig.getConfig(player);
// Deal damage.
handleOnGround(player, y, false, data, cc);
handleOnGround(player, y, data.hasSetBack() ? data.getSetBackY() : Double.NEGATIVE_INFINITY,
false, data, cc);
}

/**
Expand Down

0 comments on commit ad87137

Please sign in to comment.