mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
event rewrite done, fixed a lot of stuff, renamed/moved some stuff
This commit is contained in:
parent
7620610097
commit
1d895e64b0
36 changed files with 791 additions and 761 deletions
|
@ -1,4 +1,4 @@
|
||||||
import React, { useRef, useState } from "react";
|
import React, { memo, useRef, useState } from "react";
|
||||||
import middleSpritesheet from "../../static/sprite/end_middle_spritesheet.png";
|
import middleSpritesheet from "../../static/sprite/end_middle_spritesheet.png";
|
||||||
import middleLain from "../../static/sprite/end_middle_lain.png";
|
import middleLain from "../../static/sprite/end_middle_lain.png";
|
||||||
import circleSpritesheet from "../../static/sprite/end_circle_spritesheet.png";
|
import circleSpritesheet from "../../static/sprite/end_circle_spritesheet.png";
|
||||||
|
@ -10,7 +10,11 @@ import { PlainAnimator } from "three-plain-animator/lib/plain-animator";
|
||||||
import { a, useSpring } from "@react-spring/three";
|
import { a, useSpring } from "@react-spring/three";
|
||||||
import { useStore } from "../../store";
|
import { useStore } from "../../store";
|
||||||
|
|
||||||
const EndSelectionScreen = () => {
|
type EndSelectionScreenProps = {
|
||||||
|
visible: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const EndSelectionScreen = memo((props: EndSelectionScreenProps) => {
|
||||||
const middleSpritesheetTex: any = useLoader(
|
const middleSpritesheetTex: any = useLoader(
|
||||||
THREE.TextureLoader,
|
THREE.TextureLoader,
|
||||||
middleSpritesheet
|
middleSpritesheet
|
||||||
|
@ -63,7 +67,7 @@ const EndSelectionScreen = () => {
|
||||||
const lainOpacity = lainOpacityToggle.to([0, 1], [0, 0.5]);
|
const lainOpacity = lainOpacityToggle.to([0, 1], [0, 0.5]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<group visible={props.visible}>
|
||||||
<sprite position={[-3.5, 0, -3]} scale={[10, 0.8, 0]}>
|
<sprite position={[-3.5, 0, -3]} scale={[10, 0.8, 0]}>
|
||||||
<spriteMaterial attach="material" map={middleSpritesheetTex} />
|
<spriteMaterial attach="material" map={middleSpritesheetTex} />
|
||||||
</sprite>
|
</sprite>
|
||||||
|
@ -93,8 +97,8 @@ const EndSelectionScreen = () => {
|
||||||
opacity={lainOpacity}
|
opacity={lainOpacity}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
</>
|
</group>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default EndSelectionScreen;
|
export default EndSelectionScreen;
|
||||||
|
|
|
@ -31,13 +31,7 @@ const Images = () => {
|
||||||
const textureLoader = useMemo(() => new THREE.TextureLoader(), []);
|
const textureLoader = useMemo(() => new THREE.TextureLoader(), []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let images;
|
const images = currentScene === "idle_media" ? idleNodeImages : nodeImages;
|
||||||
if (currentScene === "media" || currentScene === "tak") {
|
|
||||||
images = nodeImages;
|
|
||||||
} else if (currentScene === "idle_media") {
|
|
||||||
images = idleNodeImages;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (images) {
|
if (images) {
|
||||||
// checking the length of the img arr doesn't work in some cases
|
// checking the length of the img arr doesn't work in some cases
|
||||||
// since the amount of images varies from 1 to 3.
|
// since the amount of images varies from 1 to 3.
|
||||||
|
|
|
@ -1,32 +1,23 @@
|
||||||
import { useCallback, useEffect, useRef } from "react";
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
BootSceneContext,
|
|
||||||
EndSceneContext,
|
|
||||||
getBootSceneContext,
|
getBootSceneContext,
|
||||||
getEndSceneContext,
|
getEndSceneContext,
|
||||||
getMainSceneContext,
|
getMainSceneContext,
|
||||||
getMediaSceneContext,
|
getMediaSceneContext,
|
||||||
getSsknSceneContext,
|
getSsknSceneContext,
|
||||||
MainSceneContext,
|
|
||||||
MediaSceneContext,
|
|
||||||
playAudio,
|
playAudio,
|
||||||
SsknSceneContext,
|
|
||||||
useStore,
|
useStore,
|
||||||
} from "../store";
|
} from "../store";
|
||||||
import { getKeyCodeAssociation } from "../utils/keyPressUtils";
|
import { getKeyCodeAssociation } from "../utils/getKey";
|
||||||
import handleMediaSceneKeyPress from "../core/scene-keypress-handlers/handleMediaSceneKeyPress";
|
import handleMediaSceneKeyPress from "../core/scene-keypress-handlers/handleMediaSceneKeyPress";
|
||||||
import handleSsknSceneKeyPress from "../core/scene-keypress-handlers/handleSsknSceneKeyPress";
|
import handleSsknSceneKeyPress from "../core/scene-keypress-handlers/handleSsknSceneKeyPress";
|
||||||
import handleMainSceneKeyPress from "../core/scene-keypress-handlers/handleMainSceneKeyPress";
|
import handleMainSceneKeyPress from "../core/scene-keypress-handlers/handleMainSceneKeyPress";
|
||||||
import handleBootSceneKeyPress from "../core/scene-keypress-handlers/handleBootSceneKeyPress";
|
import handleBootSceneKeyPress from "../core/scene-keypress-handlers/handleBootSceneKeyPress";
|
||||||
import { useFrame } from "react-three-fiber";
|
import { useFrame } from "react-three-fiber";
|
||||||
import { getRandomIdleLainAnim } from "../utils/idle-utils";
|
import { getRandomIdleLainAnim } from "../helpers/idle-helpers";
|
||||||
import * as audio from "../static/sfx";
|
import * as audio from "../static/audio/sfx";
|
||||||
import handleEndSceneKeyPress from "../core/scene-keypress-handlers/handleEndSceneKeyPress";
|
import handleEndSceneKeyPress from "../core/scene-keypress-handlers/handleEndSceneKeyPress";
|
||||||
import handleMediaSceneEvent from "../core/scene-event-handlers/handleMediaSceneEvent";
|
import handleEvent, { GameEvent } from "../core/handleEvent";
|
||||||
import handleSsknSceneEvent from "../core/scene-event-handlers/handleSsknSceneEvent";
|
|
||||||
import handleBootSceneEvent from "../core/scene-event-handlers/handleBootSceneEvent";
|
|
||||||
import handleEndSceneEvent from "../core/scene-event-handlers/handleEndSceneEvent";
|
|
||||||
import handleEvent from "../core/scene-event-handlers/handleEvent";
|
|
||||||
|
|
||||||
const KeyPressHandler = () => {
|
const KeyPressHandler = () => {
|
||||||
const scene = useStore((state) => state.currentScene);
|
const scene = useStore((state) => state.currentScene);
|
||||||
|
@ -83,9 +74,9 @@ const KeyPressHandler = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
keyPress
|
keyPress &&
|
||||||
// !inputCooldown &&
|
now > timeSinceLastKeyPress.current + inputCooldown &&
|
||||||
// now > timeSinceLastKeyPress.current + 1500
|
inputCooldown !== -1
|
||||||
) {
|
) {
|
||||||
if (scene === "main") {
|
if (scene === "main") {
|
||||||
lainIdleCounter.current = now;
|
lainIdleCounter.current = now;
|
||||||
|
@ -105,34 +96,31 @@ const KeyPressHandler = () => {
|
||||||
contextProvider: getMediaSceneContext,
|
contextProvider: getMediaSceneContext,
|
||||||
keyPressHandler: handleMediaSceneKeyPress,
|
keyPressHandler: handleMediaSceneKeyPress,
|
||||||
};
|
};
|
||||||
// case "sskn":
|
case "sskn":
|
||||||
// return {
|
return {
|
||||||
// contextProvider: getSsknSceneContext,
|
contextProvider: getSsknSceneContext,
|
||||||
// keyPressHandler: handleSsknSceneKeyPress,
|
keyPressHandler: handleSsknSceneKeyPress,
|
||||||
// eventHandler: handleSsknSceneEvent,
|
};
|
||||||
// };
|
case "boot":
|
||||||
// case "boot":
|
return {
|
||||||
// return {
|
contextProvider: getBootSceneContext,
|
||||||
// contextProvider: getBootSceneContext,
|
keyPressHandler: handleBootSceneKeyPress,
|
||||||
// keyPressHandler: handleBootSceneKeyPress,
|
};
|
||||||
// eventHandler: handleBootSceneEvent,
|
case "end":
|
||||||
// };
|
return {
|
||||||
// case "end":
|
contextProvider: getEndSceneContext,
|
||||||
// return {
|
keyPressHandler: handleEndSceneKeyPress,
|
||||||
// contextProvider: getEndSceneContext,
|
};
|
||||||
// keyPressHandler: handleEndSceneKeyPress,
|
case "gate":
|
||||||
// eventHandler: handleEndSceneEvent,
|
case "polytan":
|
||||||
// };
|
useStore.setState({ currentScene: "main" });
|
||||||
// case "gate":
|
break;
|
||||||
// case "polytan":
|
case "idle_media":
|
||||||
// useStore.setState({ currentScene: "main" });
|
useStore.setState({
|
||||||
// break;
|
currentScene: "main",
|
||||||
// case "idle_media":
|
idleStarting: false,
|
||||||
// useStore.setState({
|
});
|
||||||
// currentScene: "main",
|
break;
|
||||||
// idleStarting: false,
|
|
||||||
// });
|
|
||||||
// break;
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -140,9 +128,8 @@ const KeyPressHandler = () => {
|
||||||
const { contextProvider, keyPressHandler } = sceneFns;
|
const { contextProvider, keyPressHandler } = sceneFns;
|
||||||
|
|
||||||
const ctx = contextProvider(keyPress);
|
const ctx = contextProvider(keyPress);
|
||||||
const event = keyPressHandler(ctx as any) as any;
|
const event: GameEvent | undefined = keyPressHandler(ctx as any);
|
||||||
if (event) handleEvent(event);
|
if (event) handleEvent(event);
|
||||||
// if (event) eventHandler(event.event, event.mutations);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,6 +21,9 @@ const Loading = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<sprite scale={[5, 5, 5]}>
|
||||||
|
<spriteMaterial attach="material" color={0x000000} />
|
||||||
|
</sprite>
|
||||||
<sprite scale={[0.35, 0.6, 0.35]} position={[0, 0.2, 0]}>
|
<sprite scale={[0.35, 0.6, 0.35]} position={[0, 0.2, 0]}>
|
||||||
<spriteMaterial attach="material" map={loadingTex} />
|
<spriteMaterial attach="material" map={loadingTex} />
|
||||||
</sprite>
|
</sprite>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { useStore } from "../../store";
|
||||||
import lerp from "../../utils/lerp";
|
import lerp from "../../utils/lerp";
|
||||||
import GreenTextRenderer from "../TextRenderer/GreenTextRenderer";
|
import GreenTextRenderer from "../TextRenderer/GreenTextRenderer";
|
||||||
import usePrevious from "../../hooks/usePrevious";
|
import usePrevious from "../../hooks/usePrevious";
|
||||||
import { getNodeHud } from "../../utils/node-utils";
|
import { getNodeHud } from "../../helpers/node-helpers";
|
||||||
|
|
||||||
export type HUDType = {
|
export type HUDType = {
|
||||||
mirrored: number;
|
mirrored: number;
|
||||||
|
@ -130,7 +130,6 @@ const HUD = memo(() => {
|
||||||
if (
|
if (
|
||||||
!(scene === "main" && prevData?.scene === "main") ||
|
!(scene === "main" && prevData?.scene === "main") ||
|
||||||
(subscene === "site" && prevData?.subscene === "pause") ||
|
(subscene === "site" && prevData?.subscene === "pause") ||
|
||||||
(subscene === "site" && prevData?.subscene === "not_found") ||
|
|
||||||
subscene === "pause"
|
subscene === "pause"
|
||||||
) {
|
) {
|
||||||
// set to final pos instantly
|
// set to final pos instantly
|
||||||
|
|
|
@ -64,7 +64,7 @@ const Pause = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setShowActiveComponent(true);
|
setShowActiveComponent(true);
|
||||||
setIntro(false);
|
setIntro(false);
|
||||||
setInputCooldown(false);
|
setInputCooldown(1000);
|
||||||
}, 3500);
|
}, 3500);
|
||||||
}, 3400);
|
}, 3400);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,16 @@ import notFound from "../../../static/sprite/not_found.png";
|
||||||
import notFoundLof from "../../../static/sprite/not_found_lof.png";
|
import notFoundLof from "../../../static/sprite/not_found_lof.png";
|
||||||
import { useLoader } from "react-three-fiber";
|
import { useLoader } from "react-three-fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
import { useStore } from "../../../store";
|
||||||
|
|
||||||
const NotFound = memo(() => {
|
const NotFound = memo(() => {
|
||||||
const notFoundTex = useLoader(THREE.TextureLoader, notFound);
|
const notFoundTex = useLoader(THREE.TextureLoader, notFound);
|
||||||
const notFoundLofTex = useLoader(THREE.TextureLoader, notFoundLof);
|
const notFoundLofTex = useLoader(THREE.TextureLoader, notFoundLof);
|
||||||
|
|
||||||
|
const wordNotFound = useStore((state) => state.wordNotFound);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group visible={false}>
|
<group visible={wordNotFound}>
|
||||||
<sprite scale={[1, 0.25, 0]} renderOrder={106} position={[-1, -0.05, 0]}>
|
<sprite scale={[1, 0.25, 0]} renderOrder={106} position={[-1, -0.05, 0]}>
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useStore } from "../../../store";
|
||||||
import { SiteData } from "./Site";
|
import { SiteData } from "./Site";
|
||||||
import InactiveLevelNode from "./InactiveLevelNode";
|
import InactiveLevelNode from "./InactiveLevelNode";
|
||||||
import usePrevious from "../../../hooks/usePrevious";
|
import usePrevious from "../../../hooks/usePrevious";
|
||||||
import { generateInactiveNodes } from "../../../utils/node-utils";
|
import { generateInactiveNodes } from "../../../helpers/node-helpers";
|
||||||
|
|
||||||
type ActiveLevelNodesProps = {
|
type ActiveLevelNodesProps = {
|
||||||
visibleNodes: SiteData;
|
visibleNodes: SiteData;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import InactiveLevelNodes from "./InactiveLevelNodes";
|
||||||
import site_a from "../../../resources/site_a.json";
|
import site_a from "../../../resources/site_a.json";
|
||||||
import site_b from "../../../resources/site_b.json";
|
import site_b from "../../../resources/site_b.json";
|
||||||
import level_y_values from "../../../resources/level_y_values.json";
|
import level_y_values from "../../../resources/level_y_values.json";
|
||||||
import { filterInvisibleNodes } from "../../../utils/node-utils";
|
import { filterInvisibleNodes } from "../../../helpers/node-helpers";
|
||||||
import Loading from "../../Loading";
|
import Loading from "../../Loading";
|
||||||
|
|
||||||
export type NodeData = {
|
export type NodeData = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { memo } from "react";
|
||||||
import body from "../../static/sprite/body.png";
|
import body from "../../static/sprite/body.png";
|
||||||
import head from "../../static/sprite/head.png";
|
import head from "../../static/sprite/head.png";
|
||||||
import leftLeg from "../../static/sprite/left_leg.png";
|
import leftLeg from "../../static/sprite/left_leg.png";
|
||||||
|
@ -8,19 +8,9 @@ import rightLeg from "../../static/sprite/right_leg.png";
|
||||||
import skeleton from "../../static/sprite/polytan_skeleton.png";
|
import skeleton from "../../static/sprite/polytan_skeleton.png";
|
||||||
import { useLoader } from "react-three-fiber";
|
import { useLoader } from "react-three-fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
import { useStore } from "../../store";
|
||||||
|
|
||||||
type PolytanBearProps = {
|
const PolytanBear = memo(() => {
|
||||||
unlockedParts: {
|
|
||||||
body: boolean;
|
|
||||||
head: boolean;
|
|
||||||
leftArm: boolean;
|
|
||||||
rightArm: boolean;
|
|
||||||
leftLeg: boolean;
|
|
||||||
rightLeg: boolean;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const PolytanBear = (props: PolytanBearProps) => {
|
|
||||||
const skeletonTex = useLoader(THREE.TextureLoader, skeleton);
|
const skeletonTex = useLoader(THREE.TextureLoader, skeleton);
|
||||||
const headTex = useLoader(THREE.TextureLoader, head);
|
const headTex = useLoader(THREE.TextureLoader, head);
|
||||||
const bodyTex = useLoader(THREE.TextureLoader, body);
|
const bodyTex = useLoader(THREE.TextureLoader, body);
|
||||||
|
@ -29,6 +19,8 @@ const PolytanBear = (props: PolytanBearProps) => {
|
||||||
const rightArmTex = useLoader(THREE.TextureLoader, rightArm);
|
const rightArmTex = useLoader(THREE.TextureLoader, rightArm);
|
||||||
const rightLegTex = useLoader(THREE.TextureLoader, rightLeg);
|
const rightLegTex = useLoader(THREE.TextureLoader, rightLeg);
|
||||||
|
|
||||||
|
const unlockedParts = useStore((state) => state.polytanUnlockedParts);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<sprite scale={[4, 5, 0]} position={[0, -0.4, 0]}>
|
<sprite scale={[4, 5, 0]} position={[0, -0.4, 0]}>
|
||||||
|
@ -39,7 +31,7 @@ const PolytanBear = (props: PolytanBearProps) => {
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={bodyTex}
|
map={bodyTex}
|
||||||
visible={props.unlockedParts.body}
|
visible={unlockedParts.body}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
|
|
||||||
|
@ -47,39 +39,39 @@ const PolytanBear = (props: PolytanBearProps) => {
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={headTex}
|
map={headTex}
|
||||||
visible={props.unlockedParts.head}
|
visible={unlockedParts.head}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
<sprite scale={[1.9, 1, 0]} position={[1, -2.2, 0]}>
|
<sprite scale={[1.9, 1, 0]} position={[1, -2.2, 0]}>
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={leftLegTex}
|
map={leftLegTex}
|
||||||
visible={props.unlockedParts.leftLeg}
|
visible={unlockedParts.leftLeg}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
<sprite scale={[1.5, 1.9, 0]} position={[1.2, -0.4, 0]}>
|
<sprite scale={[1.5, 1.9, 0]} position={[1.2, -0.4, 0]}>
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={leftArmTex}
|
map={leftArmTex}
|
||||||
visible={props.unlockedParts.leftArm}
|
visible={unlockedParts.leftArm}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
<sprite scale={[1.6, 2, 0]} position={[-1.2, -1.2, 0]}>
|
<sprite scale={[1.6, 2, 0]} position={[-1.2, -1.2, 0]}>
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={rightArmTex}
|
map={rightArmTex}
|
||||||
visible={props.unlockedParts.rightArm}
|
visible={unlockedParts.rightArm}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
<sprite scale={[1.9, 1, 0]} position={[-1, -2.2, 0]}>
|
<sprite scale={[1.9, 1, 0]} position={[-1, -2.2, 0]}>
|
||||||
<spriteMaterial
|
<spriteMaterial
|
||||||
attach="material"
|
attach="material"
|
||||||
map={rightLegTex}
|
map={rightLegTex}
|
||||||
visible={props.unlockedParts.rightLeg}
|
visible={unlockedParts.rightLeg}
|
||||||
/>
|
/>
|
||||||
</sprite>
|
</sprite>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default PolytanBear;
|
export default PolytanBear;
|
||||||
|
|
|
@ -91,7 +91,6 @@ const BigLetter = memo((props: { letter: string; letterIdx: number }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
subscene === "pause" ||
|
subscene === "pause" ||
|
||||||
(subscene === "site" && prevData?.subscene === "not_found") ||
|
|
||||||
(subscene === "site" && prevData?.subscene === "pause")
|
(subscene === "site" && prevData?.subscene === "pause")
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useStore } from "../../store";
|
||||||
import { a, useTrail } from "@react-spring/three";
|
import { a, useTrail } from "@react-spring/three";
|
||||||
import BigLetter from "./BigLetter";
|
import BigLetter from "./BigLetter";
|
||||||
import usePrevious from "../../hooks/usePrevious";
|
import usePrevious from "../../hooks/usePrevious";
|
||||||
import { getNodeHud } from "../../utils/node-utils";
|
import { getNodeHud } from "../../helpers/node-helpers";
|
||||||
|
|
||||||
const MainYellowTextAnimator = (props: { visible?: boolean }) => {
|
const MainYellowTextAnimator = (props: { visible?: boolean }) => {
|
||||||
const activeNode = useStore((state) => state.activeNode);
|
const activeNode = useStore((state) => state.activeNode);
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
import { NodeData } from "../components/MainScene/Site/Site";
|
import { NodeData } from "../components/MainScene/Site/Site";
|
||||||
import * as audio from "../static/sfx";
|
import * as audio from "../static/audio/sfx";
|
||||||
import {
|
import {
|
||||||
nodeExplodeAnimation,
|
nodeExplodeAnimation,
|
||||||
nodeKnockAndFallAnimation,
|
nodeKnockAndFallAnimation,
|
||||||
nodeKnockAnimation,
|
nodeKnockAnimation,
|
||||||
nodeRipAnimation,
|
nodeRipAnimation,
|
||||||
nodeThrowAnimation,
|
nodeThrowAnimation,
|
||||||
} from "../utils/node-animations";
|
} from "../helpers/node-animation-helpers";
|
||||||
import { playAudio } from "../store";
|
import { playMediaElement, resetMediaElement } from "../helpers/media-helpers";
|
||||||
|
import {
|
||||||
|
ActiveSite,
|
||||||
|
EndComponent,
|
||||||
|
GameProgress,
|
||||||
|
GameScene,
|
||||||
|
LeftMediaComponent,
|
||||||
|
MediaComponent,
|
||||||
|
MediaSide,
|
||||||
|
PromptComponent,
|
||||||
|
RightMediaComponent,
|
||||||
|
SiteSaveState,
|
||||||
|
SsknComponent,
|
||||||
|
} from "../store";
|
||||||
|
|
||||||
export const siteMoveHorizontal = (calculatedState: {
|
export const siteMoveHorizontal = (calculatedState: {
|
||||||
lainMoveAnimation: string;
|
lainMoveAnimation: string;
|
||||||
|
@ -19,15 +32,13 @@ export const siteMoveHorizontal = (calculatedState: {
|
||||||
mutation: {
|
mutation: {
|
||||||
lainMoveState: calculatedState.lainMoveAnimation,
|
lainMoveState: calculatedState.lainMoveAnimation,
|
||||||
siteRot: calculatedState.siteRot,
|
siteRot: calculatedState.siteRot,
|
||||||
inputCooldown: true,
|
inputCooldown: 5500,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
activeNode: calculatedState.activeNode,
|
activeNode: calculatedState.activeNode,
|
||||||
lainMoveState: "standing",
|
lainMoveState: "standing",
|
||||||
inputCooldown: false,
|
|
||||||
},
|
},
|
||||||
delay: 3900,
|
delay: 3900,
|
||||||
},
|
},
|
||||||
|
@ -45,37 +56,36 @@ export const siteMoveVertical = (calculatedState: {
|
||||||
mutation: {
|
mutation: {
|
||||||
lainMoveState: calculatedState.lainMoveAnimation,
|
lainMoveState: calculatedState.lainMoveAnimation,
|
||||||
activeLevel: calculatedState.activeLevel,
|
activeLevel: calculatedState.activeLevel,
|
||||||
inputCooldown: true,
|
inputCooldown: 5500,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
activeNode: calculatedState.activeNode,
|
activeNode: calculatedState.activeNode,
|
||||||
lainMoveState: "standing",
|
lainMoveState: "standing",
|
||||||
inputCooldown: false,
|
|
||||||
},
|
},
|
||||||
delay: 3900,
|
delay: 3900,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [
|
audio: [
|
||||||
{ sfx: [audio.sound13], delay: 0 },
|
{ sfx: [audio.sound13] },
|
||||||
{ sfx: [audio.sound10, audio.sound9], delay: 1300 },
|
{ sfx: [audio.sound10, audio.sound9], delay: 1300 },
|
||||||
{ sfx: [audio.sound8], delay: 2700 },
|
{ sfx: [audio.sound8], delay: 2700 },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const changeNode = (calculatedState: { activeNode: NodeData }) => ({
|
export const changeNode = (calculatedState: { activeNode: NodeData }) => ({
|
||||||
state: [{ mutation: { activeNode: calculatedState.activeNode }, delay: 0 }],
|
|
||||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const throwNode = (calculatedState: { currentScene: string }) => ({
|
|
||||||
state: [
|
state: [
|
||||||
{
|
{
|
||||||
mutation: { lainMoveState: "throw_node", inputCooldown: true },
|
mutation: { activeNode: calculatedState.activeNode, inputCooldown: 1500 },
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const throwNode = (calculatedState: { currentScene: GameScene }) => ({
|
||||||
|
state: [
|
||||||
|
{ mutation: { lainMoveState: "throw_node", inputCooldown: -1 } },
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
currentScene: calculatedState.currentScene,
|
currentScene: calculatedState.currentScene,
|
||||||
|
@ -87,18 +97,15 @@ export const throwNode = (calculatedState: { currentScene: string }) => ({
|
||||||
],
|
],
|
||||||
effects: [nodeThrowAnimation],
|
effects: [nodeThrowAnimation],
|
||||||
audio: [
|
audio: [
|
||||||
{ sfx: [audio.sound0], delay: 0 },
|
{ sfx: [audio.sound0] },
|
||||||
{ sfx: [audio.sound12], delay: 1600 },
|
{ sfx: [audio.sound12], delay: 1600 },
|
||||||
{ sfx: [audio.sound13, audio.sound14], delay: 2800 },
|
{ sfx: [audio.sound13, audio.sound14], delay: 2800 },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ripNode = (calculatedState: { currentScene: string }) => ({
|
export const ripNode = (calculatedState: { currentScene: GameScene }) => ({
|
||||||
state: [
|
state: [
|
||||||
{
|
{ mutation: { lainMoveState: "rip_node", inputCooldown: -1 } },
|
||||||
mutation: { lainMoveState: "rip_node", inputCooldown: true },
|
|
||||||
delay: 0,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
currentScene: calculatedState.currentScene,
|
currentScene: calculatedState.currentScene,
|
||||||
|
@ -110,7 +117,7 @@ export const ripNode = (calculatedState: { currentScene: string }) => ({
|
||||||
],
|
],
|
||||||
effects: [nodeRipAnimation],
|
effects: [nodeRipAnimation],
|
||||||
audio: [
|
audio: [
|
||||||
{ sfx: [audio.sound0], delay: 0 },
|
{ sfx: [audio.sound0] },
|
||||||
{ sfx: [audio.sound12], delay: 1600 },
|
{ sfx: [audio.sound12], delay: 1600 },
|
||||||
{ sfx: [audio.sound13, audio.sound15], delay: 4000 },
|
{ sfx: [audio.sound13, audio.sound15], delay: 4000 },
|
||||||
],
|
],
|
||||||
|
@ -121,18 +128,17 @@ export const explodeNode = {
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
lainMoveState: "touch_node_and_get_scared",
|
lainMoveState: "touch_node_and_get_scared",
|
||||||
inputCooldown: true,
|
inputCooldown: 3800,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mutation: { lainMoveState: "standing", inputCooldown: false },
|
mutation: { lainMoveState: "standing" },
|
||||||
delay: 3800,
|
delay: 3800,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
effects: [nodeExplodeAnimation],
|
effects: [nodeExplodeAnimation],
|
||||||
audio: [
|
audio: [
|
||||||
{ sfx: [audio.sound0], delay: 0 },
|
{ sfx: [audio.sound0] },
|
||||||
{ sfx: [audio.sound17], delay: 2400 },
|
{ sfx: [audio.sound17], delay: 2400 },
|
||||||
{ sfx: [audio.sound33], delay: 3150 },
|
{ sfx: [audio.sound33], delay: 3150 },
|
||||||
],
|
],
|
||||||
|
@ -140,33 +146,26 @@ export const explodeNode = {
|
||||||
|
|
||||||
export const knockNode = {
|
export const knockNode = {
|
||||||
state: [
|
state: [
|
||||||
{ mutation: { lainMoveState: "knock", inputCooldown: true }, delay: 0 },
|
{ mutation: { lainMoveState: "knock", inputCooldown: 3500 } },
|
||||||
{
|
{
|
||||||
mutation: { lainMoveState: "standing", inputCooldown: false },
|
mutation: { lainMoveState: "standing" },
|
||||||
delay: 2900,
|
delay: 3500,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
effects: [nodeKnockAnimation],
|
effects: [nodeKnockAnimation],
|
||||||
audio: [
|
audio: [{ sfx: [audio.sound0] }, { sfx: [audio.sound18], delay: 1200 }],
|
||||||
{ sfx: [audio.sound0], delay: 0 },
|
|
||||||
{ sfx: [audio.sound18], delay: 1200 },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const knockNodeAndFall = {
|
export const knockNodeAndFall = {
|
||||||
state: [
|
state: [
|
||||||
|
{ mutation: { lainMoveState: "knock_and_fall", inputCooldown: 6000 } },
|
||||||
{
|
{
|
||||||
mutation: { lainMoveState: "knock_and_fall", inputCooldown: true },
|
mutation: { lainMoveState: "standing" },
|
||||||
delay: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mutation: { lainMoveState: "standing", inputCooldown: false },
|
|
||||||
delay: 7500,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
effects: [nodeKnockAndFallAnimation],
|
effects: [nodeKnockAndFallAnimation],
|
||||||
audio: [
|
audio: [
|
||||||
{ sfx: [audio.sound0], delay: 0 },
|
{ sfx: [audio.sound0] },
|
||||||
{ sfx: [audio.sound18], delay: 1200 },
|
{ sfx: [audio.sound18], delay: 1200 },
|
||||||
{ sfx: [audio.sound19], delay: 2300 },
|
{ sfx: [audio.sound19], delay: 2300 },
|
||||||
{ sfx: [audio.sound33], delay: 3150 },
|
{ sfx: [audio.sound33], delay: 3150 },
|
||||||
|
@ -181,23 +180,28 @@ export const enterLevelSelection = (calculatedState: {
|
||||||
mutation: {
|
mutation: {
|
||||||
selectedLevel: calculatedState.selectedLevel,
|
selectedLevel: calculatedState.selectedLevel,
|
||||||
mainSubscene: "level_selection",
|
mainSubscene: "level_selection",
|
||||||
|
inputCooldown: 1500,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const exitLevelSelection = {
|
export const exitLevelSelection = {
|
||||||
state: [{ mutation: { mainSubscene: "site" }, delay: 0 }],
|
state: [{ mutation: { mainSubscene: "site", inputCooldown: 1500 } }],
|
||||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const changeSelectedLevel = (calculatedState: {
|
export const changeSelectedLevel = (calculatedState: {
|
||||||
selectedLevel: number;
|
selectedLevel: number;
|
||||||
}) => ({
|
}) => ({
|
||||||
state: [
|
state: [
|
||||||
{ mutation: { selectedLevel: calculatedState.selectedLevel }, delay: 0 },
|
{
|
||||||
|
mutation: {
|
||||||
|
selectedLevel: calculatedState.selectedLevel,
|
||||||
|
inputCooldown: 300,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -212,15 +216,13 @@ export const selectLevel = (calculatedState: {
|
||||||
lainMoveState: calculatedState.lainMoveState,
|
lainMoveState: calculatedState.lainMoveState,
|
||||||
activeLevel: calculatedState.activeLevel,
|
activeLevel: calculatedState.activeLevel,
|
||||||
mainSubscene: "site",
|
mainSubscene: "site",
|
||||||
inputCooldown: true,
|
inputCooldown: 5500,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
activeNode: calculatedState.activeNode,
|
activeNode: calculatedState.activeNode,
|
||||||
lainMoveState: "standing",
|
lainMoveState: "standing",
|
||||||
inputCooldown: false,
|
|
||||||
},
|
},
|
||||||
delay: 3900,
|
delay: 3900,
|
||||||
},
|
},
|
||||||
|
@ -238,19 +240,15 @@ export const pauseGame = (calculatedState: { siteRot: number[] }) => ({
|
||||||
lainMoveState: "rip_middle_ring",
|
lainMoveState: "rip_middle_ring",
|
||||||
pauseExitAnimation: false,
|
pauseExitAnimation: false,
|
||||||
mainSubscene: "pause",
|
mainSubscene: "pause",
|
||||||
inputCooldown: true,
|
inputCooldown: -1,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mutation: { siteRot: calculatedState.siteRot },
|
mutation: { siteRot: calculatedState.siteRot },
|
||||||
delay: 3600,
|
delay: 3600,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [
|
audio: [{ sfx: [audio.sound7] }, { sfx: [audio.sound23], delay: 3600 }],
|
||||||
{ sfx: [audio.sound7], delay: 0 },
|
|
||||||
{ sfx: [audio.sound23], delay: 3600 },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const changePauseComponent = (calculatedState: {
|
export const changePauseComponent = (calculatedState: {
|
||||||
|
@ -258,29 +256,31 @@ export const changePauseComponent = (calculatedState: {
|
||||||
}) => ({
|
}) => ({
|
||||||
state: [
|
state: [
|
||||||
{
|
{
|
||||||
mutation: { activePauseComponent: calculatedState.activePauseComponent },
|
mutation: {
|
||||||
delay: 0,
|
activePauseComponent: calculatedState.activePauseComponent,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const showPermissionDenied = {
|
export const showPermissionDenied = {
|
||||||
state: [
|
state: [
|
||||||
{ mutation: { permissionDenied: true }, delay: 0 },
|
{ mutation: { permissionDenied: true, inputCooldown: 1200 } },
|
||||||
{ mutation: { permissionDenied: false }, delay: 1200 },
|
{ mutation: { permissionDenied: false }, delay: 1200 },
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const displayPrompt = {
|
export const displayPrompt = {
|
||||||
state: [{ mutation: { promptVisible: true }, delay: 0 }],
|
state: [{ mutation: { promptVisible: true, inputCooldown: 500 } }],
|
||||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const showAbout = {
|
export const showAbout = {
|
||||||
state: [{ mutation: { showingAbout: true }, delay: 0 }],
|
state: [{ mutation: { showingAbout: true } }],
|
||||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const exitPause = (calculatedState: { siteRot: number[] }) => ({
|
export const exitPause = (calculatedState: { siteRot: number[] }) => ({
|
||||||
|
@ -290,9 +290,8 @@ export const exitPause = (calculatedState: { siteRot: number[] }) => ({
|
||||||
siteRot: calculatedState.siteRot,
|
siteRot: calculatedState.siteRot,
|
||||||
pauseExitAnimation: true,
|
pauseExitAnimation: true,
|
||||||
activePauseComponent: "change",
|
activePauseComponent: "change",
|
||||||
inputCooldown: true,
|
inputCooldown: 1400,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
|
@ -303,84 +302,70 @@ export const exitPause = (calculatedState: { siteRot: number[] }) => ({
|
||||||
delay: 1200,
|
delay: 1200,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const exitAbout = {
|
export const exitAbout = {
|
||||||
state: [{ mutation: { showingAbout: false }, delay: 0 }],
|
state: [{ mutation: { showingAbout: false, inputCooldown: 500 } }],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const changePromptComponent = (calculatedState: {
|
export const changePromptComponent = (calculatedState: {
|
||||||
activePromptComponent: "yes" | "no";
|
activePromptComponent: PromptComponent;
|
||||||
}) => ({
|
}) => ({
|
||||||
state: [
|
state: [
|
||||||
{
|
{
|
||||||
mutation: {
|
mutation: {
|
||||||
activePromptComponent: calculatedState.activePromptComponent,
|
activePromptComponent: calculatedState.activePromptComponent,
|
||||||
|
inputCooldown: 500,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const exitPrompt = {
|
export const exitPrompt = {
|
||||||
state: [
|
state: [
|
||||||
{
|
{
|
||||||
mutation: { activePromptComponent: "no", promptVisible: false },
|
mutation: {
|
||||||
delay: 0,
|
activePromptComponent: "no",
|
||||||
|
promptVisible: false,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound28], delay: 0 }],
|
audio: [{ sfx: [audio.sound28] }],
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo actually save
|
// todo actually save
|
||||||
export const saveGame = () => ({
|
export const saveGame = () => ({
|
||||||
state: [
|
state: [
|
||||||
{
|
{ mutation: { saveSuccessful: true, inputCooldown: 1200 } },
|
||||||
mutation: { saveSuccessful: true },
|
|
||||||
delay: 0,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
mutation: { saveSuccessful: undefined },
|
mutation: { saveSuccessful: undefined },
|
||||||
delay: 1200,
|
delay: 1200,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound28], delay: 0 }],
|
audio: [{ sfx: [audio.sound28] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
// todo actually load
|
// todo actually load
|
||||||
export const loadGame = () => ({
|
export const loadGame = () => ({
|
||||||
state: [
|
state: [
|
||||||
{
|
{ mutation: { loadSuccessful: true, inputCooldown: 1200 } },
|
||||||
mutation: { loadSuccessful: true },
|
|
||||||
delay: 0,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
mutation: { loadSuccessful: undefined },
|
mutation: { loadSuccessful: undefined },
|
||||||
delay: 1200,
|
delay: 1200,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound28], delay: 0 }],
|
audio: [{ sfx: [audio.sound28] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const changeSite = (calculatedState: {
|
export const changeSite = (calculatedState: {
|
||||||
newActiveSite: "a" | "b";
|
newActiveSite: ActiveSite;
|
||||||
newActiveNode: NodeData;
|
newActiveNode: NodeData;
|
||||||
newActiveLevel: string;
|
newActiveLevel: string;
|
||||||
newSiteRot: number[];
|
newSiteRot: number[];
|
||||||
newSiteSaveState: {
|
newSiteSaveState: SiteSaveState;
|
||||||
a: {
|
|
||||||
activeNode: NodeData;
|
|
||||||
siteRot: number[];
|
|
||||||
activeLevel: string;
|
|
||||||
};
|
|
||||||
b: {
|
|
||||||
activeNode: NodeData;
|
|
||||||
siteRot: number[];
|
|
||||||
activeLevel: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}) => ({
|
}) => ({
|
||||||
state: [
|
state: [
|
||||||
{
|
{
|
||||||
|
@ -397,26 +382,274 @@ export const changeSite = (calculatedState: {
|
||||||
activeLevel: calculatedState.newActiveLevel,
|
activeLevel: calculatedState.newActiveLevel,
|
||||||
// save state
|
// save state
|
||||||
siteSaveState: calculatedState.newSiteSaveState,
|
siteSaveState: calculatedState.newSiteSaveState,
|
||||||
|
inputCooldown: -1,
|
||||||
},
|
},
|
||||||
delay: 0,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const changeLeftMediaComponent = (calculatedState: {
|
export const changeLeftMediaComponent = (calculatedState: {
|
||||||
activeComponent: "play" | "exit";
|
activeComponent: LeftMediaComponent;
|
||||||
}) => ({
|
}) => ({
|
||||||
state: [
|
state: [
|
||||||
{ mutation: { activeMediaComponent: calculatedState.activeComponent } },
|
{
|
||||||
|
mutation: {
|
||||||
|
activeMediaComponent: calculatedState.activeComponent,
|
||||||
|
inputCooldown: 1200,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const changeMediaSide = (calculatedState: {
|
export const changeMediaSide = (calculatedState: {
|
||||||
activeMediaComponent: "fstWord" | "sndWord" | "thirdWord" | "exit" | "play";
|
activeMediaComponent: MediaComponent;
|
||||||
lastActiveMediaComponents: {
|
lastActiveMediaComponents: {
|
||||||
left: "play" | "exit";
|
left: LeftMediaComponent;
|
||||||
right: "fstWord" | "sndWord" | "thirdWord";
|
right: RightMediaComponent;
|
||||||
};
|
};
|
||||||
currentMediaSide: "right" | "left";
|
currentMediaSide: MediaSide;
|
||||||
}) => ({});
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
activeMediaComponent: calculatedState.activeMediaComponent,
|
||||||
|
lastActiveMediaComponents: calculatedState.lastActiveMediaComponents,
|
||||||
|
currentMediaSide: calculatedState.currentMediaSide,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const playMedia = {
|
||||||
|
state: [{ mutation: { mediaPercentageElapsed: 0, inputCooldown: 500 } }],
|
||||||
|
effects: [playMediaElement],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const exitMedia = {
|
||||||
|
state: [{ mutation: { currentScene: "main", inputCooldown: -1 } }],
|
||||||
|
effects: [resetMediaElement],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const changeRightMediaComponent = (calculatedState: {
|
||||||
|
wordPosStateIdx: number;
|
||||||
|
activeComponent: RightMediaComponent;
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
activeMediaComponent: calculatedState.activeComponent,
|
||||||
|
mediaWordPosStateIdx: calculatedState.wordPosStateIdx,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const wordNotFound = {
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
currentScene: "main",
|
||||||
|
wordNotFound: true,
|
||||||
|
inputCooldown: 300,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound30] }],
|
||||||
|
effects: [resetMediaElement],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hideWordNotFound = {
|
||||||
|
state: [{ mutation: { wordNotFound: false, inputCooldown: 300 } }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectWord = (calculatedState: {
|
||||||
|
activeLevel: string;
|
||||||
|
activeNode: NodeData;
|
||||||
|
siteRot: number[];
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
activeLevel: calculatedState.activeLevel,
|
||||||
|
siteRot: calculatedState.siteRot,
|
||||||
|
activeNode: calculatedState.activeNode,
|
||||||
|
wordSelected: true,
|
||||||
|
currentScene: "main",
|
||||||
|
inputCooldown: -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound29] }],
|
||||||
|
effects: [resetMediaElement],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const changeSsknComponent = (calculatedState: {
|
||||||
|
activeSsknComponent: SsknComponent;
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
activeSsknComponent: calculatedState.activeSsknComponent,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const upgradeSskn = (calculatedState: {
|
||||||
|
gameProgress: GameProgress;
|
||||||
|
ssknLvl: number;
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
gameProgress: calculatedState.gameProgress,
|
||||||
|
ssknLvl: calculatedState.ssknLvl,
|
||||||
|
ssknLoading: true,
|
||||||
|
inputCooldown: -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ mutation: { currentScene: "main" }, delay: 6000 },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const exitSskn = {
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
currentScene: "main",
|
||||||
|
ssknLoading: false,
|
||||||
|
activeSsknComponent: "ok",
|
||||||
|
inputCooldown: -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const changeEndComponent = (calculatedState: {
|
||||||
|
activeEndComponent: EndComponent;
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
activeEndComponent: calculatedState.activeEndComponent,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const endGame = {
|
||||||
|
state: [{ mutation: { currentScene: "boot", inputCooldown: -1 } }],
|
||||||
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo this is probably buggy
|
||||||
|
export const continueGameAfterEnd = {
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: { currentScene: "change_disc", intro: true, inputCooldown: -1 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const changeMainMenuComponent = (calculatedState: {
|
||||||
|
activeMainMenuComponent: "authorize_user" | "load_data";
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
activeMainMenuComponent: calculatedState.activeMainMenuComponent,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound1] }],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const exitLoadData = {
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
bootSubscene: "main_menu",
|
||||||
|
promptVisible: false,
|
||||||
|
activePromptComponent: "no",
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound29] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const enterLoadData = {
|
||||||
|
state: [
|
||||||
|
{ mutation: { bootSubscene: "load_data", inputCooldown: 500 } },
|
||||||
|
{ mutation: { promptVisible: true }, delay: 500 },
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const enterUserAuthorization = {
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
bootSubscene: "authorize_user",
|
||||||
|
authorizeUserLetterIdx: 0,
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const exitUserAuthorization = {
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
playerName: "",
|
||||||
|
bootSubscene: "main_menu",
|
||||||
|
inputCooldown: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
audio: [{ sfx: [audio.sound29] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const startNewGame = {
|
||||||
|
state: [
|
||||||
|
{ mutation: { currentScene: "main", intro: true, inputCooldown: -1 } },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updatePlayerName = (calculatedState: { playerName: string }) => ({
|
||||||
|
state: [{ mutation: { playerName: calculatedState.playerName } }],
|
||||||
|
audio: [{ sfx: [audio.sound0] }],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const removePlayerNameLastChar = (calculatedState: {
|
||||||
|
playerName: string;
|
||||||
|
}) => ({
|
||||||
|
state: [{ mutation: { playerName: calculatedState.playerName } }],
|
||||||
|
audio: [{ sfx: [audio.sound29] }],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const failUpdatePlayerName = { audio: [{ sfx: [audio.sound0] }] };
|
||||||
|
|
||||||
|
export const updateAuthorizeUserLetterIdx = (calculatedState: {
|
||||||
|
authorizeUserLetterIdx: number;
|
||||||
|
}) => ({
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
mutation: {
|
||||||
|
inputCooldown: 300,
|
||||||
|
authorizeUserLetterIdx: calculatedState.authorizeUserLetterIdx,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
|
@ -1,47 +1,44 @@
|
||||||
import { playAudio, useStore } from "../../store";
|
import { playAudio, useStore } from "../store";
|
||||||
import sleep from "../../utils/sleep";
|
import sleep from "../utils/sleep";
|
||||||
|
|
||||||
type Mutation = {
|
type Mutation = {
|
||||||
mutation: Object;
|
mutation: Object;
|
||||||
delay: number;
|
delay?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type EventAudio = {
|
type EventAudio = {
|
||||||
sfx: HTMLAudioElement[];
|
sfx: HTMLAudioElement[];
|
||||||
delay: number;
|
delay?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Event = {
|
export type GameEvent = {
|
||||||
state: Mutation[];
|
state?: Mutation[];
|
||||||
audio?: EventAudio[];
|
audio?: EventAudio[];
|
||||||
effects?: (() => void)[];
|
effects?: (() => void)[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// the async/await here might be misleading for some, it functions as a setTimeout that fires
|
// the async/await here might be misleading for some, it functions as a setTimeout that fires
|
||||||
// multiple async calls without stopping the execution, which is what we want.
|
// multiple async calls without stopping the execution, which is what we want.
|
||||||
const handleEvent = (event: Event) => {
|
const handleEvent = (event: GameEvent) => {
|
||||||
const now = performance.now();
|
|
||||||
const setState = useStore.setState;
|
const setState = useStore.setState;
|
||||||
|
|
||||||
const { state, audio, effects } = event;
|
const { state, effects, audio } = event;
|
||||||
|
|
||||||
state.forEach(async (mutationData) => {
|
if (state)
|
||||||
const { delay, mutation } = mutationData;
|
state.forEach(async (mutationData) => {
|
||||||
if (delay) await sleep(delay);
|
const { delay, mutation } = mutationData;
|
||||||
setState(mutation);
|
if (delay) await sleep(delay);
|
||||||
});
|
setState(mutation);
|
||||||
|
});
|
||||||
|
|
||||||
if (effects) effects.forEach((effect) => effect());
|
if (effects) effects.forEach((effect) => effect());
|
||||||
|
|
||||||
if (audio) {
|
if (audio)
|
||||||
audio.forEach(async (audio) => {
|
audio.forEach(async (audio) => {
|
||||||
const { delay, sfx } = audio;
|
const { delay, sfx } = audio;
|
||||||
if (delay) await sleep(delay);
|
if (delay) await sleep(delay);
|
||||||
sfx.forEach((soundEffect) => playAudio(soundEffect));
|
sfx.forEach((soundEffect) => playAudio(soundEffect));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(performance.now() - now);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handleEvent;
|
export default handleEvent;
|
|
@ -1,84 +0,0 @@
|
||||||
import { playAudio, useStore } from "../../store";
|
|
||||||
import * as audio from "../../static/sfx";
|
|
||||||
|
|
||||||
const handleBootSceneEvent = (eventState: any) => {
|
|
||||||
const setState = useStore.setState;
|
|
||||||
|
|
||||||
switch (eventState.event) {
|
|
||||||
case "main_menu_up":
|
|
||||||
setState({ activeMainMenuComponent: "authorize_user" });
|
|
||||||
playAudio(audio.sound1);
|
|
||||||
break;
|
|
||||||
case "main_menu_down":
|
|
||||||
setState({ activeMainMenuComponent: "load_data" });
|
|
||||||
playAudio(audio.sound1);
|
|
||||||
break;
|
|
||||||
case "main_menu_load_data_select":
|
|
||||||
setState({ bootSubscene: "load_data" });
|
|
||||||
playAudio(audio.sound0);
|
|
||||||
|
|
||||||
setTimeout(() => setState({ promptVisible: true }), 500);
|
|
||||||
break;
|
|
||||||
case "main_menu_authorize_user_select":
|
|
||||||
setState({ authorizeUserLetterIdx: 0, bootSubscene: "authorize_user" });
|
|
||||||
playAudio(audio.sound0);
|
|
||||||
break;
|
|
||||||
case "authorize_user_up":
|
|
||||||
case "authorize_user_down":
|
|
||||||
case "authorize_user_left":
|
|
||||||
case "authorize_user_right":
|
|
||||||
setState({
|
|
||||||
authorizeUserLetterIdx: eventState.authorizeUserLetterIdx,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "authorize_user_back":
|
|
||||||
setState({
|
|
||||||
playerName: "",
|
|
||||||
bootSubscene: "main_menu",
|
|
||||||
});
|
|
||||||
playAudio(audio.sound29);
|
|
||||||
break;
|
|
||||||
case "update_player_name":
|
|
||||||
setState({
|
|
||||||
playerName: eventState.playerName,
|
|
||||||
});
|
|
||||||
playAudio(audio.sound0);
|
|
||||||
break;
|
|
||||||
case "update_player_name_denied":
|
|
||||||
playAudio(audio.sound0);
|
|
||||||
break;
|
|
||||||
case "remove_last_char":
|
|
||||||
setState({ playerName: eventState.playerName });
|
|
||||||
playAudio(audio.sound29);
|
|
||||||
break;
|
|
||||||
case "load_data_no":
|
|
||||||
setState({
|
|
||||||
bootSubscene: "main_menu",
|
|
||||||
promptVisible: false,
|
|
||||||
activePromptComponent: "no",
|
|
||||||
});
|
|
||||||
playAudio(audio.sound29);
|
|
||||||
break;
|
|
||||||
case "load_data_yes":
|
|
||||||
// todo check if data exists
|
|
||||||
setState({ loadSuccessful: true });
|
|
||||||
playAudio(audio.sound28);
|
|
||||||
|
|
||||||
//todo actually load
|
|
||||||
setTimeout(() => setState({ loadSuccessful: undefined }), 1200);
|
|
||||||
break;
|
|
||||||
case "prompt_left":
|
|
||||||
setState({ activePromptComponent: "yes" });
|
|
||||||
playAudio(audio.sound1);
|
|
||||||
break;
|
|
||||||
case "prompt_right":
|
|
||||||
setState({ activePromptComponent: "no" });
|
|
||||||
playAudio(audio.sound1);
|
|
||||||
break;
|
|
||||||
case "start_new_game":
|
|
||||||
setState({ currentScene: "main", intro: true });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default handleBootSceneEvent;
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { useStore } from "../../store";
|
|
||||||
|
|
||||||
const handleEndSceneEvent = (eventState: any) => {
|
|
||||||
const setState = useStore.setState;
|
|
||||||
switch (eventState.event) {
|
|
||||||
case "end_selection_up":
|
|
||||||
setState({ activeEndComponent: "end" });
|
|
||||||
break;
|
|
||||||
case "end_selection_down":
|
|
||||||
setState({ activeEndComponent: "continue" });
|
|
||||||
break;
|
|
||||||
case "end_continue_select":
|
|
||||||
setState({ currentScene: "change_disc", intro: true });
|
|
||||||
break;
|
|
||||||
case "end_end_select":
|
|
||||||
setState({ currentScene: "boot" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default handleEndSceneEvent;
|
|
|
@ -1,84 +0,0 @@
|
||||||
import { playAudio, useStore } from "../../store";
|
|
||||||
import * as audio from "../../static/sfx";
|
|
||||||
|
|
||||||
const handleMediaSceneEvent = (eventState: any) => {
|
|
||||||
const setState = useStore.setState;
|
|
||||||
|
|
||||||
const setNodeViewed = useStore.getState().setNodeViewed;
|
|
||||||
const updateLeftSide = useStore.getState().updateLeftSide;
|
|
||||||
const updateRightSide = useStore.getState().updateRightSide;
|
|
||||||
|
|
||||||
const setPercentageElapsed = useStore.getState().setPercentageElapsed;
|
|
||||||
|
|
||||||
const playMedia = () => {
|
|
||||||
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
|
||||||
|
|
||||||
if (mediaElement && mediaElement.paused) {
|
|
||||||
setPercentageElapsed(0);
|
|
||||||
|
|
||||||
mediaElement.play();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const exitMedia = () => {
|
|
||||||
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
|
||||||
if (mediaElement) {
|
|
||||||
mediaElement.pause();
|
|
||||||
mediaElement.currentTime = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (eventState.event) {
|
|
||||||
case "media_rightside_down":
|
|
||||||
case "media_rightside_up":
|
|
||||||
setState({
|
|
||||||
activeMediaComponent: eventState.newActiveComponent,
|
|
||||||
mediaWordPosStateIdx: eventState.wordPosStateIdx,
|
|
||||||
});
|
|
||||||
playAudio(audio.sound1);
|
|
||||||
break;
|
|
||||||
case "media_leftside_right":
|
|
||||||
updateLeftSide(
|
|
||||||
eventState.newActiveComponent,
|
|
||||||
eventState.lastActiveComponent
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "media_rightside_left":
|
|
||||||
updateRightSide(
|
|
||||||
eventState.newActiveComponent,
|
|
||||||
eventState.lastActiveComponent
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "media_play_select":
|
|
||||||
setNodeViewed(eventState.node.node_name, {
|
|
||||||
is_viewed: 1,
|
|
||||||
is_visible: 1,
|
|
||||||
});
|
|
||||||
playMedia();
|
|
||||||
break;
|
|
||||||
case "media_exit_select":
|
|
||||||
exitMedia();
|
|
||||||
playAudio(audio.sound29);
|
|
||||||
break;
|
|
||||||
case "media_word_select":
|
|
||||||
exitMedia();
|
|
||||||
playAudio(audio.sound29);
|
|
||||||
setState({
|
|
||||||
wordSelected: true,
|
|
||||||
activeLevel: eventState.level,
|
|
||||||
siteRot: [0, eventState.siteRotY, 0],
|
|
||||||
activeNode: eventState.node,
|
|
||||||
currentScene: "main",
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "word_node_not_found":
|
|
||||||
exitMedia();
|
|
||||||
playAudio(audio.sound30);
|
|
||||||
setState({
|
|
||||||
mainSubscene: "not_found",
|
|
||||||
currentScene: "main",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default handleMediaSceneEvent;
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { useStore } from "../../store";
|
|
||||||
|
|
||||||
const handleSsknSceneEvent = (eventState: any) => {
|
|
||||||
const setState = useStore.setState;
|
|
||||||
|
|
||||||
const setNodeViewed = useStore.getState().setNodeViewed;
|
|
||||||
|
|
||||||
switch (eventState.event) {
|
|
||||||
case "sskn_cancel_up":
|
|
||||||
setState({
|
|
||||||
activeSsknComponent: "ok",
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "sskn_ok_down":
|
|
||||||
setState({
|
|
||||||
activeSsknComponent: "cancel",
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "sskn_ok_select":
|
|
||||||
setState({
|
|
||||||
ssknLoading: true,
|
|
||||||
});
|
|
||||||
setNodeViewed(eventState.node.node_name, {
|
|
||||||
is_viewed: 1,
|
|
||||||
is_visible: 0,
|
|
||||||
});
|
|
||||||
// incrementSsknLvl();
|
|
||||||
|
|
||||||
setTimeout(() => setState({ currentScene: "main" }), 6000);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "sskn_cancel_select":
|
|
||||||
setState({
|
|
||||||
ssknLoading: false,
|
|
||||||
currentScene: "main",
|
|
||||||
activeSsknComponent: "ok",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default handleSsknSceneEvent;
|
|
|
@ -1,8 +1,25 @@
|
||||||
import authorize_user_letters from "../../resources/authorize_user_letters.json";
|
import authorize_user_letters from "../../resources/authorize_user_letters.json";
|
||||||
import handleNameSelection from "../../utils/handleNameSelection";
|
import handleNameSelection from "../../helpers/name-selection-helpers";
|
||||||
import { BootSceneContext } from "../../store";
|
import { BootSceneContext } from "../../store";
|
||||||
|
import {
|
||||||
|
changeMainMenuComponent,
|
||||||
|
changePromptComponent,
|
||||||
|
enterLoadData,
|
||||||
|
enterUserAuthorization,
|
||||||
|
exitLoadData,
|
||||||
|
exitUserAuthorization,
|
||||||
|
failUpdatePlayerName,
|
||||||
|
loadGame,
|
||||||
|
removePlayerNameLastChar,
|
||||||
|
startNewGame,
|
||||||
|
updateAuthorizeUserLetterIdx,
|
||||||
|
updatePlayerName,
|
||||||
|
} from "../eventTemplates";
|
||||||
|
import { GameEvent } from "../handleEvent";
|
||||||
|
|
||||||
const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
const handleBootSceneKeyPress = (
|
||||||
|
bootSceneContext: BootSceneContext
|
||||||
|
): GameEvent | undefined => {
|
||||||
const {
|
const {
|
||||||
keyPress,
|
keyPress,
|
||||||
subscene,
|
subscene,
|
||||||
|
@ -16,17 +33,15 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
if (promptVisible) {
|
if (promptVisible) {
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "LEFT":
|
case "LEFT":
|
||||||
return { event: "prompt_left" };
|
return changePromptComponent({ activePromptComponent: "yes" });
|
||||||
case "RIGHT":
|
case "RIGHT":
|
||||||
return { event: "prompt_right" };
|
return changePromptComponent({ activePromptComponent: "no" });
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
switch (activePromptComponent) {
|
switch (activePromptComponent) {
|
||||||
case "no":
|
case "no":
|
||||||
return { event: "load_data_no" };
|
return exitLoadData;
|
||||||
case "yes":
|
case "yes":
|
||||||
return {
|
return loadGame();
|
||||||
event: "load_data_yes",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,28 +50,34 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "UP":
|
case "UP":
|
||||||
case "DOWN":
|
case "DOWN":
|
||||||
return { event: `main_menu_${keyPress.toLowerCase()}` };
|
const newComponent =
|
||||||
|
keyPress === "UP" ? "authorize_user" : "load_data";
|
||||||
|
return changeMainMenuComponent({
|
||||||
|
activeMainMenuComponent: newComponent,
|
||||||
|
});
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
return { event: `main_menu_${activeMainMenuComponent}_select` };
|
switch (activeMainMenuComponent) {
|
||||||
|
case "authorize_user":
|
||||||
|
return enterUserAuthorization;
|
||||||
|
case "load_data":
|
||||||
|
return enterLoadData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "authorize_user":
|
case "authorize_user":
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "START":
|
case "START":
|
||||||
if (playerName.length > 0) {
|
if (playerName.length > 0) {
|
||||||
return {
|
return startNewGame;
|
||||||
event: "start_new_game",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
break;
|
return;
|
||||||
case "X":
|
case "X":
|
||||||
if (playerName.length > 0) {
|
if (playerName.length > 0) {
|
||||||
return {
|
return removePlayerNameLastChar({
|
||||||
event: "remove_last_char",
|
|
||||||
playerName: playerName.slice(0, -1),
|
playerName: playerName.slice(0, -1),
|
||||||
};
|
});
|
||||||
} else {
|
} else {
|
||||||
return { event: "authorize_user_back" };
|
return exitUserAuthorization;
|
||||||
}
|
}
|
||||||
case "LEFT":
|
case "LEFT":
|
||||||
// if utmost left, break
|
// if utmost left, break
|
||||||
|
@ -64,7 +85,7 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
[0, 13, 26, 39, 52].includes(authorizeUserLetterIdx) ||
|
[0, 13, 26, 39, 52].includes(authorizeUserLetterIdx) ||
|
||||||
authorizeUserLetterIdx === 15
|
authorizeUserLetterIdx === 15
|
||||||
)
|
)
|
||||||
break;
|
return;
|
||||||
// skip
|
// skip
|
||||||
else if (
|
else if (
|
||||||
authorizeUserLetterIdx === 41 ||
|
authorizeUserLetterIdx === 41 ||
|
||||||
|
@ -74,19 +95,17 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
authorizeUserLetterIdx === 19 ||
|
authorizeUserLetterIdx === 19 ||
|
||||||
authorizeUserLetterIdx === 45
|
authorizeUserLetterIdx === 45
|
||||||
) {
|
) {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_left",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 2,
|
authorizeUserLetterIdx: authorizeUserLetterIdx - 2,
|
||||||
};
|
});
|
||||||
} else {
|
} else {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_left",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 1,
|
authorizeUserLetterIdx: authorizeUserLetterIdx - 1,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
case "RIGHT":
|
case "RIGHT":
|
||||||
// if utmost right, break
|
// if utmost right, break
|
||||||
if ([12, 25, 38, 51, 64].includes(authorizeUserLetterIdx)) break;
|
if ([12, 25, 38, 51, 64].includes(authorizeUserLetterIdx)) return;
|
||||||
// skip empty
|
// skip empty
|
||||||
else if (
|
else if (
|
||||||
authorizeUserLetterIdx === 39 ||
|
authorizeUserLetterIdx === 39 ||
|
||||||
|
@ -96,15 +115,13 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
authorizeUserLetterIdx === 43 ||
|
authorizeUserLetterIdx === 43 ||
|
||||||
authorizeUserLetterIdx === 17
|
authorizeUserLetterIdx === 17
|
||||||
) {
|
) {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_right",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 2,
|
authorizeUserLetterIdx: authorizeUserLetterIdx + 2,
|
||||||
};
|
});
|
||||||
} else {
|
} else {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_right",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 1,
|
authorizeUserLetterIdx: authorizeUserLetterIdx + 1,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
case "DOWN":
|
case "DOWN":
|
||||||
// if utmost down, break
|
// if utmost down, break
|
||||||
|
@ -113,7 +130,7 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
authorizeUserLetterIdx
|
authorizeUserLetterIdx
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
break;
|
return;
|
||||||
// skip empty
|
// skip empty
|
||||||
} else if (
|
} else if (
|
||||||
authorizeUserLetterIdx === 0 ||
|
authorizeUserLetterIdx === 0 ||
|
||||||
|
@ -123,20 +140,17 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
authorizeUserLetterIdx === 31 ||
|
authorizeUserLetterIdx === 31 ||
|
||||||
authorizeUserLetterIdx === 5
|
authorizeUserLetterIdx === 5
|
||||||
) {
|
) {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_down",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 26,
|
authorizeUserLetterIdx: authorizeUserLetterIdx + 26,
|
||||||
};
|
});
|
||||||
} else if (authorizeUserLetterIdx === 3) {
|
} else if (authorizeUserLetterIdx === 3) {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_down",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 52,
|
authorizeUserLetterIdx: authorizeUserLetterIdx + 52,
|
||||||
};
|
});
|
||||||
} else {
|
} else {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_down",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 13,
|
authorizeUserLetterIdx: authorizeUserLetterIdx + 13,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
case "UP":
|
case "UP":
|
||||||
// if utmost up, break
|
// if utmost up, break
|
||||||
|
@ -145,7 +159,7 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
authorizeUserLetterIdx
|
authorizeUserLetterIdx
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
break;
|
return;
|
||||||
// skip empty
|
// skip empty
|
||||||
} else if (
|
} else if (
|
||||||
authorizeUserLetterIdx === 26 ||
|
authorizeUserLetterIdx === 26 ||
|
||||||
|
@ -154,20 +168,17 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
authorizeUserLetterIdx === 31 ||
|
authorizeUserLetterIdx === 31 ||
|
||||||
authorizeUserLetterIdx === 57
|
authorizeUserLetterIdx === 57
|
||||||
) {
|
) {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_up",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 26,
|
authorizeUserLetterIdx: authorizeUserLetterIdx - 26,
|
||||||
};
|
});
|
||||||
} else if (authorizeUserLetterIdx === 55) {
|
} else if (authorizeUserLetterIdx === 55) {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_up",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 52,
|
authorizeUserLetterIdx: authorizeUserLetterIdx - 52,
|
||||||
};
|
});
|
||||||
} else {
|
} else {
|
||||||
return {
|
return updateAuthorizeUserLetterIdx({
|
||||||
event: "authorize_user_up",
|
|
||||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 13,
|
authorizeUserLetterIdx: authorizeUserLetterIdx - 13,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
const chosenCharacter =
|
const chosenCharacter =
|
||||||
|
@ -178,10 +189,9 @@ const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||||
const newName = handleNameSelection(playerName, chosenCharacter);
|
const newName = handleNameSelection(playerName, chosenCharacter);
|
||||||
|
|
||||||
if (newName !== undefined)
|
if (newName !== undefined)
|
||||||
return { event: "update_player_name", playerName: newName };
|
return updatePlayerName({ playerName: newName });
|
||||||
else return { event: "update_player_name_denied" };
|
else return failUpdatePlayerName;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
import { EndSceneContext } from "../../store";
|
import { EndSceneContext } from "../../store";
|
||||||
|
import {
|
||||||
|
changeEndComponent,
|
||||||
|
continueGameAfterEnd,
|
||||||
|
endGame,
|
||||||
|
} from "../eventTemplates";
|
||||||
|
import { GameEvent } from "../handleEvent";
|
||||||
|
|
||||||
const handleEndSceneKeyPress = (endSceneContext: EndSceneContext) => {
|
const handleEndSceneKeyPress = (
|
||||||
|
endSceneContext: EndSceneContext
|
||||||
|
): GameEvent | undefined => {
|
||||||
const { keyPress, selectionVisible, activeEndComponent } = endSceneContext;
|
const { keyPress, selectionVisible, activeEndComponent } = endSceneContext;
|
||||||
|
|
||||||
if (selectionVisible) {
|
if (selectionVisible) {
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "UP":
|
case "UP":
|
||||||
case "DOWN":
|
case "DOWN":
|
||||||
return { event: `end_selection_${keyPress.toLowerCase()}` };
|
const newComponent = keyPress === "UP" ? "end" : "continue";
|
||||||
|
return changeEndComponent({ activeEndComponent: newComponent });
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
return { event: `end_${activeEndComponent}_select` };
|
switch (activeEndComponent) {
|
||||||
|
case "end":
|
||||||
|
return endGame;
|
||||||
|
case "continue":
|
||||||
|
return continueGameAfterEnd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {
|
||||||
getNodeById,
|
getNodeById,
|
||||||
isNodeVisible,
|
isNodeVisible,
|
||||||
unknownNodeTemplate,
|
unknownNodeTemplate,
|
||||||
} from "../../utils/node-utils";
|
} from "../../helpers/node-helpers";
|
||||||
import { MainSceneContext } from "../../store";
|
import { MainSceneContext } from "../../store";
|
||||||
import {
|
import {
|
||||||
changeNode,
|
changeNode,
|
||||||
|
@ -18,19 +18,25 @@ import {
|
||||||
exitPause,
|
exitPause,
|
||||||
exitPrompt,
|
exitPrompt,
|
||||||
explodeNode,
|
explodeNode,
|
||||||
|
hideWordNotFound,
|
||||||
knockNode,
|
knockNode,
|
||||||
knockNodeAndFall,
|
knockNodeAndFall,
|
||||||
loadGame,
|
loadGame,
|
||||||
pauseGame,
|
pauseGame,
|
||||||
|
ripNode,
|
||||||
saveGame,
|
saveGame,
|
||||||
selectLevel,
|
selectLevel,
|
||||||
showAbout,
|
showAbout,
|
||||||
showPermissionDenied,
|
showPermissionDenied,
|
||||||
siteMoveHorizontal,
|
siteMoveHorizontal,
|
||||||
siteMoveVertical,
|
siteMoveVertical,
|
||||||
|
throwNode,
|
||||||
} from "../eventTemplates";
|
} from "../eventTemplates";
|
||||||
|
import { GameEvent } from "../handleEvent";
|
||||||
|
|
||||||
const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
const handleMainSceneKeyPress = (
|
||||||
|
mainSceneContext: MainSceneContext
|
||||||
|
): GameEvent | undefined => {
|
||||||
const {
|
const {
|
||||||
subscene,
|
subscene,
|
||||||
selectedLevel,
|
selectedLevel,
|
||||||
|
@ -47,6 +53,7 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
activePromptComponent,
|
activePromptComponent,
|
||||||
gateLvl,
|
gateLvl,
|
||||||
siteSaveState,
|
siteSaveState,
|
||||||
|
wordNotFound,
|
||||||
} = mainSceneContext;
|
} = mainSceneContext;
|
||||||
|
|
||||||
if (promptVisible) {
|
if (promptVisible) {
|
||||||
|
@ -73,8 +80,6 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
activeLevel: level.toString().padStart(2, "0"),
|
activeLevel: level.toString().padStart(2, "0"),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
console.log(newSiteSaveState);
|
|
||||||
|
|
||||||
return changeSite({
|
return changeSite({
|
||||||
newActiveSite: siteToLoad,
|
newActiveSite: siteToLoad,
|
||||||
newActiveNode: stateToLoad.activeNode,
|
newActiveNode: stateToLoad.activeNode,
|
||||||
|
@ -92,6 +97,7 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
} else {
|
} else {
|
||||||
switch (subscene) {
|
switch (subscene) {
|
||||||
case "site":
|
case "site":
|
||||||
|
if (wordNotFound) return hideWordNotFound;
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "LEFT":
|
case "LEFT":
|
||||||
case "RIGHT": {
|
case "RIGHT": {
|
||||||
|
@ -169,8 +175,7 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
else return changeNode({ activeNode: newNode });
|
else return changeNode({ activeNode: newNode });
|
||||||
}
|
}
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
const eventAnimation =
|
const eventAnimation = Math.random() < 0.4 ? throwNode : ripNode;
|
||||||
Math.random() < 0.4 ? "rip_node" : "throw_node";
|
|
||||||
|
|
||||||
const nodeType = activeNode.type;
|
const nodeType = activeNode.type;
|
||||||
|
|
||||||
|
@ -181,7 +186,7 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (activeNode.upgrade_requirement > ssknLvl) {
|
if (activeNode.upgrade_requirement > ssknLvl) {
|
||||||
const rejectEvents = [explodeNode, knockNode, knockNodeAndFall];
|
const rejectEvents = [knockNodeAndFall, knockNode, explodeNode];
|
||||||
return rejectEvents[Math.floor(Math.random() * 3)];
|
return rejectEvents[Math.floor(Math.random() * 3)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,37 +196,19 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
case 4:
|
case 4:
|
||||||
case 3:
|
case 3:
|
||||||
case 5:
|
case 5:
|
||||||
return {
|
return eventAnimation({ currentScene: "media" });
|
||||||
event: `${eventAnimation}_media`,
|
|
||||||
mutations: { scene: "media" },
|
|
||||||
};
|
|
||||||
case 6:
|
case 6:
|
||||||
if (activeNode.node_name.substr(0, 3) === "TaK") {
|
if (activeNode.node_name.substr(0, 3) === "TaK") {
|
||||||
return {
|
return eventAnimation({ currentScene: "tak" });
|
||||||
event: `${eventAnimation}_tak`,
|
|
||||||
mutations: { scene: "tak" },
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return {
|
return eventAnimation({ currentScene: "media" });
|
||||||
event: `${eventAnimation}_media`,
|
|
||||||
mutations: { scene: "media" },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
case 8:
|
case 8:
|
||||||
return {
|
return eventAnimation({ currentScene: "gate" });
|
||||||
event: `${eventAnimation}_gate`,
|
|
||||||
mutations: { scene: "gate" },
|
|
||||||
};
|
|
||||||
case 7:
|
case 7:
|
||||||
return {
|
return eventAnimation({ currentScene: "gate" });
|
||||||
event: `${eventAnimation}_sskn`,
|
|
||||||
mutations: { scene: "sskn" },
|
|
||||||
};
|
|
||||||
case 9:
|
case 9:
|
||||||
return {
|
return eventAnimation({ currentScene: "polytan" });
|
||||||
event: `${eventAnimation}_polytan`,
|
|
||||||
mutations: { scene: "polytan" },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "L2":
|
case "L2":
|
||||||
|
@ -284,13 +271,12 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "UP":
|
case "UP":
|
||||||
case "DOWN":
|
case "DOWN":
|
||||||
const direction = keyPress.toLowerCase();
|
|
||||||
const components = ["load", "about", "change", "save", "exit"];
|
const components = ["load", "about", "change", "save", "exit"];
|
||||||
|
|
||||||
const newComponent =
|
const newComponent =
|
||||||
components[
|
components[
|
||||||
components.indexOf(activePauseComponent) +
|
components.indexOf(activePauseComponent) +
|
||||||
(direction === "up" ? -1 : 1)
|
(keyPress === "UP" ? -1 : 1)
|
||||||
];
|
];
|
||||||
|
|
||||||
if (newComponent)
|
if (newComponent)
|
||||||
|
|
|
@ -1,8 +1,19 @@
|
||||||
import { findNodeFromWord } from "../../utils/media-utils";
|
import { findNodeFromWord } from "../../helpers/media-helpers";
|
||||||
import { MediaSceneContext } from "../../store";
|
import { MediaSceneContext } from "../../store";
|
||||||
import { changeLeftMediaComponent, changeMediaSide } from "../eventTemplates";
|
import {
|
||||||
|
changeLeftMediaComponent,
|
||||||
|
changeMediaSide,
|
||||||
|
changeRightMediaComponent,
|
||||||
|
exitMedia,
|
||||||
|
playMedia,
|
||||||
|
selectWord,
|
||||||
|
wordNotFound,
|
||||||
|
} from "../eventTemplates";
|
||||||
|
import { GameEvent } from "../handleEvent";
|
||||||
|
|
||||||
const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
const handleMediaSceneKeyPress = (
|
||||||
|
mediaSceneContext: MediaSceneContext
|
||||||
|
): GameEvent | undefined => {
|
||||||
const {
|
const {
|
||||||
keyPress,
|
keyPress,
|
||||||
activeMediaComponent,
|
activeMediaComponent,
|
||||||
|
@ -19,8 +30,8 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "UP":
|
case "UP":
|
||||||
case "DOWN": {
|
case "DOWN": {
|
||||||
const direction = keyPress.toLowerCase();
|
const newComponent = keyPress === "UP" ? "play" : "exit";
|
||||||
const newComponent = direction === "up" ? "play" : "exit";
|
|
||||||
return changeLeftMediaComponent({ activeComponent: newComponent });
|
return changeLeftMediaComponent({ activeComponent: newComponent });
|
||||||
}
|
}
|
||||||
case "RIGHT": {
|
case "RIGHT": {
|
||||||
|
@ -36,14 +47,9 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
switch (activeMediaComponent) {
|
switch (activeMediaComponent) {
|
||||||
case "play":
|
case "play":
|
||||||
return {
|
return playMedia;
|
||||||
event: "media_play_select",
|
|
||||||
node: activeNode,
|
|
||||||
};
|
|
||||||
case "exit":
|
case "exit":
|
||||||
return {
|
return exitMedia;
|
||||||
event: "media_play_select",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -54,6 +60,7 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||||
wordPosStateIdx - 1 < 1 ? 6 : wordPosStateIdx - 1;
|
wordPosStateIdx - 1 < 1 ? 6 : wordPosStateIdx - 1;
|
||||||
const newComponent = (() => {
|
const newComponent = (() => {
|
||||||
switch (activeMediaComponent) {
|
switch (activeMediaComponent) {
|
||||||
|
default:
|
||||||
case "fstWord":
|
case "fstWord":
|
||||||
return "thirdWord";
|
return "thirdWord";
|
||||||
case "sndWord":
|
case "sndWord":
|
||||||
|
@ -62,17 +69,17 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||||
return "sndWord";
|
return "sndWord";
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
return {
|
return changeRightMediaComponent({
|
||||||
event: "media_rightside_up",
|
activeComponent: newComponent,
|
||||||
newActiveComponent: newComponent,
|
|
||||||
wordPosStateIdx: newWordPosStateIdx,
|
wordPosStateIdx: newWordPosStateIdx,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
case "DOWN": {
|
case "DOWN": {
|
||||||
const newWordPosStateIdx =
|
const newWordPosStateIdx =
|
||||||
wordPosStateIdx + 1 > 6 ? 1 : wordPosStateIdx + 1;
|
wordPosStateIdx + 1 > 6 ? 1 : wordPosStateIdx + 1;
|
||||||
const newComponent = (() => {
|
const newComponent = (() => {
|
||||||
switch (activeMediaComponent) {
|
switch (activeMediaComponent) {
|
||||||
|
default:
|
||||||
case "fstWord":
|
case "fstWord":
|
||||||
return "sndWord";
|
return "sndWord";
|
||||||
case "sndWord":
|
case "sndWord":
|
||||||
|
@ -82,11 +89,10 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return {
|
return changeRightMediaComponent({
|
||||||
event: "media_rightside_down",
|
activeComponent: newComponent,
|
||||||
newActiveComponent: newComponent,
|
|
||||||
wordPosStateIdx: newWordPosStateIdx,
|
wordPosStateIdx: newWordPosStateIdx,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
case "LEFT":
|
case "LEFT":
|
||||||
|
@ -111,9 +117,14 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
return { event: `media_word_select`, ...data };
|
const { node, level, siteRotY } = { ...data };
|
||||||
|
return selectWord({
|
||||||
|
activeNode: node,
|
||||||
|
activeLevel: level,
|
||||||
|
siteRot: [0, siteRotY, 0],
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return { event: `word_node_not_found` };
|
return wordNotFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,42 @@
|
||||||
import { SsknSceneContext } from "../../store";
|
import { SsknSceneContext } from "../../store";
|
||||||
|
import { changeSsknComponent, exitSskn, upgradeSskn } from "../eventTemplates";
|
||||||
|
import { GameEvent } from "../handleEvent";
|
||||||
|
|
||||||
const handleSsknSceneKeyPress = (ssknSceneContext: SsknSceneContext) => {
|
const handleSsknSceneKeyPress = (
|
||||||
const { keyPress, activeSsknComponent, activeNode } = ssknSceneContext;
|
ssknSceneContext: SsknSceneContext
|
||||||
|
): GameEvent | undefined => {
|
||||||
|
const {
|
||||||
|
keyPress,
|
||||||
|
activeSsknComponent,
|
||||||
|
activeNode,
|
||||||
|
gameProgress,
|
||||||
|
ssknLvl,
|
||||||
|
} = ssknSceneContext;
|
||||||
|
|
||||||
switch (keyPress) {
|
switch (keyPress) {
|
||||||
case "UP":
|
case "UP":
|
||||||
case "DOWN":
|
case "DOWN":
|
||||||
return {
|
const direction = keyPress.toLowerCase();
|
||||||
event: `sskn_${activeSsknComponent}_${keyPress.toLowerCase()}`,
|
const newComponent = direction === "up" ? "ok" : "cancel";
|
||||||
};
|
return changeSsknComponent({ activeSsknComponent: newComponent });
|
||||||
case "CIRCLE":
|
case "CIRCLE":
|
||||||
if (activeSsknComponent === "ok") {
|
switch (activeSsknComponent) {
|
||||||
return {
|
case "ok":
|
||||||
event: `sskn_ok_select`,
|
const newGameProgress = {
|
||||||
node: activeNode,
|
...gameProgress,
|
||||||
};
|
[activeNode.node_name]: {
|
||||||
} else {
|
is_viewed: 1,
|
||||||
return {
|
is_visible: 0,
|
||||||
event: `sskn_cancel_select`,
|
},
|
||||||
};
|
};
|
||||||
|
const newSsknLvl = ssknLvl + 1;
|
||||||
|
|
||||||
|
return upgradeSskn({
|
||||||
|
gameProgress: newGameProgress,
|
||||||
|
ssknLvl: newSsknLvl,
|
||||||
|
});
|
||||||
|
case "cancel":
|
||||||
|
return exitSskn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,12 +2,13 @@ import site_a from "../resources/site_a.json";
|
||||||
import site_b from "../resources/site_b.json";
|
import site_b from "../resources/site_b.json";
|
||||||
import node_matrices from "../resources/node_matrices.json";
|
import node_matrices from "../resources/node_matrices.json";
|
||||||
import { NodeData, SiteData } from "../components/MainScene/Site/Site";
|
import { NodeData, SiteData } from "../components/MainScene/Site/Site";
|
||||||
import { isNodeVisible } from "./node-utils";
|
import { isNodeVisible } from "./node-helpers";
|
||||||
|
import { ActiveSite, RightMediaComponent } from "../store";
|
||||||
|
|
||||||
export const findNodeFromWord = (
|
export const findNodeFromWord = (
|
||||||
wordLabel: string,
|
wordLabel: RightMediaComponent,
|
||||||
activeNode: NodeData,
|
activeNode: NodeData,
|
||||||
site: "a" | "b",
|
site: ActiveSite,
|
||||||
gameProgress: any
|
gameProgress: any
|
||||||
) => {
|
) => {
|
||||||
const labelToIdx = (() => {
|
const labelToIdx = (() => {
|
||||||
|
@ -73,3 +74,18 @@ export const findNodeFromWord = (
|
||||||
level: chosenNode.id.substr(0, 2),
|
level: chosenNode.id.substr(0, 2),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const playMediaElement = () => {
|
||||||
|
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
||||||
|
|
||||||
|
if (mediaElement && mediaElement.paused) mediaElement.play();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resetMediaElement = () => {
|
||||||
|
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
||||||
|
if (mediaElement) {
|
||||||
|
mediaElement.pause();
|
||||||
|
|
||||||
|
mediaElement.currentTime = 0;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,9 +1,5 @@
|
||||||
import { useStore } from "../store";
|
import { useStore } from "../store";
|
||||||
import sleep from "./sleep";
|
import sleep from "../utils/sleep";
|
||||||
|
|
||||||
const setActiveNodePos = useStore.getState().setNodePos;
|
|
||||||
const setActiveNodeRot = useStore.getState().setNodeRot;
|
|
||||||
const setActiveNodeAttributes = useStore.getState().setNodeAttributes;
|
|
||||||
|
|
||||||
const calculateCoordsBasedOnRotation = (
|
const calculateCoordsBasedOnRotation = (
|
||||||
x: number,
|
x: number,
|
||||||
|
@ -18,6 +14,10 @@ const calculateCoordsBasedOnRotation = (
|
||||||
// throw a warning about an unhandled promise, and we dont care about that.
|
// throw a warning about an unhandled promise, and we dont care about that.
|
||||||
// async/awaits here are used simply to improve readability, nothing else.
|
// async/awaits here are used simply to improve readability, nothing else.
|
||||||
|
|
||||||
|
const setActiveNodePos = useStore.getState().setNodePos;
|
||||||
|
const setActiveNodeRot = useStore.getState().setNodeRot;
|
||||||
|
const setActiveNodeAttributes = useStore.getState().setNodeAttributes;
|
||||||
|
|
||||||
export const nodeThrowAnimation = () => {
|
export const nodeThrowAnimation = () => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const siteRotY = useStore.getState().siteRot[1];
|
const siteRotY = useStore.getState().siteRot[1];
|
|
@ -1,10 +1,10 @@
|
||||||
import { NodeData, SiteData } from "../components/MainScene/Site/Site";
|
import { NodeData, SiteData } from "../components/MainScene/Site/Site";
|
||||||
import node_matrices from "../resources/node_matrices.json";
|
|
||||||
import unlocked_nodes from "../resources/initial_progress.json";
|
|
||||||
import node_huds from "../resources/node_huds.json";
|
|
||||||
import site_a from "../resources/site_a.json";
|
import site_a from "../resources/site_a.json";
|
||||||
import site_b from "../resources/site_b.json";
|
import site_b from "../resources/site_b.json";
|
||||||
import {GameProgress} from "../store";
|
import node_huds from "../resources/node_huds.json";
|
||||||
|
import unlocked_nodes from "../resources/initial_progress.json";
|
||||||
|
import node_matrices from "../resources/node_matrices.json";
|
||||||
|
import { GameProgress } from "../store";
|
||||||
|
|
||||||
export const generateInactiveNodes = (
|
export const generateInactiveNodes = (
|
||||||
visibleNodes: SiteData,
|
visibleNodes: SiteData,
|
|
@ -15,7 +15,6 @@ import sleep from "../utils/sleep";
|
||||||
const EndScene = () => {
|
const EndScene = () => {
|
||||||
const mainCylinderRef = useRef<THREE.Object3D>();
|
const mainCylinderRef = useRef<THREE.Object3D>();
|
||||||
|
|
||||||
const setAudioAnalyser = useStore((state) => state.setAudioAnalyser);
|
|
||||||
const setSelectionVisible = useStore(
|
const setSelectionVisible = useStore(
|
||||||
(state) => state.setEndSceneSelectionVisible
|
(state) => state.setEndSceneSelectionVisible
|
||||||
);
|
);
|
||||||
|
@ -110,7 +109,7 @@ const EndScene = () => {
|
||||||
mediaElement.load();
|
mediaElement.load();
|
||||||
mediaElement.play();
|
mediaElement.play();
|
||||||
}
|
}
|
||||||
}, [setAudioAnalyser]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -128,9 +127,7 @@ const EndScene = () => {
|
||||||
<EndSphere position={[2, 1.7, -0.5]} outroAnim={sceneOutro} />
|
<EndSphere position={[2, 1.7, -0.5]} outroAnim={sceneOutro} />
|
||||||
<LainSpeak intro={isIntro} outro={isOutro} />
|
<LainSpeak intro={isIntro} outro={isOutro} />
|
||||||
</group>
|
</group>
|
||||||
<group visible={showSelectionScreen}>
|
<EndSelectionScreen visible={showSelectionScreen} />
|
||||||
<EndSelectionScreen />
|
|
||||||
</group>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,18 +7,20 @@ import { useStore } from "../store";
|
||||||
|
|
||||||
const GateScene = () => {
|
const GateScene = () => {
|
||||||
const gateLvl = useStore((state) => state.gateLvl);
|
const gateLvl = useStore((state) => state.gateLvl);
|
||||||
|
const incrementGateLvl = useStore((state) => state.incrementGateLvl);
|
||||||
const [introAnim, setIntroAnim] = useState(true);
|
const [introAnim, setIntroAnim] = useState(true);
|
||||||
|
|
||||||
const activeNodeName = useStore((state) => state.activeNode.node_name);
|
const activeNodeName = useStore((state) => state.activeNode.node_name);
|
||||||
const setNodeViewed = useStore((state) => state.setNodeViewed);
|
const setNodeViewed = useStore((state) => state.setNodeViewed);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
incrementGateLvl();
|
||||||
setNodeViewed(activeNodeName, {
|
setNodeViewed(activeNodeName, {
|
||||||
is_viewed: 1,
|
is_viewed: 1,
|
||||||
is_visible: 0,
|
is_visible: 0,
|
||||||
});
|
});
|
||||||
setTimeout(() => setIntroAnim(false), 2500);
|
setTimeout(() => setIntroAnim(false), 2500);
|
||||||
}, [activeNodeName, setNodeViewed]);
|
}, [activeNodeName, incrementGateLvl, setNodeViewed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<perspectiveCamera position-z={3}>
|
<perspectiveCamera position-z={3}>
|
||||||
|
|
|
@ -14,7 +14,7 @@ import Lain from "../components/MainScene/Lain";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useFrame } from "react-three-fiber";
|
import { useFrame } from "react-three-fiber";
|
||||||
import Popups from "../components/MainScene/Popups/Popups";
|
import Popups from "../components/MainScene/Popups/Popups";
|
||||||
import * as audio from "../static/sfx";
|
import * as audio from "../static/audio/sfx";
|
||||||
import Loading from "../components/Loading";
|
import Loading from "../components/Loading";
|
||||||
import usePrevious from "../hooks/usePrevious";
|
import usePrevious from "../hooks/usePrevious";
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ const MainScene = () => {
|
||||||
|
|
||||||
const wordSelected = useStore((state) => state.wordSelected);
|
const wordSelected = useStore((state) => state.wordSelected);
|
||||||
const setWordSelected = useStore((state) => state.setWordSelected);
|
const setWordSelected = useStore((state) => state.setWordSelected);
|
||||||
|
const setInputCooldown = useStore((state) => state.setInputCooldown);
|
||||||
|
const wordNotFound = useStore((state) => state.wordNotFound);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (subscene === "pause") {
|
if (subscene === "pause") {
|
||||||
|
@ -78,13 +80,27 @@ const MainScene = () => {
|
||||||
introWrapperRef.current.rotation.x -= 0.008;
|
introWrapperRef.current.rotation.x -= 0.008;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// introWrapperRef.current.position.z = THREE.MathUtils.lerp(
|
||||||
|
// introWrapperRef.current.position.z,
|
||||||
|
// intro ? 0 : -10,
|
||||||
|
// 0.01
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// introWrapperRef.current.rotation.x = THREE.MathUtils.lerp(
|
||||||
|
// introWrapperRef.current.rotation.x,
|
||||||
|
// intro ? 0 : Math.PI / 2,
|
||||||
|
// 0.01
|
||||||
|
// );
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
!introFinished &&
|
||||||
!(
|
!(
|
||||||
introWrapperRef.current.rotation.x > 0 &&
|
introWrapperRef.current.rotation.x > 0 &&
|
||||||
introWrapperRef.current.position.z < 0
|
introWrapperRef.current.position.z < 0
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
setIntroFinished(true);
|
setIntroFinished(true);
|
||||||
|
setInputCooldown(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -97,7 +113,7 @@ const MainScene = () => {
|
||||||
<Pause />
|
<Pause />
|
||||||
<group visible={!paused}>
|
<group visible={!paused}>
|
||||||
<group visible={!wordSelected && (intro ? introFinished : true)}>
|
<group visible={!wordSelected && (intro ? introFinished : true)}>
|
||||||
<group visible={subscene !== "not_found"}>
|
<group visible={!wordNotFound}>
|
||||||
<HUD />
|
<HUD />
|
||||||
<MainYellowTextAnimator />
|
<MainYellowTextAnimator />
|
||||||
</group>
|
</group>
|
||||||
|
|
|
@ -71,7 +71,7 @@ const MediaScene = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoaded(true);
|
setLoaded(true);
|
||||||
setTimeout(() => setInputCooldown(false), 1000);
|
setTimeout(() => setInputCooldown(500), 1000);
|
||||||
}, [setInputCooldown]);
|
}, [setInputCooldown]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -4,7 +4,6 @@ import PolytanBackground from "../components/PolytanScene/PolytanBackground";
|
||||||
import { useStore } from "../store";
|
import { useStore } from "../store";
|
||||||
|
|
||||||
const PolytanScene = () => {
|
const PolytanScene = () => {
|
||||||
const unlockedParts = useStore((state) => state.polytanUnlockedParts);
|
|
||||||
const setNodeViewed = useStore((state) => state.setNodeViewed);
|
const setNodeViewed = useStore((state) => state.setNodeViewed);
|
||||||
const setPolytanPartUnlocked = useStore.getState().setPolytanPartUnlocked;
|
const setPolytanPartUnlocked = useStore.getState().setPolytanPartUnlocked;
|
||||||
const activeNodeName = useStore((state) => state.activeNode.node_name);
|
const activeNodeName = useStore((state) => state.activeNode.node_name);
|
||||||
|
@ -34,10 +33,10 @@ const PolytanScene = () => {
|
||||||
}, [activeNodeName, setNodeViewed, setPolytanPartUnlocked]);
|
}, [activeNodeName, setNodeViewed, setPolytanPartUnlocked]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<perspectiveCamera>
|
<>
|
||||||
<PolytanBear unlockedParts={unlockedParts} />
|
<PolytanBear />
|
||||||
<PolytanBackground />
|
<PolytanBackground />
|
||||||
</perspectiveCamera>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
315
src/store.ts
315
src/store.ts
|
@ -3,35 +3,103 @@ import { combine } from "zustand/middleware";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import game_progress from "./resources/initial_progress.json";
|
import game_progress from "./resources/initial_progress.json";
|
||||||
import { NodeData } from "./components/MainScene/Site/Site";
|
import { NodeData } from "./components/MainScene/Site/Site";
|
||||||
import { getNodeById } from "./utils/node-utils";
|
import { getNodeById } from "./helpers/node-helpers";
|
||||||
import site_a from "./resources/site_a.json";
|
import site_a from "./resources/site_a.json";
|
||||||
|
import { AudioAnalyser } from "three";
|
||||||
|
import MainScene from "./scenes/MainScene";
|
||||||
|
import MediaScene from "./scenes/MediaScene";
|
||||||
|
import IdleMediaScene from "./scenes/IdleMediaScene";
|
||||||
|
import GateScene from "./scenes/GateScene";
|
||||||
|
import BootScene from "./scenes/BootScene";
|
||||||
|
import SsknScene from "./scenes/SsknScene";
|
||||||
|
import PolytanScene from "./scenes/PolytanScene";
|
||||||
|
import TaKScene from "./scenes/TaKScene";
|
||||||
|
import ChangeDiscScene from "./scenes/ChangeDiscScene";
|
||||||
|
import EndScene from "./scenes/EndScene";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
export type GameProgress = typeof game_progress;
|
export type GameProgress = typeof game_progress;
|
||||||
|
|
||||||
|
type NodeAttributes = {
|
||||||
|
interactedWith: boolean;
|
||||||
|
exploding: boolean;
|
||||||
|
shrinking: boolean;
|
||||||
|
visible: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GameScene =
|
||||||
|
| "main"
|
||||||
|
| "media"
|
||||||
|
| "tak"
|
||||||
|
| "sskn"
|
||||||
|
| "polytan"
|
||||||
|
| "idle_media"
|
||||||
|
| "gate"
|
||||||
|
| "boot"
|
||||||
|
| "change_disc"
|
||||||
|
| "end";
|
||||||
|
|
||||||
|
type MainSubscene = "site" | "pause" | "level_selection";
|
||||||
|
|
||||||
|
export type ActiveSite = "a" | "b";
|
||||||
|
|
||||||
|
export type EndComponent = "end" | "continue";
|
||||||
|
|
||||||
|
export type PauseComponent = "load" | "about" | "change" | "save" | "exit";
|
||||||
|
|
||||||
|
export type MediaSide = "left" | "right";
|
||||||
|
export type LeftMediaComponent = "play" | "exit";
|
||||||
|
export type RightMediaComponent = "fstWord" | "sndWord" | "thirdWord";
|
||||||
|
export type MediaComponent = LeftMediaComponent | RightMediaComponent;
|
||||||
|
|
||||||
|
export type SiteSaveState = {
|
||||||
|
a: {
|
||||||
|
activeNode: NodeData;
|
||||||
|
siteRot: number[];
|
||||||
|
activeLevel: string;
|
||||||
|
};
|
||||||
|
b: {
|
||||||
|
activeNode: NodeData;
|
||||||
|
siteRot: number[];
|
||||||
|
activeLevel: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SsknComponent = "ok" | "cancel";
|
||||||
|
|
||||||
|
export type MainMenuComponent = "authorize_user" | "load_data";
|
||||||
|
export type BootSubscene = "main_menu" | "load_data" | "authorize_user";
|
||||||
|
|
||||||
|
export type PromptComponent = "yes" | "no";
|
||||||
|
|
||||||
|
type PolytanBodyParts = {
|
||||||
|
body: boolean;
|
||||||
|
head: boolean;
|
||||||
|
leftArm: boolean;
|
||||||
|
rightArm: boolean;
|
||||||
|
leftLeg: boolean;
|
||||||
|
rightLeg: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
currentScene: string;
|
currentScene: GameScene;
|
||||||
|
|
||||||
gameProgress: GameProgress;
|
gameProgress: GameProgress;
|
||||||
|
|
||||||
mainSubscene: string;
|
mainSubscene: MainSubscene;
|
||||||
|
|
||||||
intro: boolean;
|
intro: boolean;
|
||||||
|
|
||||||
activeNode: NodeData;
|
activeNode: NodeData;
|
||||||
activeNodePos: number[];
|
activeNodePos: number[];
|
||||||
activeNodeRot: number[];
|
activeNodeRot: number[];
|
||||||
activeNodeAttributes: {
|
activeNodeAttributes: NodeAttributes;
|
||||||
interactedWith: boolean;
|
|
||||||
exploding: boolean;
|
|
||||||
shrinking: boolean;
|
|
||||||
visible: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
// lain
|
// lain
|
||||||
lainMoveState: string;
|
lainMoveState: string;
|
||||||
|
|
||||||
// site
|
// site
|
||||||
activeSite: "a" | "b";
|
activeSite: ActiveSite;
|
||||||
siteRot: number[];
|
siteRot: number[];
|
||||||
oldSiteRot: number[];
|
oldSiteRot: number[];
|
||||||
|
|
||||||
|
@ -43,23 +111,23 @@ type State = {
|
||||||
selectedLevel: number;
|
selectedLevel: number;
|
||||||
|
|
||||||
// end scene
|
// end scene
|
||||||
activeEndComponent: "end" | "continue";
|
activeEndComponent: EndComponent;
|
||||||
endSceneSelectionVisible: boolean;
|
endSceneSelectionVisible: boolean;
|
||||||
|
|
||||||
// pause
|
// pause
|
||||||
activePauseComponent: "load" | "about" | "change" | "save" | "exit";
|
activePauseComponent: PauseComponent;
|
||||||
pauseExitAnimation: boolean;
|
pauseExitAnimation: boolean;
|
||||||
showingAbout: boolean;
|
showingAbout: boolean;
|
||||||
permissionDenied: boolean;
|
permissionDenied: boolean;
|
||||||
|
|
||||||
// media/media scene
|
// media/media scene
|
||||||
audioAnalyser: any;
|
audioAnalyser: AudioAnalyser | undefined;
|
||||||
mediaPercentageElapsed: number;
|
mediaPercentageElapsed: number;
|
||||||
currentMediaSide: "left" | "right";
|
currentMediaSide: MediaSide;
|
||||||
activeMediaComponent: "play" | "exit" | "fstWord" | "sndWord" | "thirdWord";
|
activeMediaComponent: MediaComponent;
|
||||||
lastActiveMediaComponents: {
|
lastActiveMediaComponents: {
|
||||||
left: "play" | "exit";
|
left: LeftMediaComponent;
|
||||||
right: "fstWord" | "sndWord" | "thirdWord";
|
right: RightMediaComponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
mediaWordPosStateIdx: number;
|
mediaWordPosStateIdx: number;
|
||||||
|
@ -72,19 +140,12 @@ type State = {
|
||||||
idleNodeName: string | undefined;
|
idleNodeName: string | undefined;
|
||||||
|
|
||||||
// sskn scene
|
// sskn scene
|
||||||
activeSsknComponent: "ok" | "cancel";
|
activeSsknComponent: SsknComponent;
|
||||||
ssknLoading: boolean;
|
ssknLoading: boolean;
|
||||||
ssknLvl: number;
|
ssknLvl: number;
|
||||||
|
|
||||||
// polytan scene
|
// polytan scene
|
||||||
polytanUnlockedParts: {
|
polytanUnlockedParts: PolytanBodyParts;
|
||||||
body: boolean;
|
|
||||||
head: boolean;
|
|
||||||
leftArm: boolean;
|
|
||||||
rightArm: boolean;
|
|
||||||
leftLeg: boolean;
|
|
||||||
rightLeg: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
// gate scene
|
// gate scene
|
||||||
gateLvl: number;
|
gateLvl: number;
|
||||||
|
@ -93,40 +154,32 @@ type State = {
|
||||||
playerName: string;
|
playerName: string;
|
||||||
|
|
||||||
// boot scene
|
// boot scene
|
||||||
activeMainMenuComponent: "authorize_user" | "load_data";
|
activeMainMenuComponent: MainMenuComponent;
|
||||||
authorizeUserLetterIdx: number;
|
authorizeUserLetterIdx: number;
|
||||||
bootSubscene: "main_menu" | "load_data" | "authorize_user";
|
bootSubscene: BootSubscene;
|
||||||
|
|
||||||
// prompt
|
// prompt
|
||||||
promptVisible: boolean;
|
promptVisible: boolean;
|
||||||
activePromptComponent: "yes" | "no";
|
activePromptComponent: PromptComponent;
|
||||||
|
|
||||||
// status notifiers
|
// status notifiers
|
||||||
loadSuccessful: boolean | undefined;
|
loadSuccessful: boolean | undefined;
|
||||||
saveSuccessful: boolean | undefined;
|
saveSuccessful: boolean | undefined;
|
||||||
|
|
||||||
// save state
|
// word not found notification thing
|
||||||
siteSaveState: {
|
wordNotFound: boolean;
|
||||||
a: {
|
|
||||||
activeNode: NodeData;
|
|
||||||
siteRot: number[];
|
|
||||||
activeLevel: string;
|
|
||||||
};
|
|
||||||
b: {
|
|
||||||
activeNode: NodeData;
|
|
||||||
siteRot: number[];
|
|
||||||
activeLevel: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
inputCooldown: boolean;
|
// save state
|
||||||
|
siteSaveState: SiteSaveState;
|
||||||
|
|
||||||
|
inputCooldown: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useStore = create(
|
export const useStore = create(
|
||||||
combine(
|
combine(
|
||||||
{
|
{
|
||||||
// scene data
|
// scene data
|
||||||
currentScene: "media",
|
currentScene: "main",
|
||||||
|
|
||||||
// game progress
|
// game progress
|
||||||
gameProgress: game_progress,
|
gameProgress: game_progress,
|
||||||
|
@ -232,6 +285,9 @@ export const useStore = create(
|
||||||
loadSuccessful: undefined,
|
loadSuccessful: undefined,
|
||||||
saveSuccessful: undefined,
|
saveSuccessful: undefined,
|
||||||
|
|
||||||
|
// word not found notification thing
|
||||||
|
wordNotFound: false,
|
||||||
|
|
||||||
// save states for loading the game/changing sites
|
// save states for loading the game/changing sites
|
||||||
siteSaveState: {
|
siteSaveState: {
|
||||||
a: {
|
a: {
|
||||||
|
@ -252,13 +308,11 @@ export const useStore = create(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
inputCooldown: false,
|
inputCooldown: -1,
|
||||||
} as State,
|
} as State,
|
||||||
(set) => ({
|
(set) => ({
|
||||||
// scene data setters
|
setScene: (to: GameScene) => set(() => ({ currentScene: to })),
|
||||||
setScene: (to: string) => set(() => ({ currentScene: to })),
|
|
||||||
|
|
||||||
// node setters
|
|
||||||
setNodePos: (to: number[]) => set(() => ({ activeNodePos: to })),
|
setNodePos: (to: number[]) => set(() => ({ activeNodePos: to })),
|
||||||
setNodeRot: (to: number[]) => set(() => ({ activeNodeRot: to })),
|
setNodeRot: (to: number[]) => set(() => ({ activeNodeRot: to })),
|
||||||
setNodeAttributes: (
|
setNodeAttributes: (
|
||||||
|
@ -269,102 +323,6 @@ export const useStore = create(
|
||||||
activeNodeAttributes: { ...state.activeNodeAttributes, [at]: to },
|
activeNodeAttributes: { ...state.activeNodeAttributes, [at]: to },
|
||||||
})),
|
})),
|
||||||
|
|
||||||
// lain setters
|
|
||||||
setLainMoveState: (to: string) => set(() => ({ lainMoveState: to })),
|
|
||||||
|
|
||||||
// site setters
|
|
||||||
setSiteRotX: (to: number) =>
|
|
||||||
set((prev) => {
|
|
||||||
const nextRot = [...prev.siteRot];
|
|
||||||
nextRot[0] = to;
|
|
||||||
return { siteRot: nextRot };
|
|
||||||
}),
|
|
||||||
|
|
||||||
// end scene setters
|
|
||||||
setEndSceneSelectionVisible: (to: boolean) =>
|
|
||||||
set(() => ({ endSceneSelectionVisible: to })),
|
|
||||||
|
|
||||||
// pause setters
|
|
||||||
setShowingAbout: (to: boolean) => set(() => ({ showingAbout: to })),
|
|
||||||
|
|
||||||
// media scene setters
|
|
||||||
setAudioAnalyser: (to: any) => set(() => ({ audioAnalyser: to })),
|
|
||||||
setPercentageElapsed: (to: number) =>
|
|
||||||
set(() => ({ mediaPercentageElapsed: to })),
|
|
||||||
setWordSelected: (to: boolean) => set(() => ({ wordSelected: to })),
|
|
||||||
updateLeftSide: (
|
|
||||||
newActiveComponent: "fstWord" | "sndWord" | "thirdWord",
|
|
||||||
lastActiveComponent: "exit" | "play"
|
|
||||||
) =>
|
|
||||||
set((state) => ({
|
|
||||||
activeMediaComponent: newActiveComponent,
|
|
||||||
lastActiveMediaComponents: {
|
|
||||||
...state.lastActiveMediaComponents,
|
|
||||||
left: lastActiveComponent,
|
|
||||||
},
|
|
||||||
currentMediaSide: "right",
|
|
||||||
})),
|
|
||||||
updateRightSide: (
|
|
||||||
newActiveComponent: "play" | "exit",
|
|
||||||
lastActiveComponent: "fstWord" | "sndWord" | "thirdWord"
|
|
||||||
) =>
|
|
||||||
set((state) => ({
|
|
||||||
activeMediaComponent: newActiveComponent,
|
|
||||||
lastActiveMediaComponents: {
|
|
||||||
...state.lastActiveMediaComponents,
|
|
||||||
right: lastActiveComponent,
|
|
||||||
},
|
|
||||||
currentMediaSide: "left",
|
|
||||||
})),
|
|
||||||
|
|
||||||
// idle media setters
|
|
||||||
setIdleStarting: (to: boolean) => set(() => ({ idleStarting: to })),
|
|
||||||
setIdleScene: (to: {
|
|
||||||
images: { "1": string; "2": string; "3": string } | undefined;
|
|
||||||
media: string | undefined;
|
|
||||||
nodeName: string | undefined;
|
|
||||||
}) =>
|
|
||||||
set(() => ({
|
|
||||||
idleMedia: to.media,
|
|
||||||
idleImages: to.images,
|
|
||||||
idleNodeName: to.nodeName,
|
|
||||||
})),
|
|
||||||
|
|
||||||
//polytan setters
|
|
||||||
setPolytanPartUnlocked: (bodyPart: string) =>
|
|
||||||
set((state) => ({
|
|
||||||
polytanUnlockedParts: {
|
|
||||||
...state.polytanUnlockedParts,
|
|
||||||
[bodyPart]: true,
|
|
||||||
},
|
|
||||||
})),
|
|
||||||
|
|
||||||
changeSite: (to: "a" | "b") =>
|
|
||||||
set((state) => {
|
|
||||||
const newState = state.siteSaveState[to];
|
|
||||||
return {
|
|
||||||
currentScene: "change_disc",
|
|
||||||
promptVisible: false,
|
|
||||||
activePromptComponent: "no",
|
|
||||||
mainSubscene: "site",
|
|
||||||
// load new state
|
|
||||||
activeSite: to,
|
|
||||||
activeNode: newState.activeNode,
|
|
||||||
siteRot: newState.siteRot,
|
|
||||||
activeLevel: newState.activeLevel,
|
|
||||||
// save current state
|
|
||||||
siteSaveState: {
|
|
||||||
...state.siteSaveState,
|
|
||||||
[to === "a" ? "b" : "a"]: {
|
|
||||||
activeNode: state.activeNode,
|
|
||||||
siteRot: [0, state.siteRot[1], 0],
|
|
||||||
activeLevel: state.activeLevel,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
// progress setters
|
|
||||||
setNodeViewed: (
|
setNodeViewed: (
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
to: { is_viewed: number; is_visible: number }
|
to: { is_viewed: number; is_visible: number }
|
||||||
|
@ -376,13 +334,37 @@ export const useStore = create(
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
|
||||||
setInputCooldown: (to: boolean) => set(() => ({ inputCooldown: to })),
|
setLainMoveState: (to: string) => set(() => ({ lainMoveState: to })),
|
||||||
|
|
||||||
|
setEndSceneSelectionVisible: (to: boolean) =>
|
||||||
|
set(() => ({ endSceneSelectionVisible: to })),
|
||||||
|
|
||||||
|
setShowingAbout: (to: boolean) => set(() => ({ showingAbout: to })),
|
||||||
|
|
||||||
|
setAudioAnalyser: (to: AudioAnalyser) =>
|
||||||
|
set(() => ({ audioAnalyser: to })),
|
||||||
|
setPercentageElapsed: (to: number) =>
|
||||||
|
set(() => ({ mediaPercentageElapsed: to })),
|
||||||
|
setWordSelected: (to: boolean) => set(() => ({ wordSelected: to })),
|
||||||
|
|
||||||
|
setPolytanPartUnlocked: (bodyPart: string) =>
|
||||||
|
set((state) => ({
|
||||||
|
polytanUnlockedParts: {
|
||||||
|
...state.polytanUnlockedParts,
|
||||||
|
[bodyPart]: true,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
|
||||||
|
setInputCooldown: (to: number) => set(() => ({ inputCooldown: to })),
|
||||||
|
|
||||||
|
incrementGateLvl: () => set((state) => ({ gateLvl: state.gateLvl + 1 })),
|
||||||
|
incrementSsknLvl: () => set((state) => ({ ssknLvl: state.ssknLvl + 1 })),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
type PromptContext = {
|
type PromptContext = {
|
||||||
activePromptComponent: "yes" | "no";
|
activePromptComponent: PromptComponent;
|
||||||
promptVisible: boolean;
|
promptVisible: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -401,25 +383,15 @@ export interface MainSceneContext extends PromptContext {
|
||||||
activeNode: NodeData;
|
activeNode: NodeData;
|
||||||
showingAbout: boolean;
|
showingAbout: boolean;
|
||||||
level: number;
|
level: number;
|
||||||
activePauseComponent: "load" | "about" | "change" | "save" | "exit";
|
activePauseComponent: PauseComponent;
|
||||||
gameProgress: GameProgress;
|
gameProgress: GameProgress;
|
||||||
gateLvl: number;
|
gateLvl: number;
|
||||||
subscene: string;
|
subscene: string;
|
||||||
siteRotY: number;
|
siteRotY: number;
|
||||||
activeSite: "a" | "b";
|
activeSite: ActiveSite;
|
||||||
selectedLevel: number;
|
selectedLevel: number;
|
||||||
siteSaveState: {
|
wordNotFound: boolean;
|
||||||
a: {
|
siteSaveState: SiteSaveState;
|
||||||
activeNode: NodeData;
|
|
||||||
siteRot: number[];
|
|
||||||
activeLevel: string;
|
|
||||||
};
|
|
||||||
b: {
|
|
||||||
activeNode: NodeData;
|
|
||||||
siteRot: number[];
|
|
||||||
activeLevel: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getMainSceneContext = (keyPress: string): MainSceneContext => {
|
export const getMainSceneContext = (keyPress: string): MainSceneContext => {
|
||||||
|
@ -440,13 +412,16 @@ export const getMainSceneContext = (keyPress: string): MainSceneContext => {
|
||||||
showingAbout: state.showingAbout,
|
showingAbout: state.showingAbout,
|
||||||
gateLvl: state.gateLvl,
|
gateLvl: state.gateLvl,
|
||||||
siteSaveState: state.siteSaveState,
|
siteSaveState: state.siteSaveState,
|
||||||
|
wordNotFound: state.wordNotFound,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SsknSceneContext = {
|
export type SsknSceneContext = {
|
||||||
keyPress: string;
|
keyPress: string;
|
||||||
activeSsknComponent: "ok" | "cancel";
|
activeSsknComponent: SsknComponent;
|
||||||
activeNode: NodeData;
|
activeNode: NodeData;
|
||||||
|
gameProgress: GameProgress;
|
||||||
|
ssknLvl: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSsknSceneContext = (keyPress: string): SsknSceneContext => {
|
export const getSsknSceneContext = (keyPress: string): SsknSceneContext => {
|
||||||
|
@ -455,21 +430,23 @@ export const getSsknSceneContext = (keyPress: string): SsknSceneContext => {
|
||||||
keyPress: keyPress,
|
keyPress: keyPress,
|
||||||
activeSsknComponent: state.activeSsknComponent,
|
activeSsknComponent: state.activeSsknComponent,
|
||||||
activeNode: state.activeNode,
|
activeNode: state.activeNode,
|
||||||
|
gameProgress: state.gameProgress,
|
||||||
|
ssknLvl: state.ssknLvl,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MediaSceneContext = {
|
export type MediaSceneContext = {
|
||||||
keyPress: string;
|
keyPress: string;
|
||||||
wordPosStateIdx: number;
|
wordPosStateIdx: number;
|
||||||
currentMediaSide: "left" | "right";
|
currentMediaSide: MediaSide;
|
||||||
activeMediaComponent: "play" | "exit" | "fstWord" | "sndWord" | "thirdWord";
|
activeMediaComponent: MediaComponent;
|
||||||
activeNode: NodeData;
|
activeNode: NodeData;
|
||||||
gameProgress: GameProgress;
|
gameProgress: GameProgress;
|
||||||
lastActiveMediaComponents: {
|
lastActiveMediaComponents: {
|
||||||
left: "play" | "exit";
|
left: LeftMediaComponent;
|
||||||
right: "fstWord" | "sndWord" | "thirdWord";
|
right: RightMediaComponent;
|
||||||
};
|
};
|
||||||
activeSite: "a" | "b";
|
activeSite: ActiveSite;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMediaSceneContext = (keyPress: string): MediaSceneContext => {
|
export const getMediaSceneContext = (keyPress: string): MediaSceneContext => {
|
||||||
|
@ -490,8 +467,8 @@ export const getMediaSceneContext = (keyPress: string): MediaSceneContext => {
|
||||||
export interface BootSceneContext extends PromptContext {
|
export interface BootSceneContext extends PromptContext {
|
||||||
keyPress: string;
|
keyPress: string;
|
||||||
playerName: string;
|
playerName: string;
|
||||||
subscene: "main_menu" | "load_data" | "authorize_user";
|
subscene: BootSubscene;
|
||||||
activeMainMenuComponent: "load_data" | "authorize_user";
|
activeMainMenuComponent: MainMenuComponent;
|
||||||
authorizeUserLetterIdx: number;
|
authorizeUserLetterIdx: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +487,7 @@ export const getBootSceneContext = (keyPress: string): BootSceneContext => {
|
||||||
|
|
||||||
export type EndSceneContext = {
|
export type EndSceneContext = {
|
||||||
keyPress: string;
|
keyPress: string;
|
||||||
activeEndComponent: "end" | "continue";
|
activeEndComponent: EndComponent;
|
||||||
selectionVisible: boolean;
|
selectionVisible: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
2
src/tests/media-helpers.test.ts
Normal file
2
src/tests/media-helpers.test.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import { findNodeFromWord } from "../helpers/media-helpers";
|
||||||
|
|
Loading…
Reference in a new issue