Release v0.1.9 2026-07-13
This commit is contained in:
@@ -30,15 +30,30 @@ import type { BossId, MemberId, PulseKind } from "../game/types";
|
||||
import { BossRoom } from "./BossRoom";
|
||||
import { BossMechanicIndicators } from "./boss/BossMechanicIndicators";
|
||||
import { bossCanTrackTarget, bossDeathOpacity } from "./boss/bossDeathVisuals";
|
||||
import { GameAssetProvider, LEGACY_GAME_ASSETS_FORCED, selectedGameAssetUrl, useGameGLTF } from "./GameAssetProvider";
|
||||
|
||||
const PARTY_MODEL_URLS: Record<MemberId, string> = {
|
||||
const PARTY_MODEL_LEGACY_URLS: Record<MemberId, string> = {
|
||||
aelia: new URL("../assets/game/models/claudecraft/chars/players/druid.glb", import.meta.url).href,
|
||||
brann: new URL("../assets/game/models/claudecraft/chars/players/knight.glb", import.meta.url).href,
|
||||
nia: new URL("../assets/game/models/claudecraft/chars/players/ranger.glb", import.meta.url).href,
|
||||
orin: new URL("../assets/game/models/claudecraft/chars/players/mage.glb", import.meta.url).href,
|
||||
vale: new URL("../assets/game/models/claudecraft/chars/players/rogue.glb", import.meta.url).href,
|
||||
};
|
||||
const PARTY_WEAPON_URLS: Record<MemberId, { right: string; left?: string }> = {
|
||||
const PARTY_MODEL_OPTIMIZED_URLS: Record<MemberId, string> = {
|
||||
aelia: new URL("../assets/game/models/claudecraft/chars/players/druid-uastc.glb", import.meta.url).href,
|
||||
brann: new URL("../assets/game/models/claudecraft/chars/players/knight-uastc.glb", import.meta.url).href,
|
||||
nia: new URL("../assets/game/models/claudecraft/chars/players/ranger-uastc.glb", import.meta.url).href,
|
||||
orin: new URL("../assets/game/models/claudecraft/chars/players/mage-uastc.glb", import.meta.url).href,
|
||||
vale: new URL("../assets/game/models/claudecraft/chars/players/rogue-uastc.glb", import.meta.url).href,
|
||||
};
|
||||
const PARTY_MODEL_URLS = Object.fromEntries(Object.keys(PARTY_MODEL_LEGACY_URLS).map((memberId) => [
|
||||
memberId,
|
||||
selectedGameAssetUrl(
|
||||
PARTY_MODEL_LEGACY_URLS[memberId as MemberId],
|
||||
PARTY_MODEL_OPTIMIZED_URLS[memberId as MemberId],
|
||||
),
|
||||
])) as Record<MemberId, string>;
|
||||
const PARTY_WEAPON_LEGACY_URLS: Record<MemberId, { right: string; left?: string }> = {
|
||||
aelia: { right: new URL("../assets/game/models/claudecraft/weapons/adv_druid_staff.glb", import.meta.url).href },
|
||||
brann: {
|
||||
right: new URL("../assets/game/models/claudecraft/weapons/adv_sword_1handed.glb", import.meta.url).href,
|
||||
@@ -54,6 +69,30 @@ const PARTY_WEAPON_URLS: Record<MemberId, { right: string; left?: string }> = {
|
||||
left: new URL("../assets/game/models/claudecraft/weapons/adv_dagger.glb", import.meta.url).href,
|
||||
},
|
||||
};
|
||||
const PARTY_WEAPON_OPTIMIZED_URLS: Record<MemberId, { right: string; left?: string }> = {
|
||||
aelia: { right: new URL("../assets/game/models/claudecraft/weapons/adv_druid_staff-uastc.glb", import.meta.url).href },
|
||||
brann: {
|
||||
right: new URL("../assets/game/models/claudecraft/weapons/adv_sword_1handed-uastc.glb", import.meta.url).href,
|
||||
left: new URL("../assets/game/models/claudecraft/weapons/shield_badge-uastc.glb", import.meta.url).href,
|
||||
},
|
||||
nia: { right: new URL("../assets/game/models/claudecraft/weapons/crossbow_2handed-uastc.glb", import.meta.url).href },
|
||||
orin: {
|
||||
right: new URL("../assets/game/models/claudecraft/weapons/adv_wand-uastc.glb", import.meta.url).href,
|
||||
left: new URL("../assets/game/models/claudecraft/weapons/spellbook_open-uastc.glb", import.meta.url).href,
|
||||
},
|
||||
vale: {
|
||||
right: new URL("../assets/game/models/claudecraft/weapons/adv_dagger-uastc.glb", import.meta.url).href,
|
||||
left: new URL("../assets/game/models/claudecraft/weapons/adv_dagger-uastc.glb", import.meta.url).href,
|
||||
},
|
||||
};
|
||||
const PARTY_WEAPON_URLS = Object.fromEntries(Object.keys(PARTY_WEAPON_LEGACY_URLS).map((memberId) => {
|
||||
const legacy = PARTY_WEAPON_LEGACY_URLS[memberId as MemberId];
|
||||
const optimized = PARTY_WEAPON_OPTIMIZED_URLS[memberId as MemberId];
|
||||
return [memberId, {
|
||||
right: selectedGameAssetUrl(legacy.right, optimized.right),
|
||||
left: legacy.left && optimized.left ? selectedGameAssetUrl(legacy.left, optimized.left) : undefined,
|
||||
}];
|
||||
})) as Record<MemberId, { right: string; left?: string }>;
|
||||
const PARTY_MODEL_SCALES: Record<MemberId, number> = { aelia: 0.62, brann: 0.68, nia: 0.7, orin: 0.64, vale: 0.72 };
|
||||
const PARTY_ATTACK_CLIPS: Record<MemberId, string> = {
|
||||
aelia: "2H_Melee_Attack_Chop",
|
||||
@@ -227,12 +266,12 @@ function PartyCharacterModel({
|
||||
animationState: MutableRefObject<ActorAnimationState>;
|
||||
animationTrigger: MutableRefObject<number>;
|
||||
}) {
|
||||
const gltf = useGLTF(PARTY_MODEL_URLS[memberId], false, true);
|
||||
const gltf = useGameGLTF(PARTY_MODEL_URLS[memberId]);
|
||||
const actorScene = useMemo(() => cloneSkeleton(gltf.scene), [gltf.scene]);
|
||||
const loadout = PARTY_WEAPON_URLS[memberId];
|
||||
const grips = PARTY_WEAPON_GRIPS[memberId];
|
||||
const rightWeapon = useGLTF(loadout.right, false, true);
|
||||
const leftWeapon = useGLTF(loadout.left ?? loadout.right, false, true);
|
||||
const rightWeapon = useGameGLTF(loadout.right);
|
||||
const leftWeapon = useGameGLTF(loadout.left ?? loadout.right);
|
||||
const rightHandSlot = resolveRigNode(actorScene, "handslot.r");
|
||||
const leftHandSlot = resolveRigNode(actorScene, "handslot.l");
|
||||
const rightWeaponScene = useMemo(
|
||||
@@ -793,7 +832,8 @@ function AlternateBoss({ kind, bossIndex }: { kind: AlternateBossKind; bossIndex
|
||||
const defeated = bossHp <= 0;
|
||||
const group = useRef<THREE.Group>(null);
|
||||
const light = useRef<THREE.PointLight>(null);
|
||||
const gltf = useGLTF(config.url, false, true);
|
||||
const assetUrl = selectedGameAssetUrl(config.url, config.optimizedUrl ?? config.url);
|
||||
const gltf = useGameGLTF(assetUrl);
|
||||
const { model, fadeMaterials } = useMemo(() => createBossRenderModel(gltf.scene), [gltf.scene]);
|
||||
const { actions } = useAnimations(gltf.animations, model);
|
||||
const targetPosition = useMemo(() => new THREE.Vector3(), []);
|
||||
@@ -1184,23 +1224,27 @@ export function GameScene() {
|
||||
camera={{ position: [0, 5.2, 12], fov: 48, near: 0.1, far: 70 }}
|
||||
gl={{ alpha: false, antialias: false, powerPreference: "high-performance" }}
|
||||
>
|
||||
<SceneFrameScheduler dpr={dpr} onDprChange={setRenderDpr} />
|
||||
<BossRoom />
|
||||
<BossMechanicIndicators />
|
||||
<BarrierField />
|
||||
<TankAuraField />
|
||||
<Party />
|
||||
<BossActor />
|
||||
<RangedProjectiles />
|
||||
<CombatFx />
|
||||
{PERFORMANCE_PROBE_ENABLED && <PerformanceProbe />}
|
||||
<GameAssetProvider>
|
||||
<SceneFrameScheduler dpr={dpr} onDprChange={setRenderDpr} />
|
||||
<BossRoom />
|
||||
<BossMechanicIndicators />
|
||||
<BarrierField />
|
||||
<TankAuraField />
|
||||
<Party />
|
||||
<BossActor />
|
||||
<RangedProjectiles />
|
||||
<CombatFx />
|
||||
{PERFORMANCE_PROBE_ENABLED && <PerformanceProbe />}
|
||||
</GameAssetProvider>
|
||||
</Canvas>
|
||||
);
|
||||
}
|
||||
|
||||
for (const memberId of CRITICAL_PARTY_MEMBER_IDS) {
|
||||
useGLTF.preload(PARTY_MODEL_URLS[memberId], false, true);
|
||||
const loadout = PARTY_WEAPON_URLS[memberId];
|
||||
useGLTF.preload(loadout.right, false, true);
|
||||
if (loadout.left) useGLTF.preload(loadout.left, false, true);
|
||||
if (LEGACY_GAME_ASSETS_FORCED) {
|
||||
for (const memberId of CRITICAL_PARTY_MEMBER_IDS) {
|
||||
useGLTF.preload(PARTY_MODEL_URLS[memberId], false, true);
|
||||
const loadout = PARTY_WEAPON_URLS[memberId];
|
||||
useGLTF.preload(loadout.right, false, true);
|
||||
if (loadout.left) useGLTF.preload(loadout.left, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user