Implement different flight types

This commit is contained in:
Sollace 2020-10-08 09:39:30 +02:00
parent 6f2ef7719a
commit 629f30be0e
10 changed files with 85 additions and 63 deletions

View file

@ -0,0 +1,24 @@
package com.minelittlepony.unicopia;
public enum FlightType {
NONE,
CREATIVE,
AVIAN,
INSECTOID;
public boolean isGrounded() {
return this == NONE;
}
public boolean canFly() {
return !isGrounded();
}
public boolean canFlyCreative() {
return this == CREATIVE || this == INSECTOID;
}
public boolean canFlySurvival() {
return canFly() && !canFlyCreative();
}
}

View file

@ -21,21 +21,21 @@ public enum Race implements Affine {
* The default, unset race. * The default, unset race.
* This is used if there are no other races. * This is used if there are no other races.
*/ */
HUMAN(false, false, false), HUMAN(false, FlightType.NONE, false),
EARTH(false, false, true), EARTH(false, FlightType.NONE, true),
UNICORN(true, false, false), UNICORN(true, FlightType.NONE, false),
PEGASUS(false, true, false), PEGASUS(false, FlightType.AVIAN, false),
BAT(false, true, false), BAT(false, FlightType.AVIAN, false),
ALICORN(true, true, true), ALICORN(true, FlightType.AVIAN, true),
CHANGELING(false, true, false); CHANGELING(false, FlightType.INSECTOID, false);
private final boolean magic; private final boolean magic;
private final boolean flight; private final FlightType flight;
private final boolean earth; private final boolean earth;
private final static Map<Integer, Race> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Enum::ordinal, Function.identity())); private final static Map<Integer, Race> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Enum::ordinal, Function.identity()));
Race(boolean magic, boolean flight, boolean earth) { Race(boolean magic, FlightType flight, boolean earth) {
this.magic = magic; this.magic = magic;
this.flight = flight; this.flight = flight;
this.earth = earth; this.earth = earth;
@ -62,10 +62,14 @@ public enum Race implements Affine {
return this == ALICORN; return this == ALICORN;
} }
public boolean canFly() { public FlightType getFlightType() {
return flight; return flight;
} }
public boolean canFly() {
return !getFlightType().isGrounded();
}
public boolean canCast() { public boolean canCast() {
return magic; return magic;
} }

View file

@ -1,5 +1,6 @@
package com.minelittlepony.unicopia.ability; package com.minelittlepony.unicopia.ability;
import com.minelittlepony.unicopia.FlightType;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
/** /**
@ -8,5 +9,5 @@ import com.minelittlepony.unicopia.entity.player.Pony;
* This overrides what the race specifies. * This overrides what the race specifies.
*/ */
public interface FlightPredicate { public interface FlightPredicate {
boolean checkCanFly(Pony player); FlightType getFlightType(Pony player);
} }

View file

@ -40,11 +40,6 @@ public interface Spell extends NbtSerialisable, Affine {
*/ */
void setDirty(boolean dirty); void setDirty(boolean dirty);
/**
* Returns true if this effect can be crafted into a gem.
*/
boolean isCraftable();
/** /**
* Gets the highest level this spell can be safely operated at. * Gets the highest level this spell can be safely operated at.
* Gems may go higher, however chance of explosion/exhaustion increases with every level. * Gems may go higher, however chance of explosion/exhaustion increases with every level.

View file

@ -10,11 +10,6 @@ public abstract class AbstractSpell implements Spell {
protected boolean isDead; protected boolean isDead;
protected boolean isDirty; protected boolean isDirty;
@Override
public boolean isCraftable() {
return true;
}
@Override @Override
public void setDead() { public void setDead() {
isDead = true; isDead = true;

View file

@ -5,6 +5,7 @@ import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.FlightType;
import com.minelittlepony.unicopia.Owned; import com.minelittlepony.unicopia.Owned;
import com.minelittlepony.unicopia.ability.FlightPredicate; import com.minelittlepony.unicopia.ability.FlightPredicate;
import com.minelittlepony.unicopia.ability.DimensionsPredicate; import com.minelittlepony.unicopia.ability.DimensionsPredicate;
@ -37,11 +38,6 @@ public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Sup
return "disguise"; return "disguise";
} }
@Override
public boolean isCraftable() {
return false;
}
@Override @Override
public Affinity getAffinity() { public Affinity getAffinity() {
return Affinity.BAD; return Affinity.BAD;
@ -211,8 +207,11 @@ public class DisguiseSpell extends AbstractSpell implements AttachableSpell, Sup
} }
@Override @Override
public boolean checkCanFly(Pony player) { public FlightType getFlightType(Pony player) {
return disguise.canFly() && player.getSpecies().canFly(); if (isSuppressed() || !disguise.isPresent()) {
return player.getSpecies().getFlightType();
}
return disguise.getFlightType();
} }
@Override @Override

View file

@ -24,11 +24,6 @@ public class ScorchSpell extends FireSpell implements ThrowableSpell {
return "scorch"; return "scorch";
} }
@Override
public boolean isCraftable() {
return false;
}
@Override @Override
public int getTint() { public int getTint() {
return 0; return 0;

View file

@ -157,11 +157,9 @@ public class SpellRegistry {
this.color = inst.getTint(); this.color = inst.getTint();
this.affinity = inst.getAffinity(); this.affinity = inst.getAffinity();
if (inst.isCraftable()) {
for (Affinity affinity : affinity.getImplicators()) { for (Affinity affinity : affinity.getImplicators()) {
keysByAffinity.computeIfAbsent(affinity, a -> new HashSet<>()).add(inst.getName()); keysByAffinity.computeIfAbsent(affinity, a -> new HashSet<>()).add(inst.getName());
} }
}
entries.put(inst.getName(), this); entries.put(inst.getName(), this);
} }

View file

@ -8,6 +8,7 @@ import java.util.UUID;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.minelittlepony.unicopia.FlightType;
import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.Owned; import com.minelittlepony.unicopia.Owned;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
@ -163,25 +164,29 @@ public class Disguise implements NbtSerialisable {
} }
} }
public boolean canFly() { public FlightType getFlightType() {
if (entity == null) { if (entity == null) {
return false; return FlightType.NONE;
} }
if (entity instanceof Owned) { if (entity instanceof Owned) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Pony iplayer = Pony.of(((Owned<PlayerEntity>)entity).getOwner()); Pony iplayer = Pony.of(((Owned<PlayerEntity>)entity).getOwner());
return iplayer != null && iplayer.getSpecies().canFly(); return iplayer == null ? FlightType.NONE : iplayer.getSpecies().getFlightType();
} }
return entity instanceof FlyingEntity if (entity instanceof FlyingEntity
|| entity instanceof AmbientEntity || entity instanceof AmbientEntity
|| entity instanceof EnderDragonEntity || entity instanceof EnderDragonEntity
|| entity instanceof VexEntity || entity instanceof VexEntity
|| entity instanceof ShulkerBulletEntity || entity instanceof ShulkerBulletEntity
|| entity instanceof Flutterer || entity instanceof Flutterer
|| ProjectileUtil.isProjectile(entity); || ProjectileUtil.isProjectile(entity)) {
return FlightType.INSECTOID;
}
return FlightType.NONE;
} }
public float getStandingEyeHeight() { public float getStandingEyeHeight() {

View file

@ -1,5 +1,6 @@
package com.minelittlepony.unicopia.entity.player; package com.minelittlepony.unicopia.entity.player;
import com.minelittlepony.unicopia.FlightType;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.FlightPredicate; import com.minelittlepony.unicopia.ability.FlightPredicate;
@ -79,10 +80,12 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
boolean creative = entity.abilities.creativeMode || pony.getOwner().isSpectator(); boolean creative = entity.abilities.creativeMode || pony.getOwner().isSpectator();
boolean canFly = checkCanFly(); FlightType type = getFlightType();
entity.abilities.allowFlying = type.canFlyCreative();
if (!creative) { if (!creative) {
entity.abilities.flying |= (canFly || entity.abilities.allowFlying) && isFlyingEither; entity.abilities.flying |= (type.canFly() || entity.abilities.allowFlying) && isFlyingEither;
if ((entity.isOnGround() && entity.isSneaking()) if ((entity.isOnGround() && entity.isSneaking())
|| entity.isTouchingWater() || entity.isTouchingWater()
@ -110,7 +113,7 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
} }
} }
if (canFly) { if (type.canFly()) {
if (isFlying()) { if (isFlying()) {
if (pony.getSpecies() == Race.BAT && entity.verticalCollision && pony.canHangAt(pony.getOrigin().up(2))) { if (pony.getSpecies() == Race.BAT && entity.verticalCollision && pony.canHangAt(pony.getOrigin().up(2))) {
@ -146,12 +149,15 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
} }
entity.fallDistance = 0; entity.fallDistance = 0;
if (type == FlightType.AVIAN) {
applyThrust(entity, velocity);
}
moveFlying(entity, velocity); moveFlying(entity, velocity);
if (entity.world.hasRain(entity.getBlockPos())) { if (entity.world.hasRain(entity.getBlockPos())) {
applyTurbulance(entity, velocity); applyTurbulance(entity, velocity);
} }
if (type == FlightType.AVIAN) {
if (entity.world.isClient && ticksInAir % 20 == 0 && entity.getVelocity().length() < 0.29) { if (entity.world.isClient && ticksInAir % 20 == 0 && entity.getVelocity().length() < 0.29) {
entity.playSound(getWingSound(), 0.5F, 1); entity.playSound(getWingSound(), 0.5F, 1);
thrustScale = 1; thrustScale = 1;
@ -159,10 +165,11 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
velocity.y -= 0.02; velocity.y -= 0.02;
velocity.x *= 0.9896; velocity.x *= 0.9896;
velocity.z *= 0.9896; velocity.z *= 0.9896;
}
} else { } else {
ticksInAir = 0; ticksInAir = 0;
if (!creative) { if (!creative && type == FlightType.AVIAN) {
double horMotion = getHorizontalMotion(entity); double horMotion = getHorizontalMotion(entity);
double motion = entity.getPos().subtract(lastPos).lengthSquared(); double motion = entity.getPos().subtract(lastPos).lengthSquared();
@ -219,8 +226,6 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
} }
protected void moveFlying(PlayerEntity player, MutableVector velocity) { protected void moveFlying(PlayerEntity player, MutableVector velocity) {
applyThrust(player, velocity);
double motion = getHorizontalMotion(player); double motion = getHorizontalMotion(player);
float forward = 0.000015F * (1 + (pony.getLevel().get() / 10F)) * (float)Math.sqrt(motion); float forward = 0.000015F * (1 + (pony.getLevel().get() / 10F)) * (float)Math.sqrt(motion);
@ -292,29 +297,30 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
return Entity.squaredHorizontalLength(e.getPos().subtract(lastPos)); return Entity.squaredHorizontalLength(e.getPos().subtract(lastPos));
} }
private boolean checkCanFly() { private FlightType getFlightType() {
if (pony.getOwner().abilities.creativeMode || pony.getOwner().isSpectator()) { if (pony.getOwner().isCreative() || pony.getOwner().isSpectator()) {
return true; return FlightType.CREATIVE;
} }
if (pony.hasSpell()) { if (pony.hasSpell()) {
Spell effect = pony.getSpell(true); Spell effect = pony.getSpell(true);
if (!effect.isDead() && effect instanceof FlightPredicate) { if (!effect.isDead() && effect instanceof FlightPredicate) {
return ((FlightPredicate)effect).checkCanFly(pony); return ((FlightPredicate)effect).getFlightType(pony);
} }
} }
return pony.getSpecies().canFly(); return pony.getSpecies().getFlightType();
} }
public void updateFlightStat(boolean flying) { public void updateFlightStat(boolean flying) {
PlayerEntity entity = pony.getOwner(); PlayerEntity entity = pony.getOwner();
boolean canFly = checkCanFly(); FlightType type = getFlightType();
if (canFly || entity.abilities.allowFlying) { entity.abilities.allowFlying = type.canFlyCreative();
if (type.canFly() || entity.abilities.allowFlying) {
entity.abilities.flying |= flying; entity.abilities.flying |= flying;
isFlyingSurvival = entity.abilities.flying; isFlyingSurvival = entity.abilities.flying;
} else { } else {
entity.abilities.flying = false; entity.abilities.flying = false;