From f166c1675ea57aedd009fe670e84fec48554035c Mon Sep 17 00:00:00 2001 From: Luke <39926192+LukeWasTakenn@users.noreply.github.com> Date: Sun, 12 Feb 2023 19:26:09 +0100 Subject: [PATCH] feat(web/skillcheck): random skill check key from inputs table --- resource/interface/client/skillcheck.lua | 7 +++++-- web/src/features/dev/debug/skillcheck.ts | 7 +++++-- web/src/features/skillcheck/index.tsx | 24 +++++++++++++++-------- web/src/features/skillcheck/indicator.tsx | 21 +++++++++++++++----- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/resource/interface/client/skillcheck.lua b/resource/interface/client/skillcheck.lua index cbae068..bd3f2db 100644 --- a/resource/interface/client/skillcheck.lua +++ b/resource/interface/client/skillcheck.lua @@ -5,14 +5,17 @@ local skillcheck ---@param difficulty SkillCheckDifficulity | SkillCheckDifficulity[] ---@return boolean? -function lib.skillCheck(difficulty) +function lib.skillCheck(difficulty, inputs) if skillcheck then return end skillcheck = promise:new() SetNuiFocus(true, false) SendNUIMessage({ action = 'startSkillCheck', - data = difficulty + data = { + difficulty = difficulty, + inputs = inputs + } }) return Citizen.Await(skillcheck) diff --git a/web/src/features/dev/debug/skillcheck.ts b/web/src/features/dev/debug/skillcheck.ts index ad50032..3e689b2 100644 --- a/web/src/features/dev/debug/skillcheck.ts +++ b/web/src/features/dev/debug/skillcheck.ts @@ -2,10 +2,13 @@ import { debugData } from '../../../utils/debugData'; import { GameDifficulty } from '../../skillcheck'; export const debugSkillCheck = () => { - debugData([ + debugData<{ difficulty: GameDifficulty | GameDifficulty[]; inputs?: string[] }>([ { action: 'startSkillCheck', - data: ['easy', 'easy', 'hard'], + data: { + difficulty: ['easy', 'easy', 'hard'], + inputs: ['W', 'A', 'S', 'D'], + }, }, ]); }; diff --git a/web/src/features/skillcheck/index.tsx b/web/src/features/skillcheck/index.tsx index 2932cb2..55a9130 100644 --- a/web/src/features/skillcheck/index.tsx +++ b/web/src/features/skillcheck/index.tsx @@ -15,6 +15,7 @@ export interface SkillCheckProps { angle: number; difficultyOffset: number; difficulty: GameDifficulty; + key: string; } export const circleCircumference = 2 * 50 * Math.PI; @@ -65,49 +66,56 @@ const useStyles = createStyles((theme) => ({ })); const SkillCheck: React.FC = () => { - const theme = useMantineTheme(); const { classes } = useStyles(); const [visible, setVisible] = useState(false); - const dataRef = useRef(null); + const dataRef = useRef<{ difficulty: GameDifficulty | GameDifficulty[]; inputs?: string[] } | null>(null); const dataIndexRef = useRef(0); const [skillCheck, setSkillCheck] = useState({ angle: 0, difficultyOffset: 50, difficulty: 'easy', + key: 'e', }); - useNuiEvent('startSkillCheck', (data: GameDifficulty | GameDifficulty[]) => { + useNuiEvent('startSkillCheck', (data: { difficulty: GameDifficulty | GameDifficulty[]; inputs?: string[] }) => { dataRef.current = data; dataIndexRef.current = 0; - const gameData = Array.isArray(data) ? data[0] : data; + const gameData = Array.isArray(data.difficulty) ? data.difficulty[0] : data.difficulty; const offset = typeof gameData === 'object' ? gameData.areaSize : difficultyOffsets[gameData]; + const randomKey = data.inputs ? data.inputs[Math.floor(Math.random() * data.inputs.length)] : 'e'; setSkillCheck({ angle: -90 + getRandomAngle(120, 360 - offset), difficultyOffset: offset, difficulty: gameData, + key: randomKey, }); setVisible(true); }); const handleComplete = (success: boolean) => { - if (!success || !Array.isArray(dataRef.current)) { + if (!dataRef.current) return; + if (!success || !Array.isArray(dataRef.current.difficulty)) { setVisible(false); return fetchNui('skillCheckOver', success); } - if (dataIndexRef.current >= dataRef.current.length - 1) { + if (dataIndexRef.current >= dataRef.current.difficulty.length - 1) { setVisible(false); return fetchNui('skillCheckOver', success); } dataIndexRef.current++; - const data = dataRef.current[dataIndexRef.current]; + const data = dataRef.current.difficulty[dataIndexRef.current]; + const key = dataRef.current.inputs + ? dataRef.current.inputs[Math.floor(Math.random() * dataRef.current.inputs.length)] + : 'e'; const offset = typeof data === 'object' ? data.areaSize : difficultyOffsets[data]; setSkillCheck({ angle: -90 + getRandomAngle(120, 360 - offset), difficultyOffset: offset, difficulty: data, + key, }); }; @@ -145,7 +153,7 @@ const SkillCheck: React.FC = () => { skillCheck={skillCheck} /> - E + {skillCheck.key.toUpperCase()} )} diff --git a/web/src/features/skillcheck/indicator.tsx b/web/src/features/skillcheck/indicator.tsx index 0589ab9..df43155 100644 --- a/web/src/features/skillcheck/indicator.tsx +++ b/web/src/features/skillcheck/indicator.tsx @@ -1,7 +1,6 @@ -import { useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useKeyPress } from '../../hooks/useKeyPress'; import { SkillCheckProps } from './index'; -// import { useInterval } from '@chakra-ui/react'; import { useInterval } from '@mantine/hooks'; import { circleCircumference } from './index'; @@ -16,7 +15,7 @@ interface Props { const Indicator: React.FC = ({ angle, offset, multiplier, handleComplete, skillCheck, className }) => { const [indicatorAngle, setIndicatorAngle] = useState(-90); - const isKeyPressed = useKeyPress('e'); + const [keyPressed, setKeyPressed] = useState(false); const interval = useInterval( () => setIndicatorAngle((prevState) => { @@ -25,8 +24,17 @@ const Indicator: React.FC = ({ angle, offset, multiplier, handleComplete, 1 ); + const keyHandler = useCallback( + (e: KeyboardEvent) => { + if (e.key.toLowerCase() !== skillCheck.key.toLowerCase()) return; + setKeyPressed(true); + }, + [skillCheck] + ); + useEffect(() => { setIndicatorAngle(-90); + window.addEventListener('keydown', keyHandler); interval.start(); }, [skillCheck]); @@ -38,13 +46,16 @@ const Indicator: React.FC = ({ angle, offset, multiplier, handleComplete, }, [indicatorAngle]); useEffect(() => { - if (!isKeyPressed) return; + if (!keyPressed) return; interval.stop(); + setKeyPressed(false); + window.removeEventListener('keydown', keyHandler); + if (indicatorAngle < angle || indicatorAngle > angle + offset) handleComplete(false); else handleComplete(true); - }, [isKeyPressed]); + }, [keyPressed]); return (