mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-18 23:46:03 +01:00
refactor(skillcheck): move array handling into ui
This commit is contained in:
@@ -1,62 +1,28 @@
|
|||||||
---@type promise?
|
---@type promise?
|
||||||
local skillcheck
|
local skillcheck
|
||||||
local gameCount = 0
|
|
||||||
|
|
||||||
---@alias SkillCheckDifficulity 'easy' | 'medium' | 'hard' | { areaSize: number, speedMultiplier: number }
|
---@alias SkillCheckDifficulity 'easy' | 'medium' | 'hard' | { areaSize: number, speedMultiplier: number }
|
||||||
|
|
||||||
---@type SkillCheckDifficulity | SkillCheckDifficulity[]
|
|
||||||
local gameDifficulty
|
|
||||||
|
|
||||||
---@type promise?
|
|
||||||
local gamePromise
|
|
||||||
|
|
||||||
local function resolveSkillCheck(success)
|
|
||||||
if skillcheck then
|
|
||||||
skillcheck:resolve(success)
|
|
||||||
skillcheck = nil
|
|
||||||
SetNuiFocus(false, false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param difficulty SkillCheckDifficulity | SkillCheckDifficulity[]
|
---@param difficulty SkillCheckDifficulity | SkillCheckDifficulity[]
|
||||||
---@return boolean?
|
---@return boolean?
|
||||||
function lib.skillCheck(difficulty)
|
function lib.skillCheck(difficulty)
|
||||||
if skillcheck then return end
|
if skillcheck then return end
|
||||||
|
|
||||||
skillcheck = promise:new()
|
skillcheck = promise:new()
|
||||||
gameDifficulty = difficulty
|
|
||||||
SetNuiFocus(true, false)
|
|
||||||
|
|
||||||
if type(difficulty) == 'table' then
|
SetNuiFocus(true, false)
|
||||||
gameCount = 0
|
|
||||||
for i = 1, #difficulty do
|
|
||||||
gamePromise = promise:new()
|
|
||||||
SendNUIMessage({
|
|
||||||
action = 'startSkillCheck',
|
|
||||||
data = difficulty[i]
|
|
||||||
})
|
|
||||||
if not Citizen.Await(gamePromise) then
|
|
||||||
gamePromise = nil
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
SendNUIMessage({
|
SendNUIMessage({
|
||||||
action = 'startSkillCheck',
|
action = 'startSkillCheck',
|
||||||
data = difficulty
|
data = difficulty
|
||||||
})
|
})
|
||||||
end
|
|
||||||
|
|
||||||
return Citizen.Await(skillcheck)
|
return Citizen.Await(skillcheck)
|
||||||
end
|
end
|
||||||
|
|
||||||
RegisterNUICallback('skillCheckOver', function(data, cb)
|
RegisterNUICallback('skillCheckOver', function(success, cb)
|
||||||
cb(1)
|
cb(1)
|
||||||
if not gamePromise then return resolveSkillCheck(data.success) end
|
if skillcheck then
|
||||||
gamePromise:resolve(data.success)
|
skillcheck:resolve(success)
|
||||||
if not data.success then return resolveSkillCheck(data.success) end
|
skillcheck = nil
|
||||||
gameCount += 1
|
SetNuiFocus(false, false)
|
||||||
if gameCount == #gameDifficulty then
|
|
||||||
resolveSkillCheck(data.success)
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Box, Center } from '@chakra-ui/react';
|
import { Box, Center } from '@chakra-ui/react';
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useNuiEvent } from '../../hooks/useNuiEvent';
|
import { useNuiEvent } from '../../hooks/useNuiEvent';
|
||||||
import { debugData } from '../../utils/debugData';
|
import { debugData } from '../../utils/debugData';
|
||||||
import Indicator from './indicator';
|
import Indicator from './indicator';
|
||||||
|
import { fetchNui } from '../../utils/fetchNui';
|
||||||
|
|
||||||
interface CustomGameDifficulty {
|
interface CustomGameDifficulty {
|
||||||
areaSize: number;
|
areaSize: number;
|
||||||
@@ -28,27 +29,54 @@ const difficultyOffsets = {
|
|||||||
debugData([
|
debugData([
|
||||||
{
|
{
|
||||||
action: 'startSkillCheck',
|
action: 'startSkillCheck',
|
||||||
data: 'easy',
|
data: [{ areaSize: 250, speedMultiplier: 2 }, 'easy'],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const SkillCheck: React.FC = () => {
|
const SkillCheck: React.FC = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
|
const dataRef = useRef<GameDifficulty | GameDifficulty[] | null>(null);
|
||||||
|
const dataIndexRef = useRef<number>(0);
|
||||||
const [skillCheck, setSkillCheck] = useState<SkillCheckProps>({
|
const [skillCheck, setSkillCheck] = useState<SkillCheckProps>({
|
||||||
angle: 0,
|
angle: 0,
|
||||||
difficultyOffset: 315,
|
difficultyOffset: 315,
|
||||||
difficulty: 'easy',
|
difficulty: 'easy',
|
||||||
});
|
});
|
||||||
|
|
||||||
useNuiEvent('startSkillCheck', (data: GameDifficulty) => {
|
useNuiEvent('startSkillCheck', (data: GameDifficulty | GameDifficulty[]) => {
|
||||||
|
dataRef.current = data;
|
||||||
|
dataIndexRef.current = 0;
|
||||||
|
const gameData = Array.isArray(data) ? data[0] : data;
|
||||||
|
const offset = typeof gameData === 'object' ? gameData.areaSize : difficultyOffsets[gameData];
|
||||||
|
setSkillCheck({
|
||||||
|
angle: -90 + getRandomAngle(120, 360 - (315 - offset)),
|
||||||
|
difficultyOffset: offset,
|
||||||
|
difficulty: gameData,
|
||||||
|
});
|
||||||
|
|
||||||
|
setVisible(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleComplete = (success: boolean) => {
|
||||||
|
if (!success || !Array.isArray(dataRef.current)) {
|
||||||
|
setVisible(false);
|
||||||
|
return fetchNui('skillCheckOver', success);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataIndexRef.current >= dataRef.current.length - 1) {
|
||||||
|
setVisible(false);
|
||||||
|
return fetchNui('skillCheckOver', success);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataIndexRef.current++;
|
||||||
|
const data = dataRef.current[dataIndexRef.current];
|
||||||
const offset = typeof data === 'object' ? data.areaSize : difficultyOffsets[data];
|
const offset = typeof data === 'object' ? data.areaSize : difficultyOffsets[data];
|
||||||
setSkillCheck({
|
setSkillCheck({
|
||||||
angle: -90 + getRandomAngle(120, 360 - (315 - offset)),
|
angle: -90 + getRandomAngle(120, 360 - (315 - offset)),
|
||||||
difficultyOffset: offset,
|
difficultyOffset: offset,
|
||||||
difficulty: data,
|
difficulty: data,
|
||||||
});
|
});
|
||||||
setVisible(true);
|
};
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Center height="100%" width="100%">
|
<Center height="100%" width="100%">
|
||||||
@@ -89,8 +117,8 @@ const SkillCheck: React.FC = () => {
|
|||||||
? 1.75
|
? 1.75
|
||||||
: skillCheck.difficulty.speedMultiplier
|
: skillCheck.difficulty.speedMultiplier
|
||||||
}
|
}
|
||||||
setSkillCheck={setSkillCheck}
|
handleComplete={handleComplete}
|
||||||
setVisible={setVisible}
|
skillCheck={skillCheck}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -2,48 +2,61 @@ import { useEffect, useRef, useState } from 'react';
|
|||||||
import { useNuiEvent } from '../../hooks/useNuiEvent';
|
import { useNuiEvent } from '../../hooks/useNuiEvent';
|
||||||
import { useKeyPress } from '../../hooks/useKeyPress';
|
import { useKeyPress } from '../../hooks/useKeyPress';
|
||||||
import { fetchNui } from '../../utils/fetchNui';
|
import { fetchNui } from '../../utils/fetchNui';
|
||||||
import { SkillCheckProps } from './index';
|
import skillcheck, { SkillCheckProps } from './index';
|
||||||
|
import { useInterval } from '@chakra-ui/react';
|
||||||
|
import { Simulate } from 'react-dom/test-utils';
|
||||||
|
import keyPress = Simulate.keyPress;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
angle: number;
|
angle: number;
|
||||||
offset: number;
|
offset: number;
|
||||||
multiplier: number;
|
multiplier: number;
|
||||||
setVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
skillCheck: SkillCheckProps;
|
||||||
setSkillCheck: React.Dispatch<React.SetStateAction<SkillCheckProps>>;
|
handleComplete: (success: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Indicator: React.FC<Props> = ({ angle, offset, multiplier, setSkillCheck, setVisible }) => {
|
const Indicator: React.FC<Props> = ({ angle, offset, multiplier, handleComplete, skillCheck }) => {
|
||||||
const [indicatorAngle, setIndicatorAngle] = useState(-90);
|
const [indicatorAngle, setIndicatorAngle] = useState(-90);
|
||||||
const intervalRef = useRef<NodeJS.Timer | null>(null);
|
const [gameState, setGameState] = useState(false);
|
||||||
const isKeyPressed = useKeyPress('e');
|
const isKeyPressed = useKeyPress('e');
|
||||||
|
|
||||||
useEffect(() => {
|
useInterval(
|
||||||
intervalRef.current = setInterval(() => {
|
() => {
|
||||||
setIndicatorAngle((prevState) => (prevState += multiplier));
|
setIndicatorAngle((prevState) => {
|
||||||
}, 1);
|
return (prevState += multiplier);
|
||||||
|
});
|
||||||
return () => {
|
},
|
||||||
if (intervalRef.current) clearInterval(intervalRef.current);
|
gameState ? 1 : null
|
||||||
};
|
);
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (intervalRef.current && indicatorAngle + 90 >= 360) {
|
setIndicatorAngle(-90);
|
||||||
clearInterval(intervalRef.current);
|
setGameState(true);
|
||||||
fetchNui('skillCheckOver', { success: false });
|
}, [skillCheck]);
|
||||||
setVisible(false);
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (indicatorAngle + 90 >= 360) {
|
||||||
|
// fetchNui('skillCheckOver', { success: false });
|
||||||
|
setGameState(false);
|
||||||
|
handleComplete(false);
|
||||||
}
|
}
|
||||||
|
}, [indicatorAngle]);
|
||||||
|
|
||||||
if (isKeyPressed && intervalRef.current) {
|
useEffect(() => {
|
||||||
clearInterval(intervalRef.current);
|
if (!isKeyPressed) return;
|
||||||
|
//
|
||||||
|
|
||||||
|
setGameState(false);
|
||||||
|
if (isKeyPressed) {
|
||||||
if (indicatorAngle < angle || indicatorAngle > angle + (315 - offset)) {
|
if (indicatorAngle < angle || indicatorAngle > angle + (315 - offset)) {
|
||||||
fetchNui('skillCheckOver', { success: false });
|
// fetchNui('skillCheckOver', { success: false });
|
||||||
|
handleComplete(false);
|
||||||
} else {
|
} else {
|
||||||
fetchNui('skillCheckOver', { success: true });
|
// fetchNui('skillCheckOver', { success: true });
|
||||||
|
handleComplete(true);
|
||||||
}
|
}
|
||||||
setVisible(false);
|
|
||||||
}
|
}
|
||||||
}, [indicatorAngle, isKeyPressed]);
|
}, [isKeyPressed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<circle
|
<circle
|
||||||
|
|||||||
Reference in New Issue
Block a user