forked from Simnation/Main
196 lines
6.1 KiB
Lua
196 lines
6.1 KiB
Lua
-- https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
|
local sequenceKeys = {
|
|
{ code = 0x56, label = "V" },
|
|
{ code = 0x43, label = "C" },
|
|
{ code = 0x52, label = "R" },
|
|
{ code = 0x51, label = "Q" },
|
|
{ code = 0x47, label = "G" },
|
|
{ code = 0x45, label = "E" },
|
|
{ code = 0x58, label = "X" },
|
|
{ code = 0x59, label = "Y" },
|
|
{ code = 0x48, label = "H" },
|
|
{ code = 0x5A, label = "Z" },
|
|
}
|
|
|
|
local function GenerateSequence(len)
|
|
local seq = {}
|
|
for i = 1, len do
|
|
seq[i] = sequenceKeys[math.random(#sequenceKeys)]
|
|
end
|
|
return seq
|
|
end
|
|
|
|
local function DrawSequenceRect(x, y, w, h, r, g, b, a)
|
|
DrawRect(x + w / 2, y + h / 2, w, h, r, g, b, math.floor(a))
|
|
end
|
|
|
|
local function DrawSequenceText(x, y, text, scale, r, g, b, a, center, outline)
|
|
SetTextFont(0)
|
|
SetTextScale(scale, scale)
|
|
SetTextColour(r, g, b, math.floor(a))
|
|
SetTextCentre(center)
|
|
if outline then
|
|
SetTextDropshadow(1, 0, 0, 0, 50)
|
|
SetTextOutline()
|
|
end
|
|
SetTextEntry("STRING")
|
|
AddTextComponentSubstringPlayerName(text)
|
|
DrawText(x, y)
|
|
end
|
|
|
|
local function DrawLabelAndInfo(sx, sy, totalHeight, label, infoText, alpha)
|
|
alpha = alpha or 1
|
|
local labelY = sy - (totalHeight * 0.5) - 0.02
|
|
local infoY = sy + (totalHeight * 0.5) + 0.005
|
|
|
|
if label and label ~= "" then
|
|
DrawSequenceText(sx, labelY, label, 0.18, 255, 255, 255, 255 * alpha, true, true)
|
|
end
|
|
if infoText and infoText ~= "" then
|
|
DrawSequenceText(sx, infoY, infoText, 0.15, 255, 255, 255, 255 * alpha, true, true)
|
|
end
|
|
end
|
|
|
|
local function DrawMinigameBoxes(sequence, pressedFlags, coords, currentIndex, hiddenMode, label, infoText)
|
|
local onScreen, sx, sy = GetScreenCoordFromWorldCoord(coords.x, coords.y, coords.z)
|
|
if not onScreen then return end
|
|
|
|
local boxW, boxH = 0.02, 0.03
|
|
local spacing = 0.002
|
|
local count = #sequence
|
|
local totalW = (count * boxW) + ((count - 1) * spacing)
|
|
local startX = sx - (totalW * 0.5)
|
|
|
|
for i, keyData in ipairs(sequence) do
|
|
local bx = startX + (i - 1) * (boxW + spacing)
|
|
|
|
local r, g, b = 0, 0, 0
|
|
if pressedFlags[i] then
|
|
r, g, b = 108, 240, 156
|
|
end
|
|
DrawSequenceRect(bx, sy - boxH / 2, boxW, boxH, r, g, b, 180)
|
|
|
|
local label = keyData.label
|
|
if hiddenMode and currentIndex > 1 and (not pressedFlags[i]) then
|
|
local scrambled = {'#', '?', '$', '%'}
|
|
label = scrambled[((math.floor(GetGameTimer() / 50) + i) % #scrambled) + 1]
|
|
end
|
|
|
|
local textX = bx + (boxW / 2)
|
|
local textY = sy - (boxH / 2) + 0.004
|
|
local textScale = 0.3 - (0.022 * #label)
|
|
if textScale < 0.18 then textScale = 0.18 end
|
|
DrawSequenceText(textX, textY, label, textScale, 255, 255, 255, 255, true)
|
|
end
|
|
|
|
DrawLabelAndInfo(sx, sy, boxH, label, infoText)
|
|
end
|
|
|
|
local function DrawFinalSequence(sequence, coords, colorMode, label, infoText, alpha)
|
|
local onScreen, sx, sy = GetScreenCoordFromWorldCoord(coords.x, coords.y, coords.z)
|
|
if not onScreen then return end
|
|
|
|
local boxW, boxH = 0.02, 0.03
|
|
local spacing = 0.002
|
|
local count = #sequence
|
|
local totalW = (count * boxW) + ((count - 1) * spacing)
|
|
local startX = sx - (totalW * 0.5)
|
|
|
|
local r, g, b = 108, 240, 156
|
|
if colorMode == 'red' then
|
|
r, g, b = 200, 50, 50
|
|
end
|
|
|
|
for i, keyData in ipairs(sequence) do
|
|
local bx = startX + (i - 1) * (boxW + spacing)
|
|
|
|
DrawSequenceRect(bx, sy - boxH / 2, boxW, boxH, r, g, b, 180 * alpha)
|
|
|
|
local label = keyData.label
|
|
local textX = bx + (boxW / 2)
|
|
local textY = sy - (boxH / 2) + 0.004
|
|
local textScale = 0.3 - (0.022 * #label)
|
|
if textScale < 0.18 then textScale = 0.18 end
|
|
|
|
DrawSequenceText(textX, textY, label, textScale, 255, 255, 255, 255 * alpha, true)
|
|
end
|
|
|
|
DrawLabelAndInfo(sx, sy, boxH, label, infoText, alpha)
|
|
end
|
|
|
|
local function DisablePlayerInput()
|
|
for group = 0, 2 do
|
|
DisableAllControlActions(group)
|
|
end
|
|
-- Re-enable camera look + zoom
|
|
EnableControlAction(0, 1, true) -- LookLeftRight
|
|
EnableControlAction(0, 2, true) -- LookUpDown
|
|
EnableControlAction(0, 241, true) -- MouseWheelUp (zoom)
|
|
EnableControlAction(0, 242, true) -- MouseWheelDown (zoom)
|
|
end
|
|
|
|
function SequenceMinigame(coords, length, hiddenMode, label, infoText)
|
|
local sequence = GenerateSequence(length)
|
|
local pressedFlags = {}
|
|
for i = 1, length do
|
|
pressedFlags[i] = false
|
|
end
|
|
|
|
local currentIndex = 1
|
|
local gameActive = true
|
|
local wasSuccess = false
|
|
|
|
while gameActive do
|
|
Citizen.Wait(0)
|
|
|
|
if IsRawKeyDown(0x1B) or IsRawKeyDown(0x08) then
|
|
return false
|
|
end
|
|
|
|
DisablePlayerInput()
|
|
|
|
DrawMinigameBoxes(sequence, pressedFlags, coords, currentIndex, hiddenMode, label, infoText)
|
|
|
|
local correctCode = sequence[currentIndex].code
|
|
|
|
if IsRawKeyReleased(correctCode) then
|
|
pressedFlags[currentIndex] = true
|
|
currentIndex = currentIndex + 1
|
|
if currentIndex > #sequence then
|
|
wasSuccess = true
|
|
gameActive = false
|
|
end
|
|
else
|
|
for _, keyData in ipairs(sequenceKeys) do
|
|
if IsRawKeyReleased(keyData.code) then
|
|
if keyData.code ~= correctCode then
|
|
wasSuccess = false
|
|
gameActive = false
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local endDuration, colorMode
|
|
if wasSuccess then
|
|
colorMode = 'green'
|
|
endDuration = 500
|
|
else
|
|
colorMode = 'red'
|
|
endDuration = 1000
|
|
end
|
|
|
|
local endTime = GetGameTimer() + endDuration
|
|
while GetGameTimer() < endTime do
|
|
Citizen.Wait(0)
|
|
DisablePlayerInput()
|
|
|
|
local alpha = math.max(0, (endTime - GetGameTimer()) / endDuration)
|
|
|
|
DrawFinalSequence(sequence, coords, colorMode, label, infoText, alpha)
|
|
end
|
|
|
|
return wasSuccess
|
|
end
|