Improved animations when casting or dispelling spells and added animations when using magic staffs. #151

This commit is contained in:
Sollace 2023-08-05 15:45:36 +01:00
parent 3dec711b78
commit b337709f78
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
20 changed files with 304 additions and 168 deletions

View file

@ -76,7 +76,7 @@ public class BatEeeeAbility implements Ability<Hit> {
}, rng.nextInt(10));
if (!player.getPhysics().isFlying()) {
player.setAnimation(Animation.SPREAD_WINGS);
player.setAnimation(Animation.SPREAD_WINGS, Animation.Recipient.ANYONE);
}
Vec3d origin = player.getOriginVector();

View file

@ -88,14 +88,14 @@ public class EarthPonyKickAbility implements Ability<Pos> {
entity.takeKnockback(calculatedStrength, origin.x - entity.getX(), origin.z - entity.getZ());
Living.updateVelocity(entity);
player.subtractEnergyCost(3);
player.setAnimation(Animation.KICK);
player.setAnimation(Animation.KICK, Animation.Recipient.ANYONE);
return;
}
}
BlockPos pos = kickLocation.pos();
EarthPonyStompAbility.stompBlock(w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos));
player.setAnimation(Animation.KICK);
player.setAnimation(Animation.KICK, Animation.Recipient.ANYONE);
});
}
@ -153,7 +153,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
BlockPos pos = data.pos();
TreeType tree = TreeType.at(pos, iplayer.asWorld());
iplayer.setAnimation(Animation.KICK);
iplayer.setAnimation(Animation.KICK, Animation.Recipient.ANYONE);
iplayer.subtractEnergyCost(tree == TreeType.NONE ? 1 : 3);
if (tree == TreeType.NONE) {

View file

@ -95,7 +95,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
public void apply(Pony iplayer, Hit data) {
PlayerEntity player = iplayer.asEntity();
iplayer.setAnimation(Animation.STOMP, 10);
iplayer.setAnimation(Animation.STOMP, Animation.Recipient.ANYONE, 10);
thrustDownwards(iplayer);

View file

@ -68,7 +68,7 @@ public class PegasusFlightToggleAbility implements Ability<Hit> {
player.getPhysics().cancelFlight(true);
}
player.setDirty();
player.setAnimation(Animation.SPREAD_WINGS);
player.setAnimation(Animation.SPREAD_WINGS, Animation.Recipient.ANYONE);
}
@Override

View file

@ -111,14 +111,14 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
player.spawnParticles(ParticleTypes.LARGE_SMOKE, 6);
player.playSound(USounds.SPELL_CAST_FAIL, 1, 0.5F);
} else {
player.setAnimation(Animation.ARMS_UP);
player.setAnimation(Animation.ARMS_UP, Animation.Recipient.HUMAN);
if (s instanceof HomingSpell homer) {
TraceHelper.findEntity(player.asEntity(), homer.getRange(player), 1, EntityPredicates.VALID_ENTITY).ifPresent(homer::setTarget);
}
player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F);
}
} else {
player.setAnimation(Animation.WOLOLO);
player.setAnimation(Animation.WOLOLO, Animation.Recipient.ANYONE);
}
}
}

View file

@ -58,7 +58,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
if (player.getSpecies() != Race.CHANGELING) {
if (type.getTapCount() > 1) {
player.setAnimation(Animation.WOLOLO, 10);
player.setAnimation(Animation.WOLOLO, Animation.Recipient.ANYONE, 10);
if (player.getSpellSlot().clear()) {
player.asEntity().sendMessage(Text.translatable("gui.unicopia.action.spells_cleared"), true);
} else {
@ -90,7 +90,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
@Override
public void apply(Pony player, Pos data) {
player.setAnimation(Animation.WOLOLO);
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();
});

View file

@ -43,7 +43,7 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
if (thrown.getResult() != ActionResult.FAIL) {
thrown.getValue().create().toThrowable().throwProjectile(player).ifPresent(projectile -> {
player.subtractEnergyCost(getCostEstimate(player));
player.setAnimation(Animation.ARMS_FORWARD, 2);
player.setAnimation(Animation.ARMS_FORWARD, Animation.Recipient.ANYONE, 2);
});
}
}
@ -62,7 +62,7 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
spell.toThrowable().throwProjectile(player).ifPresent(projectile -> {
player.subtractEnergyCost(getCostEstimate(player));
player.setAnimation(Animation.ARMS_FORWARD);
player.setAnimation(Animation.ARMS_FORWARD, Animation.Recipient.ANYONE);
projectile.setHydrophobic();
if (spell instanceof HomingSpell) {

View file

@ -6,6 +6,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.command.CommandArgumentEnum;
import net.minecraft.command.argument.EnumArgumentType;
import net.minecraft.item.Item;
@ -17,7 +18,7 @@ import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.StringIdentifiable;
public enum Trait implements StringIdentifiable {
public enum Trait implements CommandArgumentEnum<Trait> {
/**
* Imparts physical strength or enhances endurance.
* Spells with more of the strength trait hit harder and last longer.

View file

@ -51,7 +51,7 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
model.getAttributes().isGoingFast |= pony.getMotion().isRainbooming();
model.getAttributes().isGoingFast &= !pony.getEntityInArms().isPresent();
if (pony.getAnimation() == Animation.SPREAD_WINGS) {
if (pony.getAnimation().isOf(Animation.SPREAD_WINGS)) {
model.getAttributes().wingAngle = -AnimationUtil.seeSitSaw(pony.getAnimationProgress(1), 1.5F) * (float)Math.PI / 1.2F;
model.getAttributes().isFlying = true;
}

View file

@ -2,8 +2,10 @@ package com.minelittlepony.unicopia.client.render;
import java.util.Optional;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate;
import com.minelittlepony.unicopia.command.CommandArgumentEnum;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.GlassesItem;
import com.minelittlepony.unicopia.util.AnimationUtil;
@ -30,8 +32,12 @@ public class PlayerPoser {
public void applyPosing(MatrixStack matrices, PlayerEntity player, BipedEntityModel<?> model, Context context) {
Pony pony = Pony.of(player);
float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta());
Animation animation = pony.getAnimation();
boolean isPony = MineLPDelegate.getInstance().getPlayerPonyRace(player).isEquine();
AnimationInstance animation = pony.getAnimation();
Race ponyRace = MineLPDelegate.getInstance().getPlayerPonyRace(player);
Arm mainArm = player.getMainArm();
boolean liftLeftArm = mainArm == Arm.LEFT || !ponyRace.isEquine();
boolean liftRightArm = mainArm == Arm.RIGHT || !ponyRace.isEquine();
ItemStack glasses = GlassesItem.getForEntity(player);
@ -43,7 +49,7 @@ public class PlayerPoser {
float beat30 = bop / 30F;
if (isPony) {
if (ponyRace.isEquine()) {
float beat50 = bop / 50F;
float beat20 = bop / 20F;
@ -60,143 +66,160 @@ public class PlayerPoser {
}
}
switch (animation) {
case NECK_SNAP: {
head.yaw += 3F;
head.pitch *= -1;
break;
}
case WOLOLO: {
float roll = MathHelper.sin(player.age / 10F);
float yaw = MathHelper.cos(player.age / 10F);
model.leftArm.pitch += -1;
model.rightArm.pitch += -1;
model.leftArm.roll = -roll;
model.rightArm.roll = roll;
model.leftArm.yaw = yaw;
model.rightArm.yaw = yaw;
break;
}
case ARMS_FORWARD: {
float roll = (progress + 1) / 2F;
float pitch = 1.5F * roll;
float yaw = 0.5F * roll;
model.leftArm.pitch -= pitch;
model.rightArm.pitch -= pitch;
model.leftArm.roll = 0;
model.rightArm.roll = 0;
model.leftArm.yaw = yaw;
model.rightArm.yaw = -yaw;
break;
}
case ARMS_UP: {
float roll = (progress + 1) / 2F;
float pitch = 3F * roll;
float yaw = 0.5F * roll;
model.leftArm.pitch -= pitch;
model.rightArm.pitch -= pitch;
model.leftArm.roll = 0;
model.rightArm.roll = 0;
model.leftArm.yaw = yaw;
model.rightArm.yaw = -yaw;
break;
}
case WAVE_ONE:
case WAVE_TWO: {
progress = AnimationUtil.seesaw(progress);
if (animation == Animation.WAVE_TWO && isPony) {
rearUp(matrices, model, progress);
model.head.pitch += progress;
model.hat.pitch += progress;
}
float wave = 2.5F + progress * MathHelper.sin(player.age / 3F);
if (animation == Animation.WAVE_TWO || player.getMainArm() == Arm.LEFT) {
model.leftArm.roll = -wave;
}
if (animation == Animation.WAVE_TWO || player.getMainArm() == Arm.RIGHT) {
model.rightArm.roll = wave;
}
break;
}
case KICK: {
if (isPony) {
float roll = (progress + 1) / 2F;
model.rightLeg.pitch = roll * 1.5F;
model.rightLeg.yaw = -roll / 7F;
model.leftLeg.pitch = roll * 1.5F;
model.leftLeg.yaw = roll / 7F;
model.leftArm.pitch = 0;
model.leftArm.roll = -roll / 7F;
model.rightArm.pitch = 0;
model.rightArm.roll = roll / 7F;
if (animation.canPlay(ponyRace.isEquine())) {
switch (animation.animation()) {
case NECK_SNAP: {
head.yaw += 3F;
head.pitch *= -1;
break;
}
case WOLOLO: {
float roll = MathHelper.sin(player.age / 10F);
float yaw = MathHelper.cos(player.age / 10F);
float roll = (progress + 1) / 2F;
if (liftLeftArm) {
rotateArm(model.leftArm, 1, yaw, -roll);
}
model.rightArm.pitch += roll / 5F;
model.leftArm.roll -= roll / 5F;
model.rightArm.roll += roll / 5F;
if (liftRightArm) {
rotateArm(model.leftArm, 1, yaw, roll);
}
if (player.getMainArm() == Arm.LEFT) {
model.rightLeg.pitch = -roll * 1.5F;
model.rightLeg.roll = roll / 10F;
} else {
model.leftLeg.pitch = -roll * 1.5F;
model.leftLeg.roll = -roll / 10F;
break;
}
break;
}
case STOMP: {
progress = AnimationUtil.seesaw(progress);
case ARMS_FORWARD: {
float roll = (progress + 1) / 2F;
if (!isPony) {
if (player.getMainArm() == Arm.LEFT) {
model.rightLeg.roll = -progress / 9F;
model.rightLeg.pivotY -= progress * 5;
} else {
model.leftLeg.roll = -progress / 9F;
model.leftLeg.pivotY -= progress * 5;
float pitch = 1.5F * roll;
float yaw = -0.5F * roll;
if (liftLeftArm) {
rotateArm(model.leftArm, pitch, -yaw, 0);
}
if (liftRightArm) {
rotateArm(model.rightArm, pitch, yaw, 0);
}
break;
}
case ARMS_UP: {
float saw = AnimationUtil.seesaw(progress);
float pitch = 3F * saw;
float yaw = 0.5F * saw;
float roll = saw;
if (ponyRace.isEquine()) {
rearUp(matrices, model, saw);
pitch = roll * 2F;
model.head.pitch += saw * 0.5F;
}
if (liftLeftArm) {
rotateArm(model.leftArm, pitch, -yaw, yaw);
} else if (ponyRace.isEquine()) {
model.leftArm.pitch += saw / 4F;
model.leftArm.roll -= saw / 4F;
}
if (liftRightArm) {
rotateArm(model.rightArm, pitch, yaw, -yaw);
} else if (ponyRace.isEquine()) {
model.rightArm.pitch += saw / 4F;
model.rightArm.roll += saw / 4F;
}
break;
}
case WAVE_ONE:
case WAVE_TWO: {
progress = AnimationUtil.seesaw(progress);
if (animation.isOf(Animation.WAVE_TWO) && ponyRace.isEquine()) {
rearUp(matrices, model, progress);
model.head.pitch += progress * 0.5F;
}
float wave = 2.5F + progress * MathHelper.sin(player.age / 3F);
if (animation.isOf(Animation.WAVE_TWO) || mainArm == Arm.LEFT) {
model.leftArm.roll = -wave;
}
if (animation.isOf(Animation.WAVE_TWO) || mainArm == Arm.RIGHT) {
model.rightArm.roll = wave;
}
break;
}
case KICK: {
if (ponyRace.isEquine()) {
float roll = (progress + 1) / 2F;
rearUp(matrices, model, progress);
break;
}
case WIGGLE_NOSE: {
if (!isPony) {
model.rightLeg.pitch = roll * 1.5F;
model.rightLeg.yaw = -roll / 7F;
model.leftLeg.pitch = roll * 1.5F;
model.leftLeg.yaw = roll / 7F;
model.leftArm.pitch = 0;
model.leftArm.roll = MathHelper.lerp(progress, model.leftArm.roll, 0);
model.rightArm.pitch = 0;
model.rightArm.roll = MathHelper.lerp(progress, model.rightArm.roll, 0);
break;
}
float roll = (progress + 1) / 2F;
model.rightArm.pitch += roll / 5F;
model.leftArm.roll -= roll / 5F;
model.rightArm.roll += roll / 5F;
if (player.getMainArm() == Arm.LEFT) {
model.rightLeg.pitch = -roll * 1.5F;
model.rightLeg.roll = roll / 10F;
} else {
model.leftLeg.pitch = -roll * 1.5F;
model.leftLeg.roll = -roll / 10F;
}
break;
}
case STOMP: {
progress = AnimationUtil.seesaw(progress);
progress = AnimationUtil.seesaw(progress) * MathHelper.sin(player.age) / 7F;
if (!ponyRace.isEquine()) {
if (mainArm == Arm.LEFT) {
model.rightLeg.roll = -progress / 9F;
model.rightLeg.pivotY -= progress * 5;
} else {
model.leftLeg.roll = -progress / 9F;
model.leftLeg.pivotY -= progress * 5;
}
break;
}
model.getHead().getChild("mare").pivotY = progress;
model.getHead().getChild("stallion").pivotY = progress;
break;
rearUp(matrices, model, progress);
model.head.pitch += progress * 0.5F;
model.leftArm.pitch += progress / 2F;
model.rightArm.pitch += progress / 2F;
break;
}
case WIGGLE_NOSE: {
if (!ponyRace.isEquine()) {
break;
}
progress = AnimationUtil.seesaw(progress) * MathHelper.sin(player.age) / 7F;
model.getHead().getChild("mare").pivotY = progress;
model.getHead().getChild("stallion").pivotY = progress;
break;
}
default:
}
default:
}
if (pony.getEntityInArms().isPresent()) {
if (isPony && pony.getPhysics().isFlying()) {
if (ponyRace.isEquine() && pony.getPhysics().isFlying()) {
model.leftLeg.pitch = 1;
model.rightLeg.pitch = 1;
model.leftLeg.yaw = 0.3F;
@ -220,6 +243,12 @@ public class PlayerPoser {
model.hat.copyTransform(model.head);
}
private void rotateArm(ModelPart arm, float pitch, float yaw, float roll) {
arm.pitch -= pitch;
arm.roll = roll;
arm.yaw = yaw;
}
private void rearUp(MatrixStack matrices, BipedEntityModel<?> model, float progress) {
matrices.translate(0, 0, 0.5);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-45 * progress));
@ -234,7 +263,19 @@ public class PlayerPoser {
model.leftLeg.yaw = roll / 7F;
}
public enum Animation implements StringIdentifiable {
public record AnimationInstance(Animation animation, Animation.Recipient recipient) {
public static final AnimationInstance NONE = new AnimationInstance(Animation.NONE, Animation.Recipient.ANYONE);
public boolean isOf(Animation animation) {
return animation() == animation;
}
public boolean canPlay(boolean isPony) {
return !isOf(Animation.NONE) && (recipient == Animation.Recipient.ANYONE || isPony == (recipient == Animation.Recipient.PONY));
}
}
public enum Animation implements CommandArgumentEnum<Animation> {
NONE(0),
WOLOLO(USounds.ENTITY_PLAYER_WOLOLO, 40),
ARMS_FORWARD(5),
@ -268,11 +309,6 @@ public class PlayerPoser {
return sound;
}
@Override
public String asString() {
return name();
}
public static EnumArgumentType<Animation> argument() {
return new ArgumentType();
}
@ -286,6 +322,24 @@ public class PlayerPoser {
}
}
public enum Recipient implements CommandArgumentEnum<Recipient> {
HUMAN,
PONY,
ANYONE;
public static EnumArgumentType<Recipient> argument() {
return new ArgumentType();
}
public static final class ArgumentType extends EnumArgumentType<Recipient> {
@SuppressWarnings("deprecation")
static final Codec<Recipient> CODEC = StringIdentifiable.createCodec(Recipient::values);
protected ArgumentType() {
super(CODEC, Recipient::values);
}
}
}
}
public enum Context {

View file

@ -0,0 +1,16 @@
package com.minelittlepony.unicopia.command;
import net.minecraft.util.StringIdentifiable;
public interface CommandArgumentEnum<T extends Enum<T> & CommandArgumentEnum<T>> extends StringIdentifiable {
@SuppressWarnings("unchecked")
default T asSelf() {
return (T)this;
}
@Override
default String asString() {
return asSelf().name();
}
}

View file

@ -16,6 +16,7 @@ public class Commands {
@SuppressWarnings("deprecation")
public static void bootstrap() {
ArgumentTypeRegistry.registerArgumentType(Unicopia.id("animation"), Animation.ArgumentType.class, ConstantArgumentSerializer.of(Animation::argument));
ArgumentTypeRegistry.registerArgumentType(Unicopia.id("animation_recipient"), Animation.Recipient.ArgumentType.class, ConstantArgumentSerializer.of(Animation.Recipient::argument));
ArgumentTypeRegistry.registerArgumentType(Unicopia.id("mana_type"), ManaType.ArgumentType.class, ConstantArgumentSerializer.of(ManaType::argument));
ArgumentTypeRegistry.registerArgumentType(Unicopia.id("trait_type"), Trait.ArgumentType.class, ConstantArgumentSerializer.of(Trait::argument));
ArgumentTypeRegistry.registerArgumentType(Unicopia.id("spell_traits"), TraitsArgumentType.class, ConstantArgumentSerializer.of(TraitsArgumentType::traits));

View file

@ -15,23 +15,31 @@ public class EmoteCommand {
.literal("emote")
.then(CommandManager.argument("animation", Animation.argument()).executes(source -> apply(
source.getSource(),
source.getArgument("animation", Animation.class)
source.getArgument("animation", Animation.class),
Animation.Recipient.ANYONE
)
).then(CommandManager.argument("duration", IntegerArgumentType.integer(1, 99)).executes(source -> apply(
source.getSource(),
source.getArgument("animation", Animation.class),
source.getArgument("duration", Integer.class)
Animation.Recipient.ANYONE,
IntegerArgumentType.getInteger(source, "duration")
)
)
).then(CommandManager.argument("recipient_type", Animation.Recipient.argument()).executes(source -> apply(
source.getSource(),
source.getArgument("animation", Animation.class),
source.getArgument("recipient_type", Animation.Recipient.class),
IntegerArgumentType.getInteger(source, "duration")
)
))
)));
}
static int apply(ServerCommandSource source, Animation animation) throws CommandSyntaxException {
return apply(source, animation, animation.getDuration());
static int apply(ServerCommandSource source, Animation animation, Animation.Recipient recipient) throws CommandSyntaxException {
return apply(source, animation, recipient, animation.getDuration());
}
static int apply(ServerCommandSource source, Animation animation, int duration) throws CommandSyntaxException {
Pony.of(source.getPlayer()).setAnimation(animation, duration);
static int apply(ServerCommandSource source, Animation animation, Animation.Recipient recipient, int duration) throws CommandSyntaxException {
Pony.of(source.getPlayer()).setAnimation(animation, recipient, duration);
return 0;
}
}

View file

@ -44,7 +44,7 @@ public class ManaCommand {
);
}
enum ManaType implements StringIdentifiable {
enum ManaType implements CommandArgumentEnum<ManaType> {
EXERTION(MagicReserves::getExertion),
EXHAUSTION(MagicReserves::getExhaustion),
ENERGY(MagicReserves::getEnergy),
@ -61,11 +61,6 @@ public class ManaCommand {
return getter.apply(reserves);
}
@Override
public String asString() {
return name();
}
public static EnumArgumentType<ManaType> argument() {
return new ArgumentType();
}

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.entity.player;
import java.util.function.Supplier;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
@ -120,7 +122,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
@Override
public float getWingAngle() {
if (pony.getAnimation() == Animation.SPREAD_WINGS) {
if (pony.getAnimation().isOf(Animation.SPREAD_WINGS)) {
return AnimationUtil.seeSitSaw(pony.getAnimationProgress(1), 1.5F);
}
@ -485,6 +487,14 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
isFlyingSurvival = true;
thrustScale = 0;
entity.calculateDimensions();
if (entity.isOnGround() || !force) {
Supplier<Vec3d> vec = VecHelper.sphere(pony.asWorld().getRandom(), 0.5D);
pony.spawnParticles(ParticleTypes.CAMPFIRE_COSY_SMOKE, vec, vec, 5);
pony.spawnParticles(ParticleTypes.CLOUD, vec, vec, 5);
}
}
private void handleWallCollission(MutableVector velocity) {

View file

@ -6,6 +6,7 @@ import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.client.render.PlayerPoser.AnimationInstance;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.ability.*;
import com.minelittlepony.unicopia.ability.magic.*;
@ -100,7 +101,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
private boolean hasShades;
private int ticksSunImmunity = INITIAL_SUN_IMMUNITY;
private Animation animation = Animation.NONE;
private AnimationInstance animation = new AnimationInstance(Animation.NONE, Animation.Recipient.ANYONE);
private int animationMaxDuration;
private int animationDuration;
@ -124,34 +125,53 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
builder.add(UEntityAttributes.ENTITY_GRAVTY_MODIFIER);
}
@Deprecated
public void setAnimation(Animation animation) {
setAnimation(animation, animation.getDuration());
setAnimation(new AnimationInstance(animation, Animation.Recipient.ANYONE));
}
@Deprecated
public void setAnimation(Animation animation, int duration) {
if (animation != this.animation && duration != animationDuration) {
setAnimation(new AnimationInstance(animation, Animation.Recipient.ANYONE));
}
public void setAnimation(Animation animation, Animation.Recipient recipient) {
setAnimation(new AnimationInstance(animation, recipient), animation.getDuration());
}
public void setAnimation(Animation animation, Animation.Recipient recipient, int duration) {
setAnimation(new AnimationInstance(animation, recipient), duration);
}
public void setAnimation(AnimationInstance animation) {
setAnimation(animation, animation.animation().getDuration());
}
public void setAnimation(AnimationInstance animation, int duration) {
if (!animation.equals(this.animation) || duration != animationDuration) {
this.animation = animation;
this.animationDuration = animation == Animation.NONE ? 0 : Math.max(0, duration);
this.animationDuration = animation.isOf(Animation.NONE) ? 0 : Math.max(0, duration);
this.animationMaxDuration = animationDuration;
if (!isClient()) {
Channel.SERVER_PLAYER_ANIMATION_CHANGE.sendToAllPlayers(new MsgPlayerAnimationChange(this, animation, animationDuration), asWorld());
}
animation.getSound().ifPresent(sound -> {
animation.animation().getSound().ifPresent(sound -> {
playSound(sound, sound == USounds.ENTITY_PLAYER_WOLOLO ? 0.1F : 0.9F, 1);
});
}
}
public Animation getAnimation() {
public AnimationInstance getAnimation() {
return animation;
}
public float getAnimationProgress(float delta) {
if (animation == Animation.NONE) {
if (animation.isOf(Animation.NONE)) {
return 0;
}
System.out.println(animationMaxDuration);
return 1 - (((float)animationDuration) / animationMaxDuration);
}
@ -378,8 +398,8 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
private void updateAnimations() {
if (animationDuration >= 0 && --animationDuration <= 0) {
setAnimation(Animation.NONE);
if (animationDuration > 0 && --animationDuration <= 0) {
setAnimation(AnimationInstance.NONE);
}
}

View file

@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.entity.CastSpellEntity;
import com.minelittlepony.unicopia.entity.UEntities;
import com.minelittlepony.unicopia.entity.player.Pony;
@ -131,6 +132,7 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
pony.subtractEnergyCost(4);
stack.damage(1, pony.asEntity(), p -> p.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND));
getSpellEffect(stack).create().toThrowable().throwProjectile(pony);
pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10);
});
ChargeableItem.consumeEnergy(stack, 1);
} else if (i > 5) {
@ -138,6 +140,7 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
pony.subtractEnergyCost(4);
stack.damage(1, pony.asEntity(), p -> p.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND));
getSpellEffect(stack).create().toThrowable().throwProjectile(pony);
pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10);
});
ChargeableItem.consumeEnergy(stack, 1);
}

View file

@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.network;
import java.util.UUID;
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
import com.minelittlepony.unicopia.client.render.PlayerPoser.AnimationInstance;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.sollace.fabwork.api.packets.HandledPacket;
@ -15,22 +16,23 @@ import net.minecraft.network.PacketByteBuf;
*/
public record MsgPlayerAnimationChange (
UUID playerId,
Animation animation,
AnimationInstance animation,
int duration
) implements HandledPacket<PlayerEntity> {
MsgPlayerAnimationChange(PacketByteBuf buffer) {
this(buffer.readUuid(), buffer.readEnumConstant(Animation.class), buffer.readInt());
this(buffer.readUuid(), new AnimationInstance(buffer.readEnumConstant(Animation.class), buffer.readEnumConstant(Animation.Recipient.class)), buffer.readInt());
}
public MsgPlayerAnimationChange(Pony player, Animation animation, int duration) {
public MsgPlayerAnimationChange(Pony player, AnimationInstance animation, int duration) {
this(player.asEntity().getUuid(), animation, duration);
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeUuid(playerId);
buffer.writeEnumConstant(animation);
buffer.writeEnumConstant(animation.animation());
buffer.writeEnumConstant(animation.recipient());
buffer.writeInt(duration);
}

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.particle;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.minelittlepony.unicopia.EntityConvertable;
import com.minelittlepony.unicopia.util.shape.PointGenerator;
@ -11,6 +12,16 @@ import net.minecraft.util.math.Vec3d;
public interface ParticleSource<E extends Entity> extends ParticleSpawner, EntityConvertable<E> {
default void spawnParticles(ParticleEffect particleId, Supplier<Vec3d> posSupplier, Supplier<Vec3d> velSupplier, int count) {
for (int i = 0; i < count; i++) {
spawnParticle(particleId, posSupplier, velSupplier);
}
}
default void spawnParticle(ParticleEffect particleId, Supplier<Vec3d> posSupplier, Supplier<Vec3d> velSupplier) {
addParticle(particleId, getOriginVector().add(posSupplier.get()), velSupplier.get());
}
default void spawnParticles(ParticleEffect particleId, int count) {
ParticleUtils.spawnParticles(particleId, asEntity(), count);
}

View file

@ -3,11 +3,14 @@ package com.minelittlepony.unicopia.util;
import java.util.List;
import java.util.function.DoubleSupplier;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.EntityView;
public interface VecHelper {
@ -20,6 +23,18 @@ public interface VecHelper {
return new Vec3d(rng.getAsDouble(), rng.getAsDouble(), rng.getAsDouble());
}
static Supplier<Vec3d> supplier(DoubleSupplier rng) {
return () -> supply(rng);
}
static Supplier<Vec3d> sphere(Random rng) {
return sphere(rng, 1);
}
static Supplier<Vec3d> sphere(Random rng, double radius) {
return supplier(() -> (rng.nextGaussian() - 0.5) * radius);
}
static Predicate<Entity> inRange(Vec3d center, double range) {
double rad = Math.pow(range, 2);
return e -> {