forked from mirrors/cobblemon
More cleanup
This commit is contained in:
@@ -99,9 +99,7 @@ public class HumanoidModelMixin {
|
||||
}
|
||||
}
|
||||
|
||||
// Raise the right arm forward while the player is recalling a Pokémon, so the held Poké Ball
|
||||
// (rendered by PlayerRecallBallRenderer) is held out in front of them. Eases in/out via the
|
||||
// tracker's raise factor and holds until the recall beam is finished.
|
||||
// Pose the right arm forward while recalling so the held Poké Ball sits out in front.
|
||||
@Inject(method = "setupAnim*", at = @At("TAIL"))
|
||||
public void cobblemon$poseRecallArm(
|
||||
LivingEntity entity,
|
||||
@@ -113,12 +111,12 @@ public class HumanoidModelMixin {
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (!(entity instanceof AbstractClientPlayer player)) return;
|
||||
// Don't fight the mounted-riding arm animation.... this could look weird lol
|
||||
// Skip while riding so we don't override the mounted-riding arm animation.
|
||||
if (entity.getVehicle() instanceof PokemonEntity) return;
|
||||
float raise = RecallArmAnimationTracker.INSTANCE.raiseFactor(player.getUUID());
|
||||
if (raise <= 0f) return;
|
||||
// -90° about X points the arm straight forward.
|
||||
this.rightArm.xRot = Mth.lerp(raise, this.rightArm.xRot, -1.5708f);
|
||||
float armForwardXRot = (float) (-Math.PI / 2.0);
|
||||
this.rightArm.xRot = Mth.lerp(raise, this.rightArm.xRot, armForwardXRot);
|
||||
this.rightArm.yRot = Mth.lerp(raise, this.rightArm.yRot, 0f);
|
||||
this.rightArm.zRot = Mth.lerp(raise, this.rightArm.zRot, 0f);
|
||||
}
|
||||
|
||||
+2
-3
@@ -22,9 +22,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Hides the item normally held in a player's right hand (third person, for everyone) while they are
|
||||
* recalling a Pokémon, so the recall Poké Ball rendered by PlayerRecallBallRenderer takes its place
|
||||
* cleanly instead of clipping through the held item.
|
||||
* Hides the player's right-hand item while recalling so it doesn't overlap the recall Poké Ball
|
||||
* drawn by PlayerRecallBallRenderer.
|
||||
*/
|
||||
@Mixin(ItemInHandLayer.class)
|
||||
public class ItemInHandLayerMixin {
|
||||
|
||||
+5
-6
@@ -27,13 +27,12 @@ import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
* Renders the matching Poké Ball in a recalling player's right hand and reports the world-space point
|
||||
* the recall beam should emit from. Driven entirely by [RecallArmAnimationTracker]; the right arm is
|
||||
* posed forward separately in HumanoidModelMixin so [PlayerModel.translateToHand] lands at the
|
||||
* extended hand.
|
||||
* Draws the matching Poké Ball in a recalling player's right hand and records where the recall beam
|
||||
* should start. Driven by [RecallArmAnimationTracker]; the right arm is posed forward in
|
||||
* HumanoidModelMixin so [PlayerModel.translateToHand] lands on the extended hand.
|
||||
*
|
||||
* The local player in first person is skipped here and handled by the first-person ball renderer
|
||||
* (see ItemInHandRendererMixin) instead.
|
||||
* The local player in first person is handled by FirstPersonRecallBallRenderer instead, so it's
|
||||
* skipped here.
|
||||
*/
|
||||
class PlayerRecallBallRenderer<T : Player>(
|
||||
renderLayerParent: RenderLayerParent<T, PlayerModel<T>>
|
||||
|
||||
+4
-5
@@ -19,12 +19,11 @@ import net.minecraft.client.renderer.entity.ItemRenderer
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
|
||||
/**
|
||||
* Renders the recalling player's Poké Ball in first person, rising up from the bottom of the screen
|
||||
* in place of whatever they were holding. The world-space recall beam still originates near the
|
||||
* player's hand (handled by the eye/look fallback in PokemonRenderer) — this is purely cosmetic.
|
||||
* Draws the recalling player's Poké Ball in first person, rising into view from the bottom of the
|
||||
* screen in place of their held item. The world-space beam still starts near the hand (the eye/look
|
||||
* fallback in PokemonRenderer), so this is cosmetic only.
|
||||
*
|
||||
* Invoked from ItemInHandRendererMixin, which cancels the vanilla main-hand item render while a
|
||||
* recall is active.
|
||||
* Called from ItemInHandRendererMixin, which cancels the vanilla main-hand item while recalling.
|
||||
*/
|
||||
object FirstPersonRecallBallRenderer {
|
||||
|
||||
|
||||
+16
-23
@@ -11,28 +11,26 @@ package com.cobblemon.mod.common.client.render.player
|
||||
import com.cobblemon.mod.common.client.battle.ClientBallDisplay
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Client-side bookkeeping for the "recall pose": when a player recalls a Pokémon we want them to
|
||||
* hold the matching Poké Ball out in their right hand and have the recall beam originate from it.
|
||||
* Tracks which players are recalling a Pokémon so we can pose their arm, draw the Poké Ball in their
|
||||
* hand, and start the recall beam from it.
|
||||
*
|
||||
* Entries are keyed by the recalling player's UUID and self-expire once the beam effect is over, so
|
||||
* the arm automatically lowers without anything having to explicitly clear it (and a re-recall just
|
||||
* resets the timer).
|
||||
* Keyed by player UUID. Entries time out on their own once the beam is done, and a new recall resets
|
||||
* the timer, so nothing has to clear them.
|
||||
*
|
||||
* Populated from [com.cobblemon.mod.common.client.entity.PokemonClientDelegate] when a Pokémon
|
||||
* enters recall (beamMode 3). Read by the player arm pose (HumanoidModelMixin), the held-ball render
|
||||
* layer, the first-person ball renderer, and the beam origin in PokemonRenderer.
|
||||
* Written by PokemonClientDelegate on recall (beamMode 3); read by HumanoidModelMixin, the ball
|
||||
* renderers, and PokemonRenderer.
|
||||
*/
|
||||
object RecallArmAnimationTracker {
|
||||
|
||||
// How long the arm stays raised in seconds
|
||||
|
||||
// How long the arm stays raised, in seconds.
|
||||
const val ARM_HOLD_SECONDS = 0.8
|
||||
|
||||
// Portion of time spent easing the arm up / ball in at the start and down at the end
|
||||
// Fraction of the hold spent easing the arm up at the start and down at the end.
|
||||
private const val EASE_SECONDS = 0.15
|
||||
|
||||
class RecallAnim(
|
||||
@@ -44,17 +42,17 @@ object RecallArmAnimationTracker {
|
||||
var beamOrigin: Vec3? = null
|
||||
}
|
||||
|
||||
private val active = mutableMapOf<UUID, RecallAnim>()
|
||||
private val activeRecalls = ConcurrentHashMap<UUID, RecallAnim>()
|
||||
|
||||
fun start(playerUuid: UUID, ball: PokeBall, aspects: Set<String>) {
|
||||
active[playerUuid] = RecallAnim(ball, aspects, System.currentTimeMillis())
|
||||
activeRecalls[playerUuid] = RecallAnim(ball, aspects, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
/** Returns the active recall for the player, or null if there is none or if it has expired */
|
||||
/** Returns the active recall for the player, or null if there is none or if it has expired. */
|
||||
fun get(playerUuid: UUID): RecallAnim? {
|
||||
val anim = active[playerUuid] ?: return null
|
||||
val anim = activeRecalls[playerUuid] ?: return null
|
||||
if (secondsSince(anim) > ARM_HOLD_SECONDS) {
|
||||
active.remove(playerUuid)
|
||||
activeRecalls.remove(playerUuid)
|
||||
return null
|
||||
}
|
||||
return anim
|
||||
@@ -64,17 +62,12 @@ object RecallArmAnimationTracker {
|
||||
|
||||
private fun secondsSince(anim: RecallAnim) = (System.currentTimeMillis() - anim.startTimeMs) / 1000.0
|
||||
|
||||
/**
|
||||
* 0..1 ramp for how raised the arm and how risen the ball should be. eases up at the start, holds
|
||||
* at 1, then eases back down at the very end. Returns 0 when the player is not recalling.
|
||||
*/
|
||||
/** 0..1 ramp: eases in at the start, holds at 1, eases out at the end. 0 when not recalling. */
|
||||
fun raiseFactor(playerUuid: UUID): Float {
|
||||
val anim = get(playerUuid) ?: return 0F
|
||||
val elapsed = secondsSince(anim)
|
||||
val riseIn = Mth.clamp((elapsed / EASE_SECONDS).toFloat(), 0F, 1F)
|
||||
val fallOut = Mth.clamp(((ARM_HOLD_SECONDS - elapsed) / EASE_SECONDS).toFloat(), 0F, 1F)
|
||||
return min(riseIn, fallOut)
|
||||
return minOf(riseIn, fallOut)
|
||||
}
|
||||
|
||||
private fun min(a: Float, b: Float) = if (a < b) a else b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user