mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
lots of bugfixes
This commit is contained in:
parent
75bf23f8ef
commit
371c6a893f
13 changed files with 830 additions and 1524 deletions
|
@ -3,14 +3,11 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/png" href="icon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript
|
||||
>do you actually believe i could rewrite this in plain html css or
|
||||
smoetihng</noscript
|
||||
>
|
||||
<noscript>Your browser has JavaScript disabled, please enable it.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import "./static/css/page.css";
|
||||
import Game from "./dom-components/Game";
|
||||
import { HashRouter, Route, Switch } from "react-router-dom";
|
||||
import Notes from "./dom-components/Notes";
|
||||
|
||||
const App = () => {
|
||||
useEffect(() => {
|
||||
document.title = "< index >";
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<HashRouter>
|
||||
<Switch>
|
||||
|
|
|
@ -26,6 +26,7 @@ import { saveUserProgress, useStore } from "../store";
|
|||
|
||||
const setNodeViewed = useStore.getState().setNodeViewed;
|
||||
const resetMediaScene = useStore.getState().resetMediaScene;
|
||||
const incrementSsknLvl = useStore.getState().incrementSsknLvl;
|
||||
const loadUserSaveState = useStore.getState().loadUserSaveState;
|
||||
|
||||
export const siteMoveHorizontal = (calculatedState: {
|
||||
|
@ -462,11 +463,7 @@ export const playMedia = (calculatedState: { activeNode: NodeData }) => ({
|
|||
state: [{ mutation: { mediaPercentageElapsed: 0, inputCooldown: 500 } }],
|
||||
effects: [
|
||||
playMediaElement,
|
||||
() =>
|
||||
setNodeViewed(calculatedState.activeNode.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 1,
|
||||
}),
|
||||
() => setNodeViewed(calculatedState.activeNode.node_name),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -561,11 +558,8 @@ export const upgradeSskn = (calculatedState: { activeNode: NodeData }) => ({
|
|||
{ mutation: { currentScene: "main" }, delay: 6000 },
|
||||
],
|
||||
effects: [
|
||||
() =>
|
||||
setNodeViewed(calculatedState.activeNode.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 0,
|
||||
}),
|
||||
incrementSsknLvl,
|
||||
() => setNodeViewed(calculatedState.activeNode.node_name),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -609,7 +603,7 @@ export const changeMainMenuComponent = (calculatedState: {
|
|||
{
|
||||
mutation: {
|
||||
activeMainMenuComponent: calculatedState.activeMainMenuComponent,
|
||||
inputCooldown: 200,
|
||||
inputCooldown: 100,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -671,7 +665,11 @@ export const startNewGame = {
|
|||
};
|
||||
|
||||
export const updatePlayerName = (calculatedState: { playerName: string }) => ({
|
||||
state: [{ mutation: { playerName: calculatedState.playerName } }],
|
||||
state: [
|
||||
{
|
||||
mutation: { playerName: calculatedState.playerName, inputCooldown: 100 },
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
});
|
||||
|
||||
|
@ -690,7 +688,7 @@ export const updateAuthorizeUserLetterMatrixIndices = (calculatedState: {
|
|||
state: [
|
||||
{
|
||||
mutation: {
|
||||
inputCooldown: 300,
|
||||
inputCooldown: 0,
|
||||
authorizeUserMatrixIndices:
|
||||
calculatedState.authorizeUserLetterMatrixIndices,
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
changeRightMediaComponent,
|
||||
exitMedia,
|
||||
playMedia,
|
||||
resetInputCooldown,
|
||||
selectWord,
|
||||
wordNotFound,
|
||||
} from "../eventTemplates";
|
||||
|
@ -39,7 +40,7 @@ const handleMediaSceneInput = (
|
|||
return changeLeftMediaComponent({ activeComponent: newComponent });
|
||||
}
|
||||
case "RIGHT": {
|
||||
if (!activeNode.media_file.includes("XA")) return;
|
||||
if (!activeNode.media_file.includes("XA")) return resetInputCooldown;
|
||||
|
||||
return changeMediaSide({
|
||||
activeMediaComponent: lastActiveMediaComponents.right,
|
||||
|
|
|
@ -26,7 +26,7 @@ const Game = () => {
|
|||
const currentScene = useStore((state) => state.currentScene);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "< index >";
|
||||
document.title = "< game >";
|
||||
}, []);
|
||||
|
||||
const dispatchScene = useMemo(
|
||||
|
@ -65,12 +65,7 @@ const Game = () => {
|
|||
|
||||
const handleScreenResize = useCallback(() => {
|
||||
const isMobile = mobileAndTabletCheck();
|
||||
if (!isMobile) {
|
||||
const h = window.screen.height / 1.8;
|
||||
setWidth(h * 1.3);
|
||||
setHeight(h);
|
||||
setIsMobile(false);
|
||||
} else {
|
||||
if (isMobile) {
|
||||
const h = window.screen.height / 1.05;
|
||||
setHeight(h);
|
||||
setWidth(h * 1.3);
|
||||
|
@ -90,7 +85,10 @@ const Game = () => {
|
|||
}, [handleGameResize, handleScreenResize, isMobile]);
|
||||
|
||||
return (
|
||||
<div className="game" style={{ width: width, height: height }}>
|
||||
<div
|
||||
className="game"
|
||||
style={{ width: Math.round(width), height: Math.round(height) }}
|
||||
>
|
||||
<Canvas
|
||||
concurrent
|
||||
gl={{ antialias: false }}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import "../static/css/notes.css";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const Notes = () => {
|
||||
useEffect(() => {
|
||||
document.title = "< notes >";
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<table className="main-table">
|
||||
|
@ -22,6 +26,43 @@ const Notes = () => {
|
|||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>WebGL2</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Your setup must support WebGL2 in order to play this game. You
|
||||
can check this directly by going to{" "}
|
||||
<a
|
||||
href={"https://get.webgl.org/webgl2/"}
|
||||
className="webgl-anchor"
|
||||
>
|
||||
this website
|
||||
</a>
|
||||
. If it's not supported, this is most likely due to your
|
||||
browser. Try another one, preferably chromium/firefox-based,
|
||||
keeping in mind the notes written inside Performance. This could
|
||||
also be caused by your drivers being outdated.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Browser settings</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
This part might be updated from time to time as more issues pop
|
||||
up. <br />
|
||||
<br />
|
||||
Firefox: <br />
|
||||
privacy.resistFingerprinting needs to be set to false (it should
|
||||
be by default). Otherwise, it limits the maximum WebGL texture size to
|
||||
2048, resulting in poor sprite quality.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Keyboard Controls</p>
|
||||
|
@ -77,6 +118,7 @@ const Notes = () => {
|
|||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<p>Mobile/Tablet Controls</p>
|
||||
|
@ -126,27 +168,6 @@ const Notes = () => {
|
|||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Sound</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The game assumes that your browser volume is set to 100% (via
|
||||
the sound mixer on your operating system). It uses the Web Audio
|
||||
API to display the audio visualizer and animate Lain's mouth
|
||||
movements inside some media files. Both of those things depend
|
||||
on the browser's output volume, therefore, if you want to lower
|
||||
the game's volume, it is recommended you do so by lowering the
|
||||
system volume itself, as opposed to muting the browser
|
||||
tab/lowering the browser volume directly. Otherwise, the two
|
||||
functionalities mentioned above won't work properly.
|
||||
<br />
|
||||
If this becomes a huge problem later on, I'll try to implement
|
||||
an alternative for it.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Link to="/game">start</Link>
|
||||
|
|
|
@ -63,22 +63,31 @@ export const isNodeVisible = (
|
|||
node: NodeData,
|
||||
gameProgress: typeof unlocked_nodes
|
||||
) => {
|
||||
return node
|
||||
? Boolean(
|
||||
(node.unlocked_by === "" ||
|
||||
gameProgress.nodes[
|
||||
node.unlocked_by as keyof typeof gameProgress.nodes
|
||||
].is_viewed) &&
|
||||
gameProgress.nodes[node.node_name as keyof typeof gameProgress.nodes]
|
||||
.is_visible &&
|
||||
(node.required_final_video_viewcount > 0
|
||||
? gameProgress.final_video_viewcount > 0
|
||||
? node.required_final_video_viewcount <=
|
||||
gameProgress.final_video_viewcount + 1
|
||||
: false
|
||||
: true)
|
||||
)
|
||||
: false;
|
||||
return (() => {
|
||||
switch (node.type) {
|
||||
// polytan, sskn, gate nodes
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
return !gameProgress.nodes[
|
||||
node.node_name as keyof typeof gameProgress.nodes
|
||||
].is_viewed;
|
||||
// every other node
|
||||
default:
|
||||
return Boolean(
|
||||
(node.unlocked_by === "" ||
|
||||
gameProgress.nodes[
|
||||
node.unlocked_by as keyof typeof gameProgress.nodes
|
||||
].is_viewed) &&
|
||||
(node.required_final_video_viewcount > 0
|
||||
? gameProgress.final_video_viewcount > 0
|
||||
? node.required_final_video_viewcount <=
|
||||
gameProgress.final_video_viewcount + 1
|
||||
: false
|
||||
: true)
|
||||
);
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
export const getVisibleNodesMatrix = (
|
||||
|
@ -94,8 +103,10 @@ export const getVisibleNodesMatrix = (
|
|||
return currentMatrix.map((row: string[]) =>
|
||||
row.map((nodePos: string) => {
|
||||
const nodeId = formattedLevel + nodePos;
|
||||
if (isNodeVisible(getNodeById(nodeId, activeSite), gameProgress))
|
||||
return nodeId;
|
||||
|
||||
const node = getNodeById(nodeId, activeSite);
|
||||
|
||||
if (node && isNodeVisible(node, gameProgress)) return nodeId;
|
||||
else return undefined;
|
||||
})
|
||||
);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,10 +15,7 @@ const GateScene = () => {
|
|||
|
||||
useEffect(() => {
|
||||
incrementGateLvl();
|
||||
setNodeViewed(activeNodeName, {
|
||||
is_viewed: 1,
|
||||
is_visible: 0,
|
||||
});
|
||||
setNodeViewed(activeNodeName);
|
||||
setTimeout(() => setIntroAnim(false), 2500);
|
||||
setTimeout(() => setInputCooldown(0), 3500);
|
||||
}, [activeNodeName, incrementGateLvl, setInputCooldown, setNodeViewed]);
|
||||
|
|
|
@ -13,10 +13,7 @@ const PolytanScene = () => {
|
|||
|
||||
useEffect(() => {
|
||||
setTimeout(() => setInputCooldown(0), 1000);
|
||||
setNodeViewed(activeNodeName, {
|
||||
is_viewed: 1,
|
||||
is_visible: 0,
|
||||
});
|
||||
setNodeViewed(activeNodeName);
|
||||
const bodyPart = (() => {
|
||||
switch (parseInt(activeNodeName.slice(-1))) {
|
||||
case 6:
|
||||
|
|
|
@ -16,10 +16,7 @@ const TaKScene = () => {
|
|||
const setNodeViewed = useStore((state) => state.setNodeViewed);
|
||||
|
||||
useEffect(() => {
|
||||
setNodeViewed(activeNode.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 1,
|
||||
});
|
||||
setNodeViewed(activeNode.node_name);
|
||||
}, [activeNode.node_name, setNodeViewed]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
19
src/store.ts
19
src/store.ts
|
@ -181,7 +181,7 @@ export const useStore = create(
|
|||
idleStarting: false,
|
||||
idleMedia: site_a["00"]["0000"].media_file,
|
||||
idleNodeName: site_a["00"]["0000"].node_name,
|
||||
// this may be undefined depending on whether or not the media is audio or not
|
||||
// this may be undefined depending on whether or not the media is audio only or not
|
||||
idleImages: site_a["00"]["0000"].image_table_indices,
|
||||
|
||||
// sskn scene
|
||||
|
@ -255,12 +255,12 @@ export const useStore = create(
|
|||
activeNodeAttributes: { ...state.activeNodeAttributes, [at]: to },
|
||||
})),
|
||||
|
||||
setNodeViewed: (
|
||||
nodeName: string,
|
||||
to: { is_viewed: number; is_visible: number }
|
||||
) =>
|
||||
setNodeViewed: (nodeName: string) =>
|
||||
set((state) => {
|
||||
const nodes = { ...state.gameProgress.nodes, [nodeName]: to };
|
||||
const nodes = {
|
||||
...state.gameProgress.nodes,
|
||||
[nodeName]: { is_viewed: 1 },
|
||||
};
|
||||
return {
|
||||
gameProgress: {
|
||||
...state.gameProgress,
|
||||
|
@ -314,6 +314,13 @@ export const useStore = create(
|
|||
gate_level: state.gameProgress.gate_level + 1,
|
||||
},
|
||||
})),
|
||||
incrementSsknLvl: () =>
|
||||
set((state) => ({
|
||||
gameProgress: {
|
||||
...state.gameProgress,
|
||||
sskn_level: state.gameProgress.sskn_level + 1,
|
||||
},
|
||||
})),
|
||||
|
||||
loadUserSaveState: (userState: UserSaveState) =>
|
||||
set(() => ({
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
const getKeyPress = (keyCode: string) => {
|
||||
const getKeyPress = (key: string) => {
|
||||
if (["X", "Z", "D", "E", "V"].includes(key)) key = key.toLowerCase();
|
||||
|
||||
const keyCodeAssocs = {
|
||||
ArrowDown: "DOWN", // down arrow
|
||||
ArrowLeft: "LEFT", // left arrow
|
||||
|
@ -10,7 +12,7 @@ const getKeyPress = (keyCode: string) => {
|
|||
e: "L2", // e key
|
||||
v: "START", // v key
|
||||
};
|
||||
return keyCodeAssocs[keyCode as keyof typeof keyCodeAssocs];
|
||||
return keyCodeAssocs[key as keyof typeof keyCodeAssocs];
|
||||
};
|
||||
|
||||
export default getKeyPress;
|
||||
|
|
Loading…
Reference in a new issue