Release Healer Man 0.1.9

This commit is contained in:
phenom committed 2026-08-30 14:16:56 -04:00
1 parent c245a199b6
commit d060296ade
74 files changed
+5901 -334

No files matched your search

+25 -11
View File
@@ -61,10 +61,13 @@ import {
import {
EquipmentAttachments,
equipmentAttachmentHand,
resolveEquipmentAttachmentTransforms,
} from "./equipmentAttachments";
import {
ApproximateStarterEquipment,
StarterWeaponAttachments,
characterWeaponStance,
estimateAvatarWeaponScale,
type AvatarHand,
} from "./starterWeapons";
@@ -192,6 +195,14 @@ function LoadedCharacterModel({
}) {
const gltf = useGLTF(resolveContentUrl(entry.model));
const scene = useMemo(() => cloneAvatarScene(gltf.scene), [gltf.scene]);
const equipmentAttachmentTransforms = useMemo(
() => resolveEquipmentAttachmentTransforms(scene, entry),
[entry, scene],
);
const fallbackEquipmentScale = useMemo(
() => estimateAvatarWeaponScale(scene),
[scene],
);
const mixer = useMemo(() => new AnimationMixer(scene), [scene]);
const currentAction = useRef<AnimationAction | null>(null);
const overrideAction = useRef<AnimationAction | null>(null);
@@ -199,7 +210,6 @@ function LoadedCharacterModel({
const overrideLooping = useRef(false);
const currentMotion = useRef<CharacterLocomotionMotion | null>(null);
const observedAttackPulse = useRef(attackPulseRef?.current ?? 0);
const equipmentAttackPulseRef = useRef(attackPulseRef?.current ?? 0);
const observedAnimationRevision = useRef(animationEventRef?.current?.revision ?? 0);
const attackElapsed = useRef(ATTACK_PRESENTATION_DURATION_SECONDS);
const attackJoint = useMemo(
@@ -233,6 +243,15 @@ function LoadedCharacterModel({
}))] as AvatarHand[],
[resolved.equipmentModels],
);
const weaponStance = useMemo(() => characterWeaponStance(
identity.classId,
equipment,
resolved.equipmentModels.flatMap((itemModel) => (
itemModel.attachment === "handLeft" || itemModel.attachment === "handRight"
? [itemModel.itemId]
: []
)),
), [equipment, identity.classId, resolved.equipmentModels]);
useEffect(() => {
let cancelled = false;
@@ -339,7 +358,7 @@ function LoadedCharacterModel({
};
const selectClip = (motion: CharacterBaseMotion): AnimationClip | undefined => (
selectCharacterBaseClip(gltf.animations, motion)
selectCharacterBaseClip(gltf.animations, motion, weaponStance)
?? namedClip(entry.animations[motion])
?? namedClip(entry.animations.idle)
?? gltf.animations[0]
@@ -347,7 +366,6 @@ function LoadedCharacterModel({
const switchMotion = (motion: CharacterLocomotionMotion, moving: boolean) => {
if (overrideAction.current) return;
if (currentMotion.current === motion) return;
const verticalSelection = motion === "rising" || motion === "falling" || motion === "landing"
? selectCharacterVerticalClip(gltf.animations, motion, moving)
: null;
@@ -356,6 +374,7 @@ function LoadedCharacterModel({
motion === "idle" || motion === "walk" || motion === "run" ? motion : fallbackMotion,
);
if (!clip) return;
if (currentMotion.current === motion && currentAction.current?.getClip() === clip) return;
const loop = verticalSelection?.loop ?? true;
const next = mixer.clipAction(clip, scene);
next.enabled = true;
@@ -462,15 +481,11 @@ function LoadedCharacterModel({
if (nextAnimationEvent && nextAnimationEvent.revision !== observedAnimationRevision.current) {
observedAnimationRevision.current = nextAnimationEvent.revision;
playAnimationEvent(nextAnimationEvent);
if (nextAnimationEvent.kind === "attack" || nextAnimationEvent.kind === "ability-release") {
equipmentAttackPulseRef.current = nextAnimationEvent.revision;
}
}
const nextAttackPulse = attackPulseRef?.current ?? 0;
if (nextAttackPulse !== observedAttackPulse.current) {
observedAttackPulse.current = nextAttackPulse;
if (nextAttackPulse > 0) {
equipmentAttackPulseRef.current = nextAttackPulse;
playAnimationEvent({ revision: nextAttackPulse, kind: "attack" });
}
}
@@ -513,17 +528,16 @@ function LoadedCharacterModel({
/>
</group>
<StarterWeaponAttachments
attackPulseRef={equipmentAttackPulseRef}
classId={identity.classId}
entry={entry}
occupiedHands={occupiedEquipmentHands}
root={scene}
/>
<EquipmentAttachments
attackPulseRef={equipmentAttackPulseRef}
classId={identity.classId}
entry={entry}
fallbackScale={fallbackEquipmentScale}
models={resolved.equipmentModels}
root={scene}
transforms={equipmentAttachmentTransforms}
/>
</>
);