script_name("SignCheck Reminder") script_author("Maku Kenesu") script_version("1.0") require "lib.moonloader" require "lib.sampfuncs" local sampev = require "lib.samp.events" local inicfg = require "inicfg" local CONFIG_DIR = getWorkingDirectory() .. "\\config\\" local CONFIG_FILE = CONFIG_DIR .. "SignCheckReminder.ini" local settings = inicfg.load({ settings = { posX = 0.02, posY = 0.5, sound = true } }, CONFIG_FILE) local FONT = renderCreateFont("Arial", 13, 5) local SCREEN_X, SCREEN_Y = getScreenResolution() local COLOR_WHITE = 0xFFFFFFFF local COLOR_GREEN = 0xFF00FF00 local COLOR_RED = 0xFFFF0000 local COLOR_LABEL = 0xFFADFF2F local COLOR_BG = 0x80000000 local PADDING_X, PADDING_Y = 10, 6 local LABEL = "[SignCheck Reminder] " local AUTHOR = "by Maku Kenesu" local isTextVisible = true local isSignActive = false local isRedAlert = false local isPaycheckReceived = false local isPaycheckExpired = false local isEditing = false local signEndTime, redEndTime, payEndTime, expireEndTime, nextSoundTime = 0, 0, 0, 0, 0 local blinkTimer, blinkState = 0, true -- for blinking /SIGNCHECK local function getPixelPosition() return settings.settings.posX * SCREEN_X, settings.settings.posY * SCREEN_Y end local function saveSettings() inicfg.save(settings, CONFIG_FILE) end local function sendChat(msg, color) sampAddChatMessage(string.format("{%06X}%s{FFFFFF}%s", bit.band(COLOR_LABEL, 0xFFFFFF), LABEL, msg), -1) end local function startSignTimer() isSignActive = true isRedAlert = false isPaycheckReceived = false isPaycheckExpired = false signEndTime = os.clock() + 300 nextSoundTime = os.clock() + 30 blinkTimer = os.clock() + 1 blinkState = true end local function stopSignTimer() isSignActive = false end local function startRedAlert() isRedAlert = true isSignActive = false isPaycheckReceived = false isPaycheckExpired = false redEndTime = os.clock() + 60 end local function startPaycheckReceived() isPaycheckReceived = true isSignActive = false isRedAlert = false isPaycheckExpired = false payEndTime = os.clock() + 60 end local function startPaycheckExpired() isPaycheckExpired = true isSignActive = false isRedAlert = false isPaycheckReceived = false expireEndTime = os.clock() + 60 end local function drawSignText(text, x, y, color) local width = renderGetFontDrawTextLength(FONT, text) local height = 20 local boxWidth = width + (PADDING_X * 2) local boxHeight = height + (PADDING_Y * 2) renderDrawBox(x, y, boxWidth, boxHeight, COLOR_BG) renderFontDrawText(FONT, text, x + PADDING_X, y + PADDING_Y, color) end local function togglePositionEdit() isEditing = not isEditing showCursor(isEditing) if isEditing then sendChat("Move mode enabled. Click top-left corner to set new position.", COLOR_LABEL) else sendChat("Move mode disabled.", COLOR_LABEL) end end local function handlePositionEdit() if wasKeyPressed(VK_LBUTTON) then local mouseX, mouseY = getCursorPos() settings.settings.posX = mouseX / SCREEN_X settings.settings.posY = mouseY / SCREEN_Y saveSettings() sendChat(string.format("New position saved (%.2f, %.2f).", settings.settings.posX, settings.settings.posY), COLOR_LABEL) togglePositionEdit() end end local function toggleSound() settings.settings.sound = not settings.settings.sound saveSettings() local state = settings.settings.sound and "enabled" or "disabled" sendChat("Sound alerts " .. state .. ".", COLOR_LABEL) end local function showHelp() sendChat("Available commands:", COLOR_LABEL) sampAddChatMessage("/sr.pos - Move the reminder text.", -1) sampAddChatMessage("/sr.sound - Toggle sound alerts.", -1) sampAddChatMessage("/sr.help - Show this help message.", -1) end function sampev.onServerMessage(_, text) if text:find("Sign the check to receive your paycheck.", 1, true) then startSignTimer() if settings.settings.sound then lua_thread.create(function() addOneOffSound(0.0, 0.0, 0.0, 1097) wait(3500) addOneOffSound(0.0, 0.0, 0.0, 1098) end) end elseif text:find("________ BANK STATEMENT ________", 1, true) then if settings.settings.sound then addOneOffSound(0.0, 0.0, 0.0, 1133) end stopSignTimer() startPaycheckReceived() elseif text:find("* You haven't played long enough to obtain a paycheck.", 1, true) then if settings.settings.sound then addOneOffSound(0.0, 0.0, 0.0, 1056) end startRedAlert() elseif text:find("Your paycheck code expired. Please remember to /signcheck next time.", 1, true) then if settings.settings.sound then addOneOffSound(0.0, 0.0, 0.0, 1056) end startPaycheckExpired() elseif text:find("You have one minute left before your paycheck code expires. Please type /signcheck to get your paycheck.", 1, true) then if settings.settings.sound then lua_thread.create(function() addOneOffSound(0.0, 0.0, 0.0, 1068) wait(3500) addOneOffSound(0.0, 0.0, 0.0, 1069) end) end end end function main() while not isSampAvailable() do wait(100) end sampAddChatMessage(string.format("{%06X}%s%s {FFFFFF}- Use /sr.help for commands.", bit.band(COLOR_LABEL, 0xFFFFFF), LABEL, AUTHOR), -1) sampRegisterChatCommand("sr.pos", togglePositionEdit) sampRegisterChatCommand("sr.sound", toggleSound) sampRegisterChatCommand("sr.help", showHelp) while true do wait(0) local now = os.clock() if isRedAlert and now > redEndTime then isRedAlert = false end if isSignActive and now > signEndTime then stopSignTimer() end if isPaycheckReceived and now > payEndTime then isPaycheckReceived = false end if isPaycheckExpired and now > expireEndTime then isPaycheckExpired = false end -- Blink logic if isSignActive and now >= blinkTimer then blinkState = not blinkState blinkTimer = now + 1 end if isSignActive and now >= nextSoundTime then if settings.settings.sound then addOneOffSound(0.0, 0.0, 0.0, 1057) end nextSoundTime = now + 60 end if isTextVisible then local posX, posY = getPixelPosition() local color, text = COLOR_WHITE, "No Check to Sign" if isSignActive then color = blinkState and COLOR_GREEN or COLOR_WHITE text = "/SIGNCHECK" elseif isRedAlert then color, text = COLOR_RED, "Missed Paycheck" elseif isPaycheckReceived then color, text = COLOR_GREEN, "Paycheck Received" elseif isPaycheckExpired then color, text = COLOR_RED, "Paycheck Expired" end drawSignText(text, posX, posY, color) end if isEditing then handlePositionEdit() end end end