mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 15:06:02 +01:00
feat(web/skillcheck): random skill check key from inputs table
This commit is contained in:
@@ -2,10 +2,13 @@ import { debugData } from '../../../utils/debugData';
|
||||
import { GameDifficulty } from '../../skillcheck';
|
||||
|
||||
export const debugSkillCheck = () => {
|
||||
debugData<GameDifficulty | GameDifficulty[]>([
|
||||
debugData<{ difficulty: GameDifficulty | GameDifficulty[]; inputs?: string[] }>([
|
||||
{
|
||||
action: 'startSkillCheck',
|
||||
data: ['easy', 'easy', 'hard'],
|
||||
data: {
|
||||
difficulty: ['easy', 'easy', 'hard'],
|
||||
inputs: ['W', 'A', 'S', 'D'],
|
||||
},
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -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<GameDifficulty | GameDifficulty[] | null>(null);
|
||||
const dataRef = useRef<{ difficulty: GameDifficulty | GameDifficulty[]; inputs?: string[] } | null>(null);
|
||||
const dataIndexRef = useRef<number>(0);
|
||||
const [skillCheck, setSkillCheck] = useState<SkillCheckProps>({
|
||||
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}
|
||||
/>
|
||||
</svg>
|
||||
<Box className={classes.button}>E</Box>
|
||||
<Box className={classes.button}>{skillCheck.key.toUpperCase()}</Box>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -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<Props> = ({ 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<Props> = ({ 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<Props> = ({ 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 (
|
||||
<circle
|
||||
|
||||
Reference in New Issue
Block a user