mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Allow spells to animate post-removal
This commit is contained in:
parent
5356c5c7ec
commit
a19637a8e4
8 changed files with 95 additions and 6 deletions
|
@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.InteractionManager;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
@ -92,7 +93,11 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
public boolean apply(Pony player, Pos data) {
|
||||
player.setAnimation(Animation.WOLOLO, Animation.Recipient.ANYONE);
|
||||
Caster.stream(VecHelper.findInRange(player.asEntity(), player.asWorld(), data.vec(), 3, EquinePredicates.IS_PLACED_SPELL).stream()).forEach(target -> {
|
||||
target.getSpellSlot().clear();
|
||||
target.getSpellSlot().forEach(spell -> {
|
||||
spell.setDead();
|
||||
spell.tickDying(target);
|
||||
return Operation.ofBoolean(!spell.isDead());
|
||||
}, true);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -69,11 +69,20 @@ public abstract class AbstractDelegatingSpell implements Spell,
|
|||
getDelegates().forEach(Spell::setDead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickDying(Caster<?> caster) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return getDelegates().isEmpty() || getDelegates().stream().allMatch(Spell::isDead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDying() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return dirty || getDelegates().stream().anyMatch(Spell::isDirty);
|
||||
|
@ -110,7 +119,13 @@ public abstract class AbstractDelegatingSpell implements Spell,
|
|||
|
||||
@Override
|
||||
public boolean tick(Caster<?> source, Situation situation) {
|
||||
return execute(getDelegates().stream(), a -> a.tick(source, situation));
|
||||
return execute(getDelegates().stream(), a -> {
|
||||
if (a.isDying()) {
|
||||
a.tickDying(source);
|
||||
return !a.isDead();
|
||||
}
|
||||
return a.tick(source, situation);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,6 +59,10 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
private int prevAge;
|
||||
private int age;
|
||||
|
||||
private boolean dead;
|
||||
private int prevDeathTicks;
|
||||
private int deathTicks;
|
||||
|
||||
private Optional<Vec3d> position = Optional.empty();
|
||||
|
||||
public PlaceableSpell(CustomisedSpellType<?> type) {
|
||||
|
@ -74,6 +78,29 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
return MathHelper.lerp(tickDelta, prevAge, age);
|
||||
}
|
||||
|
||||
public float getScale(float tickDelta) {
|
||||
float add = MathHelper.clamp(getAge(tickDelta) / 25F, 0, 1);
|
||||
float subtract = dead ? 1 - (MathHelper.lerp(tickDelta, prevDeathTicks, deathTicks) / 20F) : 0;
|
||||
return MathHelper.clamp(add - subtract, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDying() {
|
||||
return dead && deathTicks > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead() {
|
||||
super.setDead();
|
||||
dead = true;
|
||||
deathTicks = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return dead && deathTicks <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Spell> getDelegates() {
|
||||
return List.of(spell);
|
||||
|
@ -119,6 +146,12 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
return !isDead();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickDying(Caster<?> caster) {
|
||||
prevDeathTicks = deathTicks;
|
||||
deathTicks--;
|
||||
}
|
||||
|
||||
private void checkDetachment(Caster<?> source, EntityValues<?> target) {
|
||||
if (getWorld(source).map(Ether::get).map(ether -> ether.get(getType(), target, placedSpellId)).isEmpty()) {
|
||||
setDead();
|
||||
|
@ -198,6 +231,8 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
super.toNBT(compound);
|
||||
compound.putBoolean("dead", dead);
|
||||
compound.putInt("deathTicks", deathTicks);
|
||||
compound.putInt("age", age);
|
||||
compound.putFloat("pitch", pitch);
|
||||
compound.putFloat("yaw", yaw);
|
||||
|
@ -217,6 +252,8 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
super.fromNBT(compound);
|
||||
dead = compound.getBoolean("dead");
|
||||
deathTicks = compound.getInt("deathTicks");
|
||||
age = compound.getInt("age");
|
||||
pitch = compound.getFloat("pitch");
|
||||
yaw = compound.getFloat("yaw");
|
||||
|
|
|
@ -61,6 +61,8 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
*/
|
||||
boolean isDead();
|
||||
|
||||
boolean isDying();
|
||||
|
||||
/**
|
||||
* Returns true if this effect has changes that need to be sent to the client.
|
||||
*/
|
||||
|
@ -68,6 +70,7 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
|
||||
/**
|
||||
* Applies this spell to the supplied caster.
|
||||
* @param caster The caster to apply the spell to
|
||||
*/
|
||||
default boolean apply(Caster<?> caster) {
|
||||
caster.getSpellSlot().put(this);
|
||||
|
@ -76,7 +79,7 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
|
||||
/**
|
||||
* Gets the default form of this spell used to apply to a caster.
|
||||
* @param caster
|
||||
* @param caster The caster currently fueling this spell
|
||||
*/
|
||||
default Spell prepareForCast(Caster<?> caster, CastingMethod method) {
|
||||
return this;
|
||||
|
@ -89,6 +92,12 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
*/
|
||||
boolean tick(Caster<?> caster, Situation situation);
|
||||
|
||||
/**
|
||||
* Called on spells that are actively dying to update any post-death animations before removal.
|
||||
* @param caster The caster currently fueling this spell
|
||||
*/
|
||||
void tickDying(Caster<?> caster);
|
||||
|
||||
/**
|
||||
* Marks this effect as dirty.
|
||||
*/
|
||||
|
|
|
@ -12,6 +12,7 @@ import net.minecraft.nbt.NbtCompound;
|
|||
public abstract class AbstractSpell implements Spell {
|
||||
|
||||
private boolean dead;
|
||||
private boolean dying;
|
||||
private boolean dirty;
|
||||
private boolean hidden;
|
||||
private boolean destroyed;
|
||||
|
@ -45,7 +46,7 @@ public abstract class AbstractSpell implements Spell {
|
|||
|
||||
@Override
|
||||
public final void setDead() {
|
||||
dead = true;
|
||||
dying = true;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
|
@ -54,6 +55,11 @@ public abstract class AbstractSpell implements Spell {
|
|||
return dead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDying() {
|
||||
return dying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDirty() {
|
||||
return dirty;
|
||||
|
@ -82,6 +88,11 @@ public abstract class AbstractSpell implements Spell {
|
|||
protected void onDestroyed(Caster<?> caster) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickDying(Caster<?> caster) {
|
||||
dead = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void destroy(Caster<?> caster) {
|
||||
if (destroyed) {
|
||||
|
@ -94,6 +105,7 @@ public abstract class AbstractSpell implements Spell {
|
|||
|
||||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
compound.putBoolean("dying", dying);
|
||||
compound.putBoolean("dead", dead);
|
||||
compound.putBoolean("hidden", hidden);
|
||||
compound.putUuid("uuid", uuid);
|
||||
|
@ -106,6 +118,7 @@ public abstract class AbstractSpell implements Spell {
|
|||
if (compound.contains("uuid")) {
|
||||
uuid = compound.getUuid("uuid");
|
||||
}
|
||||
dying = compound.getBoolean("dying");
|
||||
dead = compound.getBoolean("dead");
|
||||
hidden = compound.getBoolean("hidden");
|
||||
if (compound.contains("traits")) {
|
||||
|
|
|
@ -57,7 +57,7 @@ public class PlacedSpellRenderer extends SpellRenderer<PlaceableSpell> {
|
|||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - spell.yaw));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||
|
||||
float scale = (spell.getAge(tickDelta) / 25F) * 3;
|
||||
float scale = spell.getScale(tickDelta) * 3;
|
||||
matrices.scale(scale, scale, scale);
|
||||
|
||||
float angle = (animationProgress / 9F) % 360;
|
||||
|
|
|
@ -72,6 +72,10 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
|
|||
}
|
||||
}
|
||||
|
||||
protected void updatePostDeath() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityReference<LivingEntity> getMasterReference() {
|
||||
return owner;
|
||||
|
|
|
@ -44,7 +44,13 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
}
|
||||
|
||||
public boolean tick(Situation situation) {
|
||||
return tick(spell -> Operation.ofBoolean(spell.tick(owner, situation)));
|
||||
return tick(spell -> {
|
||||
if (spell.isDying()) {
|
||||
spell.tickDying(owner);
|
||||
return Operation.ofBoolean(!spell.isDead());
|
||||
}
|
||||
return Operation.ofBoolean(spell.tick(owner, situation));
|
||||
});
|
||||
}
|
||||
|
||||
public boolean tick(Function<Spell, Operation> tickAction) {
|
||||
|
|
Loading…
Reference in a new issue