mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-03-03 16:51:28 +01:00
Added player animations for doing things like casting spells and kicking
This commit is contained in:
parent
4e621434af
commit
bce1e5c8c1
10 changed files with 242 additions and 0 deletions
|
@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.Race;
|
|||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.ability.data.tree.TreeType;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.PosHelper;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
|
@ -89,6 +90,8 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
return;
|
||||
}
|
||||
|
||||
iplayer.setAnimation(Animation.KICK, 30);
|
||||
|
||||
BlockPos pos = data.pos();
|
||||
|
||||
BlockDestructionManager destr = ((BlockDestructionManager.Source)player.world).getDestructionManager();
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.minelittlepony.unicopia.ability.data.Hit;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.AmuletItem;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
|
@ -106,11 +107,14 @@ public class UnicornCastingAbility implements Ability<Hit> {
|
|||
player.spawnParticles(ParticleTypes.LARGE_SMOKE, 6);
|
||||
player.playSound(SoundEvents.ENTITY_ITEM_BREAK, 1, 0.5F);
|
||||
} else {
|
||||
player.setAnimation(Animation.ARMS_UP, 5);
|
||||
if (s instanceof HomingSpell) {
|
||||
RayTraceHelper.doTrace(player.getMaster(), 600, 1, EntityPredicates.CAN_COLLIDE).getEntity().ifPresent(((HomingSpell)s)::setTarget);
|
||||
}
|
||||
player.playSound(SoundEvents.BLOCK_BEACON_POWER_SELECT, 0.05F, 2.2F);
|
||||
}
|
||||
} else {
|
||||
player.setAnimation(Animation.WOLOLO, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
|
@ -43,6 +44,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
public boolean onQuickAction(Pony player, ActivationType type) {
|
||||
|
||||
if (type.getTapCount() > 1) {
|
||||
player.setAnimation(Animation.WOLOLO, 10);
|
||||
if (player.getSpellSlot().clear()) {
|
||||
player.getMaster().sendMessage(new TranslatableText("gui.unicopia.action.spells_cleared"), true);
|
||||
} else {
|
||||
|
@ -73,6 +75,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
|
||||
@Override
|
||||
public void apply(Pony player, Pos data) {
|
||||
player.setAnimation(Animation.WOLOLO, 30);
|
||||
Caster.stream(VecHelper.findInRange(player.getEntity(), player.getWorld(), data.vec(), 2, EquinePredicates.IS_PLACED_SPELL).stream()).forEach(target -> {
|
||||
target.getSpellSlot().clear();
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.minelittlepony.unicopia.ability.data.Hit;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
|
@ -69,6 +70,7 @@ public class UnicornProjectileAbility implements Ability<Hit> {
|
|||
Spell spell = thrown.getValue().create();
|
||||
|
||||
spell.toThrowable().throwProjectile(player).ifPresent(projectile -> {
|
||||
player.setAnimation(Animation.ARMS_FORWARD, 5);
|
||||
if (spell instanceof HomingSpell) {
|
||||
RayTraceHelper.doTrace(player.getMaster(), 600, 1, EntityPredicates.CAN_COLLIDE).getEntity().filter(((HomingSpell)spell)::setTarget).ifPresent(target -> {
|
||||
projectile.setHomingTarget(target);
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package com.minelittlepony.unicopia.client.render;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Arm;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public class PlayerPoser {
|
||||
public static final PlayerPoser INSTANCE = new PlayerPoser();
|
||||
|
||||
public void applyPosing(PlayerEntity entity, BipedEntityModel<?> model) {
|
||||
Pony pony = Pony.of(entity);
|
||||
float progress = pony.getAnimationProgress(MinecraftClient.getInstance().getTickDelta());
|
||||
|
||||
switch (pony.getAnimation()) {
|
||||
case WOLOLO: {
|
||||
float roll = MathHelper.sin(entity.age / 10F);
|
||||
float yaw = MathHelper.cos(entity.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 KICK: {
|
||||
float roll = (progress + 1) / 2F;
|
||||
|
||||
model.rightArm.pitch += roll / 5F;
|
||||
model.leftArm.roll -= roll / 5F;
|
||||
model.rightArm.roll += roll / 5F;
|
||||
|
||||
if (entity.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;
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
public enum Animation {
|
||||
NONE,
|
||||
WOLOLO,
|
||||
ARMS_FORWARD,
|
||||
ARMS_UP,
|
||||
KICK
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.client.UnicopiaClient;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.InteractionManager;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
|
@ -30,6 +31,7 @@ import com.minelittlepony.unicopia.item.UItems;
|
|||
import com.minelittlepony.unicopia.item.toxin.Toxin;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgOtherPlayerCapabilities;
|
||||
import com.minelittlepony.unicopia.network.MsgPlayerAnimationChange;
|
||||
import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange;
|
||||
import com.minelittlepony.unicopia.network.datasync.Transmittable;
|
||||
import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback;
|
||||
|
@ -58,6 +60,7 @@ import net.minecraft.nbt.NbtCompound;
|
|||
import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Hand;
|
||||
|
@ -106,6 +109,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
private int ticksInSun;
|
||||
private boolean hasShades;
|
||||
|
||||
private Animation animation = Animation.NONE;
|
||||
private int animationMaxDuration;
|
||||
private int animationDuration;
|
||||
|
||||
public Pony(PlayerEntity player) {
|
||||
super(player, EFFECT);
|
||||
this.mana = new ManaContainer(this);
|
||||
|
@ -121,6 +128,33 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
builder.add(PlayerAttributes.ENTITY_GRAVTY_MODIFIER);
|
||||
}
|
||||
|
||||
public void setAnimation(Animation animation, int duration) {
|
||||
if (animation != this.animation && duration != animationDuration) {
|
||||
this.animation = animation;
|
||||
this.animationDuration = animation == Animation.NONE ? 0 : Math.max(0, duration);
|
||||
this.animationMaxDuration = animationDuration;
|
||||
|
||||
if (!isClient()) {
|
||||
Channel.SERVER_PLAYER_ANIMATION_CHANGE.send(getWorld(), new MsgPlayerAnimationChange(this, animation, animationDuration));
|
||||
}
|
||||
|
||||
if (animation == Animation.WOLOLO) {
|
||||
playSound(SoundEvents.ENTITY_EVOKER_PREPARE_WOLOLO, 0.9F, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Animation getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
public float getAnimationProgress(float delta) {
|
||||
if (animation == Animation.NONE) {
|
||||
return 0;
|
||||
}
|
||||
return 1 - ((animationDuration + delta) / animationMaxDuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Race getSpecies() {
|
||||
if (getMaster() == null) {
|
||||
|
@ -288,6 +322,11 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (animationDuration >= 0) {
|
||||
if (--animationDuration <= 0) {
|
||||
setAnimation(Animation.NONE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHanging()) {
|
||||
if (ticksHanging++ > 40) {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package com.minelittlepony.unicopia.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.Desc;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.EntityRenderer;
|
||||
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
||||
@Mixin(LivingEntityRenderer.class)
|
||||
abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends EntityModel<T>> extends EntityRenderer<T> implements FeatureRendererContext<T, M> {
|
||||
MixinLivingEntityRenderer() { super(null); }
|
||||
|
||||
@Inject(method = "render",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
desc = @Desc(
|
||||
value = "setAngles",
|
||||
owner = EntityModel.class,
|
||||
args = { Entity.class, float.class, float.class, float.class, float.class, float.class }
|
||||
),
|
||||
shift = Shift.AFTER
|
||||
)
|
||||
)
|
||||
private void onRender(
|
||||
T entity,
|
||||
float f, float g,
|
||||
MatrixStack matrixStack,
|
||||
VertexConsumerProvider vertexConsumerProvider,
|
||||
int i,
|
||||
CallbackInfo into) {
|
||||
if (entity instanceof PlayerEntity player) {
|
||||
PlayerPoser.INSTANCE.applyPosing(player, (BipedEntityModel<?>)getModel());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ public interface Channel {
|
|||
S2CPacketType<MsgTribeSelect> SERVER_SELECT_TRIBE = SimpleNetworking.serverToClient(SERVER_SELECT_TRIBE_ID, MsgTribeSelect::new);
|
||||
|
||||
S2CBroadcastPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new);
|
||||
S2CBroadcastPacketType<MsgPlayerAnimationChange> SERVER_PLAYER_ANIMATION_CHANGE = SimpleNetworking.serverToClients(new Identifier("unicopia", "other_player_animation_change"), MsgPlayerAnimationChange::new);
|
||||
|
||||
static void bootstrap() {
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package com.minelittlepony.unicopia.network;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.network.Packet;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* Sent to the client when a player's animation changes.
|
||||
*/
|
||||
public class MsgPlayerAnimationChange implements Packet<PlayerEntity> {
|
||||
private final UUID playerId;
|
||||
private final Animation animation;
|
||||
private final int duration;
|
||||
|
||||
MsgPlayerAnimationChange(PacketByteBuf buffer) {
|
||||
playerId = buffer.readUuid();
|
||||
animation = Animation.values()[buffer.readInt()];
|
||||
duration = buffer.readInt();
|
||||
}
|
||||
|
||||
public MsgPlayerAnimationChange(Pony player, Animation animation, int duration) {
|
||||
this.playerId = player.getEntity().getUuid();
|
||||
this.animation = animation;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeUuid(playerId);
|
||||
buffer.writeInt(animation.ordinal());
|
||||
buffer.writeInt(duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(PlayerEntity sender) {
|
||||
Pony player = Pony.of(MinecraftClient.getInstance().world.getPlayerByUuid(playerId));
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.setAnimation(animation, duration);
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@
|
|||
"client.MixinItemModels",
|
||||
"client.MixinKeyboardInput",
|
||||
"client.MixinLightmapTextureManager",
|
||||
"client.MixinLivingEntityRenderer",
|
||||
"client.MixinMouse",
|
||||
"client.MixinPlayerEntityRenderer",
|
||||
"client.MixinTooltipComponent",
|
||||
|
|
Loading…
Add table
Reference in a new issue