J4cobLIVEmain Posted April 19 Share Posted April 19 Hey there! I told you before in some other post that I used Grok for scripting. He nearly pulled off a very nice Racing map panel. However there is a slight problem - when you buy the map, money goes away (money is inside the script too I think when you win a race it gives you certain amount) and map doesn't play or its not set. If you guys have any idea how can it be fixed, lmk. By the way, to get this kinda script you need around 2 hours on Grok for him to properly understand MTA scripting Codes: server.lua local moneyFile = "money.xml" local nextMapQueue = nil -- Store the next map if race resource isn't running -- Load player's money from XML function loadPlayerMoney(player) local serial = getPlayerSerial(player) local xml = xmlLoadFile(moneyFile) or xmlCreateFile(moneyFile, "money") if not xml then outputDebugString("Failed to load or create money.xml", 1) return end local node = xmlFindChild(xml, serial, 0) or xmlCreateChild(xml, serial) local money = tonumber(xmlNodeGetValue(node)) or 0 setElementData(player, "money", money) xmlSaveFile(xml) xmlUnloadFile(xml) end -- Save player's money to XML function savePlayerMoney(player) local serial = getPlayerSerial(player) local money = getElementData(player, "money") or 0 local xml = xmlLoadFile(moneyFile) or xmlCreateFile(moneyFile, "money") if not xml then outputDebugString("Failed to load or create money.xml", 1) return end local node = xmlFindChild(xml, serial, 0) or xmlCreateChild(xml, serial) xmlNodeSetValue(node, tostring(money)) xmlSaveFile(xml) xmlUnloadFile(xml) end -- Handle player join addEventHandler("onPlayerJoin", root, function() loadPlayerMoney(source) end) -- Handle player quit addEventHandler("onPlayerQuit", root, function() savePlayerMoney(source) end) -- Fetch all race map resources function getMapList() local mapList = {} local resources = getResources() if not resources then outputDebugString("Failed to get resources - check ACL permissions for 'function.getResources'!", 1) return mapList end local includedCount = 0 local excludedCount = 0 for i, resource in ipairs(resources) do local resName = getResourceName(resource) -- Skip system resources, our own resource, and known gamemodes if resName ~= "race_map_panel" and not resName:find("^%[") and resName ~= "csrw" and resName ~= "race" and resName ~= "play" and resName ~= "assault" and resName ~= "destructionderby" and resName ~= "ctf" and resName ~= "as-cliff" and resName ~= "ctf-goldcove" then local metaPath = ":" .. resName .. "/meta.xml" local metaFile = xmlLoadFile(metaPath) if metaFile then -- Check if the resource is a gamemode local infoNode = xmlFindChild(metaFile, "info", 0) local isGamemode = false if infoNode then local resType = xmlNodeGetAttribute(infoNode, "type") if resType and resType:lower() == "gamemode" then isGamemode = true excludedCount = excludedCount + 1 end end if not isGamemode then local isRaceMap = false local hasMapFile = false local gamemodesValue = nil -- Check for <map> element with a .map file local mapNode = xmlFindChild(metaFile, "map", 0) if mapNode then local mapSrc = xmlNodeGetAttribute(mapNode, "src") if mapSrc and mapSrc:find("%.map$") then hasMapFile = true end end -- Check for #gamemodes setting local settingsNode = xmlFindChild(metaFile, "settings", 0) if settingsNode then local settingNodes = xmlNodeGetChildren(settingsNode) for j, setting in ipairs(settingNodes) do local settingName = xmlNodeGetAttribute(setting, "name") local settingValue = xmlNodeGetAttribute(setting, "value") if settingName == "#gamemodes" then gamemodesValue = settingValue -- Parse the gamemodes value (e.g., '[ "race" ]' or '[ "race", "assault" ]') local gamemodes = settingValue:gsub("%[", ""):gsub("%]", ""):gsub('"', ""):gsub(" ", "") local gamemodeList = split(gamemodes, ",") if #gamemodeList == 1 and gamemodeList[1]:lower() == "race" then isRaceMap = true end break end end end -- If no #gamemodes setting, assume it's a race map if the name suggests it if hasMapFile and not gamemodesValue then if resName:find("^%[race%]") or resName:find("race-") then isRaceMap = true end end -- Include or exclude the map if hasMapFile and isRaceMap then includedCount = includedCount + 1 local mapInfo = { resourceName = resName, -- Store the actual resource name name = resName, -- Default to resource name author = "Unknown", cost = math.random(300, 1000) -- Random cost } if infoNode then local author = xmlNodeGetAttribute(infoNode, "author") local name = xmlNodeGetAttribute(infoNode, "name") if author then mapInfo.author = author end if name then mapInfo.name = name end end table.insert(mapList, mapInfo) else excludedCount = excludedCount + 1 end end xmlUnloadFile(metaFile) else excludedCount = excludedCount + 1 end else excludedCount = excludedCount + 1 end end outputDebugString("INFO: Total race maps found: " .. #mapList .. " (Included: " .. includedCount .. ", Excluded: " .. excludedCount .. ")", 3) return mapList end -- Send map list and player money to client addEvent("requestMapList", true) addEventHandler("requestMapList", root, function() local mapList = getMapList() local player = source local money = getElementData(player, "money") or 0 triggerClientEvent(player, "receiveMapList", player, mapList) triggerClientEvent(player, "receivePlayerMoney", player, money) end) -- Send player money to client addEvent("requestPlayerMoney", true) addEventHandler("requestPlayerMoney", root, function() local player = source local money = getElementData(player, "money") or 0 triggerClientEvent(player, "receivePlayerMoney", player, money) end) -- Function to set the next map function setNextMapIfPossible(mapResource, mapDisplayName, player) local raceResource = getResourceFromName("race") outputDebugString("DEBUG: Attempting to set next map to " .. getResourceName(mapResource) .. " for player " .. getPlayerName(player), 3) if raceResource and getResourceState(raceResource) == "running" then outputDebugString("DEBUG: Race resource is running, calling queueNextMap", 3) local success, errorMsg = pcall(function() return exports.race:queueNextMap(mapResource) -- Updated to queueNextMap end) if success and errorMsg then outputDebugString("DEBUG: Successfully queued next map to " .. getResourceName(mapResource) .. " for player " .. getPlayerName(player), 3) outputChatBox(getPlayerName(player) .. " has queued the next map to '" .. mapDisplayName .. "'!", root, 255, 255, 0) nextMapQueue = nil -- Clear the queue since the map was set return true else outputDebugString("DEBUG: Failed to queue next map to " .. getResourceName(mapResource) .. " - queueNextMap failed: " .. (errorMsg or "unknown error"), 1) outputChatBox("Failed to queue the next map (queueNextMap failed). Please try again.", player, 255, 0, 0) return false end else outputDebugString("DEBUG: Race resource not running (state: " .. (raceResource and getResourceState(raceResource) or "not found") .. "). Queuing map " .. getResourceName(mapResource), 1) nextMapQueue = { resource = mapResource, displayName = mapDisplayName, player = player } outputChatBox("Race gamemode not running. Your map '" .. mapDisplayName .. "' will be set as the next map when the gamemode starts.", player, 255, 255, 0) return false end end -- Handle map purchase and set as next map addEvent("onPlayerBuyMap", true) addEventHandler("onPlayerBuyMap", root, function(mapResourceName, mapDisplayName, cost) local player = source local money = getElementData(player, "money") or 0 if money >= cost then setElementData(player, "money", money - cost) savePlayerMoney(player) -- Set the purchased map as the next map local mapResource = getResourceFromName(mapResourceName) if mapResource then setNextMapIfPossible(mapResource, mapDisplayName, player) else outputDebugString("DEBUG: Map resource " .. mapResourceName .. " not found for player " .. getPlayerName(player), 1) outputChatBox("Map resource not found. Please try again.", player, 255, 0, 0) end triggerClientEvent(player, "onMapPurchaseSuccess", player, mapDisplayName) outputChatBox("You now have $" .. (money - cost), player, 0, 255, 0) else triggerClientEvent(player, "onMapPurchaseFail", player) end end) -- Try to set the queued map when the race gamemode starts addEventHandler("onResourceStart", root, function(startedResource) local resourceName = getResourceName(startedResource) if resourceName == "race" and nextMapQueue then outputDebugString("DEBUG: Race resource started. Attempting to set queued map " .. getResourceName(nextMapQueue.resource), 3) setNextMapIfPossible(nextMapQueue.resource, nextMapQueue.displayName, nextMapQueue.player) end end) -- Try to set the queued map when the current map ends addEvent("onRaceEnd", true) addEventHandler("onRaceEnd", root, function(winner) outputDebugString("DEBUG: onRaceEnd triggered with winner " .. getPlayerName(winner), 3) local player = winner local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) -- Try to set the queued map if it exists if nextMapQueue then outputDebugString("DEBUG: Race ended. Attempting to set queued map " .. getResourceName(nextMapQueue.resource), 3) setNextMapIfPossible(nextMapQueue.resource, nextMapQueue.displayName, nextMapQueue.player) end end) -- Handle race win detected by client addEvent("onClientPlayerRaceWin", true) addEventHandler("onClientPlayerRaceWin", root, function() outputDebugString("DEBUG: onClientPlayerRaceWin triggered for " .. getPlayerName(source), 3) local player = source local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end) -- Hook into possible race gamemode events (for debugging) addEvent("onPlayerFinish", true) addEventHandler("onPlayerFinish", root, function(rank) outputDebugString("DEBUG: onPlayerFinish triggered for " .. getPlayerName(source) .. " with rank " .. rank, 3) if rank == 1 then local player = source local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end end) addEvent("onPlayerWin", true) addEventHandler("onPlayerWin", root, function() outputDebugString("DEBUG: onPlayerWin triggered for " .. getPlayerName(source), 3) local player = source local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end) addEvent("onPlayerRaceFinish", true) addEventHandler("onPlayerRaceFinish", root, function(rank) outputDebugString("DEBUG: onPlayerRaceFinish triggered for " .. getPlayerName(source) .. " with rank " .. rank, 3) if rank == 1 then local player = source local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end end) addEvent("onPlayerVictory", true) addEventHandler("onPlayerVictory", root, function() outputDebugString("DEBUG: onPlayerVictory triggered for " .. getPlayerName(source), 3) local player = source local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end) addEvent("onPlayerWinDD", true) addEventHandler("onPlayerWinDD", root, function() outputDebugString("DEBUG: onPlayerWinDD triggered for " .. getPlayerName(source), 3) local player = source local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end) -- Debug command to simulate a race win (admin only) addCommandHandler("winrace", function(player) if not hasObjectPermissionTo(player, "general.adminpanel") then outputChatBox("You do not have permission to use this command!", player, 255, 0, 0) return end outputDebugString("DEBUG: Simulating race win for " .. getPlayerName(player), 3) local money = getElementData(player, "money") or 0 local reward = 1000 setElementData(player, "money", money + reward) savePlayerMoney(player) outputChatBox("You won the race and earned $" .. reward .. "! Total: $" .. (money + reward), player, 0, 255, 0) triggerClientEvent(player, "receivePlayerMoney", player, money + reward) end) -- Debug command to check money addCommandHandler("money", function(player) local money = getElementData(player, "money") or 0 outputChatBox("Your money: $" .. money, player, 255, 255, 0) end) client.lua local screenW, screenH = guiGetScreenSize() local mapPanelVisible = false local selectedMap = nil local maps = {} local playerMoney = 0 -- Create the map panel GUI function createMapPanel() if mapPanelVisible then return end mapPanelWindow = guiCreateWindow((screenW - 400) / 2, (screenH - 300) / 2, 400, 300, "Map Panel", false) guiWindowSetSizable(mapPanelWindow, false) mapGrid = guiCreateGridList(10, 30, 380, 150, false, mapPanelWindow) guiGridListAddColumn(mapGrid, "Map Name", 0.5) guiGridListAddColumn(mapGrid, "Author", 0.3) guiGridListAddColumn(mapGrid, "Cost", 0.2) for i, map in ipairs(maps) do local row = guiGridListAddRow(mapGrid) guiGridListSetItemText(mapGrid, row, 1, map.name, false, false) guiGridListSetItemText(mapGrid, row, 2, map.author or "Unknown", false, false) guiGridListSetItemText(mapGrid, row, 3, tostring(map.cost), false, false) end moneyLabel = guiCreateLabel(10, 190, 380, 20, "Your Money: $" .. playerMoney, false, mapPanelWindow) infoLabel = guiCreateLabel(10, 210, 380, 20, "Select a map to see details.", false, mapPanelWindow) buyButton = guiCreateButton(10, 230, 180, 30, "Buy Map", false, mapPanelWindow) quitButton = guiCreateButton(200, 230, 180, 30, "Quit", false, mapPanelWindow) addEventHandler("onClientGUIClick", mapGrid, onMapSelect, false) addEventHandler("onClientGUIClick", buyButton, buyMap, false) addEventHandler("onClientGUIClick", quitButton, closeMapPanel, false) mapPanelVisible = true showCursor(true) -- Show the cursor when the panel opens if #maps == 0 then outputChatBox("No maps found on the server!", 255, 0, 0) end end -- Handle map selection function onMapSelect() local row = guiGridListGetSelectedItem(mapGrid) if row ~= -1 then selectedMap = maps[row + 1] guiSetText(infoLabel, "Name: " .. selectedMap.name .. " | Author: " .. (selectedMap.author or "Unknown") .. " | Cost: $" .. selectedMap.cost) end end -- Buy the selected map function buyMap() if not selectedMap then outputChatBox("Please select a map first!", 255, 0, 0) return end triggerServerEvent("onPlayerBuyMap", localPlayer, selectedMap.resourceName, selectedMap.name, selectedMap.cost) end -- Close the panel function closeMapPanel() if mapPanelWindow then destroyElement(mapPanelWindow) mapPanelVisible = false selectedMap = nil showCursor(false) -- Hide the cursor when the panel closes end end -- Toggle the map panel with F3 addEventHandler("onClientResourceStart", resourceRoot, function() bindKey("f3", "down", function() if mapPanelVisible then closeMapPanel() else triggerServerEvent("requestMapList", localPlayer) end end) setTimer(function() outputChatBox("Press F3 to open the Map Panel!", 255, 255, 0) end, 5000, 1) end) -- Receive map list from server addEvent("receiveMapList", true) addEventHandler("receiveMapList", root, function(mapList) maps = mapList outputChatBox("Received " .. #maps .. " maps from server.", 0, 255, 0) createMapPanel() end) -- Receive player money from server addEvent("receivePlayerMoney", true) addEventHandler("receivePlayerMoney", root, function(money) playerMoney = money if moneyLabel and isElement(moneyLabel) then guiSetText(moneyLabel, "Your Money: $" .. playerMoney) end end) -- Handle successful purchase response from server addEvent("onMapPurchaseSuccess", true) addEventHandler("onMapPurchaseSuccess", root, function(mapDisplayName) outputChatBox("Map '" .. mapDisplayName .. "' purchased successfully and set as the next map!", 0, 255, 0) triggerServerEvent("requestPlayerMoney", localPlayer) closeMapPanel() end) -- Handle insufficient funds addEvent("onMapPurchaseFail", true) addEventHandler("onMapPurchaseFail", root, function() outputChatBox("Not enough money to buy this map!", 255, 0, 0) end) -- Detect "You have won the race!" message addEventHandler("onClientChatMessage", root, function(message) if message == "You have won the race!" then triggerServerEvent("onClientPlayerRaceWin", localPlayer) end end) It also creates money.xml which stores money, and I tried AI to understand that I wanted to pick up the money from the users account (when you add it via admin panel for example) but I couldn't. I'm also wondering if you guys could make this script better anyhow? I recommend debugscript 3 too Thanks for any help. Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now