Jump to content

myonlake

Members
  • Posts

    2,312
  • Joined

  • Days Won

    40

Everything posted by myonlake

  1. Make sure to add the following line to your meta.xml. <oop>true</oop>
  2. Your acceptHeal function is missing the player argument. Add it in the parentheses.
  3. There is no problem using element data. Just try to limit the amount of data you have laying around if you don't really need it. This goes to both methods, tables or element data, limit the amount of data where possible! Just one security related thing to element data though, you need to make sure you don't allow changing element data if it wasn't done by the server. You can read more on how here: https://wiki.multitheftauto.com/wiki/Script_security#Validating_client_setElementData I usually just carry an ID on elements that have an entry in the database so I can fetch/save data from/to a database for that specific element. Some data that you will be accessing a lot is better to have cached in element data or tables rather than always make a database query when you need it, but this depends on how you edit data. If you for example edit data through the database or a control panel somewhere, the data might get out of sync with what is stored in a table or element data. So it depends on your situation, really. I'd go with element data, but keep in mind script security as I linked above. Also to keep in mind, is if you store things in a table, all of that data will be lost upon resource restart, whereas element data will stay if the element is not deleted by the stopping resource or something else. This I think is one of the good sides about element data.
  4. So what exactly is the problem?
  5. getVehicleComponentPosition and setVehicleComponentPosition are client-side functions, this code must be run client-side, obviously.
  6. Your indentation is completely messed up. Also, there's no component with the name of movspoiler_24.0_5200, but I guess you know what you're doing. Also, note that theVeh has not been defined. If you want the current vehicle, add getPedOccupiedVehicle. function spoilernyit( ) if getElementModel( theVeh ) == 502 then local sX, sY, sZ = getVehicleComponentPosition( theVeh, "movspoiler_24.0_5200" ) if sZ < 0.6 then setVehicleComponentPosition( theVeh, "movspoiler_24.0_5200", sX, sY - 0.004, sZ + 0.005 ) elseif sZ > 0.45 then setVehicleComponentPosition( theVeh, "movspoiler_24.0_5200", sX, sY + 0.008, sZ - 0.01 ) end end end bindKey( "num_5", "down", spoilernyit ) -- Removed thePlayer, since you don't have that on client-side
  7. Show us your code so we can help you with the issue.
  8. You can use triggerClientEvent for that specific player you want to open the panel for.
  9. Some notes: You are using onClientRender for no reason. I removed it. You should set guiSetVisible after you create the window element instead. You mistyped showCursor as showCurson. You used not guiSetVisible, even though it should be not guiGetVisible. You were using mission[1] in guiGetVisible, but what you're looking for is just mission, since it's not a table, it's a GUI window element. You had an unnecessary GUI button (probably made by accident), so I removed it. You had an unnecessary GUI gridlist (probably also made by accident), so I removed it. I suggest using /debugscript 3 in the future to help you nail down these errors. GUIEditor = { gridlist = {}, button = {} } addEventHandler("onClientResourceStart", resourceRoot, function() mission = guiCreateWindow(596, 264, 204, 247, "Zombie Mission", false) guiWindowSetSizable(mission, true) guiSetVisible(mission, false) GUIEditor.button[1] = guiCreateButton(10, 22, 184, 15, "\"MISSIONS\"", false, mission) GUIEditor.button[2] = guiCreateButton(9, 214, 92, 18, "TAKE", false, mission) GUIEditor.button[3] = guiCreateButton(106, 214, 88, 18, "EXIT", false, mission) GUIEditor.gridlist[1] = guiCreateGridList(10, 39, 184, 168, false, mission) guiGridListAddColumn(GUIEditor.gridlist[1], "Mission", 0.9) for i = 1, 9 do guiGridListAddRow(GUIEditor.gridlist[1]) end guiGridListSetItemText(GUIEditor.gridlist[1], 0, 1, "Kill 1 boss RED", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 1, 1, "Kill 1 boss yellow", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 2, 1, "Kill 2 boss RED", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 3, 1, "Kill 2 boss yellow", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 4, 1, "Kill 3 boss RED", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 5, 1, "Kill 3 boss yellow", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 6, 1, "Kill 300 zombies", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 7, 1, "Kill 600 zombies", false, false) guiGridListSetItemText(GUIEditor.gridlist[1], 8, 1, "Kill 900 zombies", false, false) end ) bindKey("U", "down", function() local visibility = not guiGetVisible(mission) guiSetVisible(mission, visibility) showCursor(visibility) end)
  10. You don't seem to be using the right database details in your snippet. local host = "hotstname..." local username = "username..." local password = "password..." local db = "db_name" local connection = dbConnect("mysql", "dbname=" .. db .. ";host=" .. host, username, password) if (connection) then local qh = dbQuery(connection, "SELECT * FROM `asd` WHERE `ID` = ?", 1) if (qh) then local result = dbPoll(qh, -1) if (result) then for _, row in ipairs(result) do local id = tonumber(row["ID"]) local playerName = tostring(row["PlayerName"]) local playerPassword = tostring(row["PlayerPassword"]) local PlayerMoney = tonumber(row["PlayerMoney"]) end end end end
  11. Here's some notes: In the snippet you provided you are missing the gangs table that should contain window and label tables in it to store the GUI elements you are creating. All of your GUI elements are using relative positioning, but your coordinates are absolute. This means your elements are 540% from the left and 636% from the top. They are off-screen. I disabled relative positioning and now you can see them on the screen. Keep in mind that absolute positioning can introduce problems like small screen size not being able to see elements positioned outside of the screen bounds. I suggest centering your GUI window using guiGetScreenSize. You are passing the inviter through as an argument to the gang.invite event. I prefer sending it over as the source, as they might as well just act as the source since you don't need any other data at the moment in place of that. Feel free to turn it back to the old way if you prefer it that way. You are also passing the team name to the client, rather than the team element. While I understand why that would be useful to some way mitigate potential team rename exploiting, I still believe going with the actual team element is better since that is what you were invited to join at the end of the day. You can handle potential bad behavior separate from this script. When you run triggerServerEvent, you are giving it only one argument, a boolean. However, the server-side function expects inviter and gang_name. Your InviteToGang server-side function is missing an end. Your onPlayerRespondedToInvite server-side event is missing, you only have an event handler, but you haven't actually added the event first. You should be using root for the event handler. You're mixing MTA and Lua OOP with functional style, I suggest choosing one style so your code is consistent. Because of safety reasons and circumstances allow it, you can and should use client instead of source server-side. You are trying to set the player to a team using just the team name. However, you need a team element for the setPlayerTeam function. Use getTeamFromName to retrieve the team element, or just use the team element the client has sent to the server. You are missing the r, g, b, teamS, teamT variables in the snippet you provided. I suggest binding this data to the team element instead using element data or some other storage, since this data is to the best of my knowledge team-specific, correct? Otherwise you just need to define those variables, if you haven't already. You are trying to set the player name using their current player name and a tag prefixing it. However, if the player is already in a team, their current name will include that as well. I suggest using element data or some other form of storage to save the player's original player name upon joining the server and then using that to set their name later. Now... this whole system has a few security related issues which are sort of easy to handle. I would send info of the transaction that they are signed to do, like we do now (team, inviter), and then use that data server-side to confirm that they are in fact doing what they are supposed to, and not trying to join a team they were not requested to join, since right now a hacker would technically be able to exploit that by sending a different team to the server, and it would believe it since there is nothing to confirm it. For now I think this will work for you fine, but perhaps something for you to do, is to improve the security. It's not hard; in fact, you can just use tables to save these transactions before sending them to the client and compare this data to what the client sends the server. I just don't want to write everything for you, so that's your next challenge if you're up for it. For your question regarding the 0-255 limit, Dimos7 provided you with a good answer. Use onClientGUIChanged and perhaps a couple other GUI events to determine when the edit box has changed. Then compare the value with your limit. Also, I suggest using /debugscript 3 in-game to see syntax errors in your script... Anyway, here's the whole thing commented below. Client-side -- Initialize the gangs table with window and label tables that contain our GUI elements local gangs = { window = { }, label = { } } addEvent( "gang.invite", true ) addEventHandler( "gang.invite", root, function( team ) -- If we already have an invite window open, or team doesn't exist, stop here if isElement( gangs.window["invite"] ) or not isElement( team ) then return end -- Save our inviter and team to the gangs table gangs.inviter = source gangs.team = team -- Note that I changed "true" to "false" for absolute positioning on all of the GUI elements gangs.window["invite"] = guiCreateWindow( 540, 636, 285, 91, "GANG INVITE", false ) guiWindowSetSizable( gangs.window["invite"], false ) guiSetAlpha( gangs.window["invite"], 0.72 ) gangs.label["invite"] = guiCreateLabel( 176, 64, 101, 18, "Press 'N' to reject", false, gangs.window["invite"] ) guiLabelSetHorizontalAlign( gangs.label["invite"], "center", false ) -- Use team:getName( ) to get the name of the team element, instead of using team name directly gangs.label["invite1"] = guiCreateLabel( 10, 17, 267, 21, source:getName( ) .. " has invited you to the gang '" .. team:getName( ) .. "'", false, gangs.window["invite"] ) guiLabelSetHorizontalAlign( gangs.label["invite1"], "center", false ) gangs.label["invite2"] = guiCreateLabel( 10, 64, 113, 18, "Press 'J' to accept", false, gangs.window["invite"] ) guiLabelSetHorizontalAlign( gangs.label["invite2"], "center", false ) bindKey( "J", "down", respondInvite ) bindKey( "N", "down", respondInvite ) end ) function respondInvite( key ) -- If we want to accept the invite and the team still exists... if key == "j" and isElement( gangs.team ) then triggerServerEvent( "onPlayerRespondedToInvite", localPlayer, true, gangs.inviter, gangs.team ) -- We don't want to accept the invite elseif key == "n" then triggerServerEvent( "onPlayerRespondedToInvite", localPlayer, false, gangs.inviter, gangs.team ) -- The team doesn't exist anymore elseif not isElement( gangs.team ) then outputChatBox( "This gang does not exist anymore.", 255, 0, 0 ) end if isElement( gangs.window["invite"] ) then gangs.window["invite"]:destroy( ) end -- Let's clean our inviter and team from the gangs table gangs.inviter = nil gangs.team = nil unbindKey( "J", "down", respondInvite ) unbindKey( "N", "down", respondInvite ) end Server-side -- Let's define a new getTag method for Team elements, which uses element data "tag" function Team:getTag( ) return self:getData( "tag" ) end -- Let's define a new getSkin method for Team elements, which uses element data "skin" function Team:getSkin( ) return self:getData( "skin" ) end -- Let's define a new getOriginalName method for Player elements, which uses element data "name" function Player:getOriginalName( ) return self:getData( "name" ) end -- Let's save MTA's original setTeam method as _setTeam Player._setTeam = Player.setTeam -- Let's create a wrapper function for setTeam so we can do all of our operations in one go -- You can also ignore the custom part by providing "true" to the second argument like so: setTeam( theTeam, true ) function Player:setTeam( team, ignoreCustom ) -- Set our team using MTA's setTeam method first self:_setTeam( team ) -- If the team provided is an element and we are not ignoring custom code if isElement( team ) and ignoreCustom ~= true then -- Set our nametag color according to the team color (you can use setColor( r, g, b ) to set it ) self:setNametagColor( team:getColor( ) ) -- Get our team skin local skin = team:getSkin( ) -- If we have a team skin, set it, otherwise clear it using a default skin ID (here it is set to 0) self:setModel( tonumber( skin ) or 0 ) -- Get our team tag local tag = team:getTag( ) -- If we have a team tag, let's set it, otherwise use their original player name if tag and #tag > 0 then self:setName( "[" .. tag .. "]" .. self:getOriginalName( ) ) else self:setName( self:getOriginalName( ) ) end end end -- When a player joins the server addEventHandler( "onPlayerJoin", root, function( ) -- Save their name to element data "name" to use later source:setData( "name", source:getName( ), false ) end ) -- Let's create a Player method for inviting a player to a team function Player:inviteToTeam( team, inviter ) -- If the team exists if isElement( team ) then -- Let's trigger that client event for this player return triggerClientEvent( self, "gang.invite", inviter or self, team ) end return false end -- Let's take in our wasAccepted boolean, inviter and team function InviteToGang( wasAccepted, inviter, team ) -- If we have a team element if isElement( team ) then -- If the invitation was accepted if wasAccepted then -- Set the player's team client:setTeam( team ) -- Let the player know outputChatBox( "You accepted the gang invitation.", client, 0, 255, 0 ) -- If the invitation was not accepted else -- Let the player know outputChatBox( "You ignored the gang invitation.", client, 255, 0, 0 ) end elseif wasAccepted then -- If the invite was accepted but we had no team element, let's say we don't have that team anymore outputChatBox( "This gang does not exist.", client, 255, 0, 0 ) end end -- Add the onPlayerRespondedToInvite event first addEvent( "onPlayerRespondedToInvite", true ) addEventHandler( "onPlayerRespondedToInvite", root, InviteToGang ) Tested and working using the following script: local teamName, teamSkin, teamTag = "TestTeam", 1, "ASD" addEventHandler("onResourceStart", resourceRoot, function() local team = Team.getFromName(teamName) if not team then team = Team.create(teamName) if team then team:setData("skin", teamSkin) team:setData("tag", teamTag) end end end) addCommandHandler("inviteme", function(player) player:inviteToTeam(Team.getFromName(teamName), player) outputChatBox("invite sent", player) end) addCommandHandler("deletemyteam", function(player) local team = player:getTeam() if isElement(team) then team:destroy() outputChatBox("team destroyed", player) end end)
  12. Maybe the user you used to connect doesn't have SELECT privileges.
  13. I know, I have a feeling either the admin resource or scoreboard resource is outdated for him. Flags shouldn't be in the scoreboard resource anyway.
  14. myonlake

    Weapons skill

    You can for example use setPedStat on the onPlayerSpawn event. Weapon skill level information can be found here: https://wiki.multitheftauto.com/wiki/Weapon_skill_levels
  15. This is not a request forum. Do something for once yourself, please.
  16. Comment line 84 by adding two dashes in front of it "--". You can also delete the line...
  17. You can use bindKey to bind a key to toggle it on and off with guiSetVisible.
  18. Return will return the value after it to the caller. In this case your "return ... end" actually just stopped executing the rest of the code. if (1 == 1) then return end print "This will never get triggered." An example of how return can be used... local function getAge(name) if (name == "John") then return 30 elseif (name == "Jane") then return 31 end end print("John's age is " .. (getAge "John")) -- Will print John's age is 30 print("Jane's age is " .. (getAge "Jane")) -- Will print Jane's age is 31 print("Jack's age is " .. (getAge "Jack" or "unknown")) -- Will print Jack's age is unknown
  19. If you want to hide the race logo, then in race/race_client.lua file, comment line 84: --g_GUI['titleImage'] = guiCreateStaticImage(screenWidth/2-256, screenHeight/2-256+adjustY, 512, 512, 'img/title.png', false)
  20. If you want the players to see it every time a map starts, then the following could work: -- Let's get our screen dimensions local screenWidth, screenHeight = guiGetScreenSize() -- Save the static image into serverLogo, and the server logo timer into serverLogoTimer local serverLogo, serverLogoTimer -- Whenever onClientMapStarting is triggered by mapmanager, execute the function addEventHandler("onClientMapStarting", root, function() -- If we already have a valid server logo timer, let's kill it if (isTimer(serverLogoTimer)) then killTimer(serverLogoTimer) end -- If we already have a server logo element, let's destroy it if (isElement(serverLogo)) then destroyElement(serverLogo) end -- Let's create a static image element into serverLogo serverLogo = guiCreateStaticImage(0, 0, 0, 0, "hello.png", false) -- Let's get the native image size local serverLogoWidth, serverLogoHeight = guiStaticImageGetNativeSize(serverLogo) -- Let's center the image guiSetPosition(serverLogo, (screenWidth - serverLogoWidth) / 2, (screenHeight - serverLogoHeight) / 2, false) guiSetSize(serverLogo, serverLogoWidth, serverLogoHeight, false) -- Let's destroy the logo in 7000 ms (7 seconds) serverLogoTimer = setTimer(destroyElement, 7000, 1, serverLogo) end)
  21. If you only want the player to see it once, then this could work: -- Whenever onClientMapStarting is triggered by mapmanager, execute the function addEventHandler("onClientMapStarting", root, function() -- If the local player has already seen the server logo once, let's not show it again if (getElementData(localPlayer, "hasSeenServerLogo")) then return end -- Let's get our screen dimensions local screenWidth, screenHeight = guiGetScreenSize() -- Let's create a static image element into serverLogo local serverLogo = guiCreateStaticImage(0, 0, 0, 0, "hello.png", false) -- Let's get the native image size local serverLogoWidth, serverLogoHeight = guiStaticImageGetNativeSize(serverLogo) -- Let's center the image guiSetPosition(serverLogo, (screenWidth - serverLogoWidth) / 2, (screenHeight - serverLogoHeight) / 2, false) guiSetSize(serverLogo, serverLogoWidth, serverLogoHeight, false) -- Let's destroy the logo in 7000 ms (7 seconds) setTimer(destroyElement, 7000, 1, serverLogo) -- Let's give the local player hasSeenServerLogo data so they won't see it again setElementData(localPlayer, "hasSeenServerLogo", true) end)
  22. The reason why it doesn't work is because you are essentially passing 1 integer value to the tocolor function, hence printing out a black image. You need to either pass in all RGBA values as their own variables, or use tocolor in the variable value itself like so: function dx_() -- You were passing only the first 255 to col_1 col_1 = tocolor(255, 255, 255, 190) -- You were passing only the first 255 to col_2 col_2 = tocolor(255, 255, 255, 255) -- You were passing only the first 0 to ret_1 ret_1 = tocolor(0, 0, 0, 190) -- You were passing only the first 0 to ret_2 ret_2 = tocolor(0, 0, 0, 255) if not info and not give then if isMouseInPosition(329, 336, 387, 87) then bt_1 = col_2 else bt_1 = col_1 end dxDrawImage(201, 279, 512, 208, "button.png", 0, 0, 0, tocolor(0, 0, 0, 255)) dxDrawImage(207, 278, 512, 208, "button.png", 0, 0, 0, bt_1) -- Use bt_1 as a converted color value now dxDrawText("Some text", 388, 348, 696, 402, tocolor(0, 0, 0, 255), 1.4, "pricedown", "center", "center") end end If you wanted to pass them as their own variables then it would be like the following: -- Put them in variables col_1_r, col_1_g, col_1_b, col_1_a = 255, 255, 255, 190 -- Now to use tocolor you'd pass them in separately col_1 = tocolor(col_1_r, col_1_g, col_1_b, col_1_a)
×
×
  • Create New...