Release v0.1.2 2026-07-11
This commit is contained in:
@@ -17,6 +17,7 @@ const SPIDER_TEXTURE_URLS: Record<string, string> = {
|
||||
"haar_detail_NRM.jpg": new URL("../../game_assets/models/downloaded/low-poly-spider/textures/haar_detail_NRM.jpg", import.meta.url).href,
|
||||
};
|
||||
const DRAGON_URL = new URL("../../game_assets/models/claudecraft/creatures/dragonevolved.glb", import.meta.url).href;
|
||||
const EMBER_MANTIS_URL = new URL("../../game_assets/models/original/bosses/ember-mantis-duelist/ember_mantis_duelist.glb", import.meta.url).href;
|
||||
const PARTY_MODEL_URLS: Record<MemberId, string> = {
|
||||
aelia: new URL("../../game_assets/models/claudecraft/chars/players/druid.glb", import.meta.url).href,
|
||||
brann: new URL("../../game_assets/models/claudecraft/chars/players/knight.glb", import.meta.url).href,
|
||||
@@ -491,7 +492,7 @@ function BossFallback({ bossIndex }: { bossIndex: number }) {
|
||||
return (
|
||||
<mesh castShadow position={[position[0], 1.1, position[1]]}>
|
||||
<dodecahedronGeometry args={[1.1, 0]} />
|
||||
<meshStandardMaterial color={bossId === "vexa" ? "#56306f" : bossId === "cindermaw" ? "#9d4c24" : "#7b3928"} emissive="#3a100c" emissiveIntensity={0.5} />
|
||||
<meshStandardMaterial color={bossId === "vexa" ? "#56306f" : bossId === "cindermaw" ? "#9d4c24" : bossId === "ember-mantis-duelist" ? "#a42d18" : "#7b3928"} emissive="#3a100c" emissiveIntensity={0.5} />
|
||||
</mesh>
|
||||
);
|
||||
}
|
||||
@@ -580,7 +581,7 @@ function BullBoss({ bossIndex }: { bossIndex: number }) {
|
||||
);
|
||||
}
|
||||
|
||||
type AlternateBossKind = "vexa" | "cindermaw";
|
||||
type AlternateBossKind = "vexa" | "cindermaw" | "ember-mantis-duelist";
|
||||
|
||||
const ALTERNATE_BOSS_CONFIG = {
|
||||
vexa: {
|
||||
@@ -605,6 +606,17 @@ const ALTERNATE_BOSS_CONFIG = {
|
||||
light: "#ff8742",
|
||||
rotationOffset: 0,
|
||||
},
|
||||
"ember-mantis-duelist": {
|
||||
url: EMBER_MANTIS_URL,
|
||||
scale: 0.78,
|
||||
idle: "Idle",
|
||||
move: "Sidestep",
|
||||
attack: "LineSlash",
|
||||
special: "CrossSlash",
|
||||
death: "Death",
|
||||
light: "#ff5a24",
|
||||
rotationOffset: 0,
|
||||
},
|
||||
} as const;
|
||||
|
||||
function AlternateBoss({ kind, bossIndex }: { kind: AlternateBossKind; bossIndex: number }) {
|
||||
@@ -634,27 +646,43 @@ function AlternateBoss({ kind, bossIndex }: { kind: AlternateBossKind; bossIndex
|
||||
|
||||
const clipName = phase === "victory" || defeated
|
||||
? config.death
|
||||
: motionMode === "skyfall"
|
||||
? config.move
|
||||
: motionMode === "breath_telegraph" || motionMode === "breath_sweeping"
|
||||
? config.special
|
||||
: motionMode === "tethering" || motionMode === "venom_cast"
|
||||
: kind === "ember-mantis-duelist"
|
||||
? motionMode === "mantis_sidestep"
|
||||
? config.move
|
||||
: motionMode === "mantis_line_telegraph"
|
||||
? config.attack
|
||||
: config.idle;
|
||||
: motionMode === "mantis_cross_telegraph"
|
||||
? config.special
|
||||
: motionMode === "mantis_recover"
|
||||
? "Recover"
|
||||
: config.idle
|
||||
: motionMode === "skyfall"
|
||||
? config.move
|
||||
: motionMode === "breath_telegraph" || motionMode === "breath_sweeping"
|
||||
? config.special
|
||||
: motionMode === "tethering" || motionMode === "venom_cast"
|
||||
? config.attack
|
||||
: config.idle;
|
||||
|
||||
useEffect(() => {
|
||||
const next = actions[clipName];
|
||||
if (!next) return;
|
||||
for (const action of Object.values(actions)) action?.fadeOut(0.16);
|
||||
next.reset().setEffectiveWeight(1).fadeIn(0.16).play();
|
||||
if (phase === "victory" || defeated) {
|
||||
const timeScale = kind === "ember-mantis-duelist" && motionMode === "mantis_line_telegraph"
|
||||
? 0.55
|
||||
: kind === "ember-mantis-duelist" && motionMode === "mantis_cross_telegraph"
|
||||
? 0.6
|
||||
: 1;
|
||||
next.reset().setEffectiveWeight(1).setEffectiveTimeScale(timeScale).fadeIn(0.16).play();
|
||||
const emberOneShot = kind === "ember-mantis-duelist" && clipName !== config.idle;
|
||||
if (phase === "victory" || defeated || emberOneShot) {
|
||||
next.setLoop(THREE.LoopOnce, 1);
|
||||
next.clampWhenFinished = true;
|
||||
} else {
|
||||
next.setLoop(THREE.LoopRepeat, Number.POSITIVE_INFINITY);
|
||||
}
|
||||
return () => { next.fadeOut(0.16); };
|
||||
}, [actions, clipName, defeated, phase]);
|
||||
}, [actions, clipName, config.idle, defeated, kind, motionMode, phase]);
|
||||
|
||||
useFrame((_, delta) => {
|
||||
if (!group.current) return;
|
||||
@@ -672,6 +700,13 @@ function AlternateBoss({ kind, bossIndex }: { kind: AlternateBossKind; bossIndex
|
||||
);
|
||||
if (kind === "cindermaw" && (motion.mode === "breath_telegraph" || motion.mode === "breath_sweeping")) {
|
||||
targetAngle = motion.breathAngle;
|
||||
} else if (kind === "ember-mantis-duelist" && (
|
||||
motion.mode === "mantis_sidestep"
|
||||
|| motion.mode === "mantis_line_telegraph"
|
||||
|| motion.mode === "mantis_cross_telegraph"
|
||||
)) {
|
||||
const target = state.partyPositions[motion.chargeTargetId];
|
||||
targetAngle = Math.atan2(target[0] - motion.position[0], target[1] - motion.position[1]);
|
||||
}
|
||||
const difference = Math.atan2(
|
||||
Math.sin(targetAngle - group.current.rotation.y),
|
||||
@@ -877,7 +912,7 @@ function FxBurst({ kind, targetId }: { kind: PulseKind; targetId?: MemberId }) {
|
||||
const state = useGameStore.getState();
|
||||
const worldPosition = isBossFx ? targetBossMotion(state).position : targetId ? state.partyPositions[targetId] : [0, 0];
|
||||
const position: [number, number, number] = [worldPosition[0], 0.15, worldPosition[1]];
|
||||
const color = kind === "boss" || kind === "debuff" || kind === "charge" || kind === "pounce" ? "#ff643c" : kind === "shield" ? "#62bdff" : kind === "purify" ? "#c39bff" : "#ffe087";
|
||||
const color = kind === "boss" || kind === "debuff" || kind === "charge" || kind === "pounce" || kind === "slash" ? "#ff643c" : kind === "shield" ? "#62bdff" : kind === "purify" ? "#c39bff" : "#ffe087";
|
||||
useFrame((_, delta) => {
|
||||
age.current += delta;
|
||||
if (!ring.current || !material.current) return;
|
||||
@@ -926,6 +961,7 @@ export function GameScene() {
|
||||
}
|
||||
|
||||
useGLTF.preload(BULL_URL, false, true);
|
||||
useGLTF.preload(EMBER_MANTIS_URL, false, true);
|
||||
for (const modelUrl of Object.values(PARTY_MODEL_URLS)) useGLTF.preload(modelUrl, false, true);
|
||||
for (const loadout of Object.values(PARTY_WEAPON_URLS)) {
|
||||
useGLTF.preload(loadout.right, false, true);
|
||||
|
||||
Reference in New Issue
Block a user