-
Posts
730 -
Joined
-
Last visited
-
Days Won
2
Everything posted by koragg
-
As some of you know I'm working on a resource which makes spectating the vehicle created from the race_ghost resource possible. I wanted to create markers on the spots where checkpoints would be so that it seems more like spectating a normal player rather than an object. And I have this problem: The createMarker() function ignores the 'size' attribute on maps which were converted with the batch converter from the old MTA format to the newer one. Here is that part of code: client-side local checkpoints = {} local CPMarker = {} addEvent("onClientMapStarting", true) function onClientMapStarting() checkpoints = getAll("checkpoint") addEventHandler("onClientMapStarting", root, onClientMapStarting) ------------------------------------------------------------------------------------------------------------------------- function checkAndFixTabData() if checkpoints and #checkpoints > 0 then for i = 1, #checkpoints do local color = { 255, 255, 255, 128 } local CPposX, CPposY, CPposZ = unpack(checkpoints[i].position) if not isElement(CPMarker[i]) then CPMarker[i] = createMarker(CPposX, CPposY, CPposZ, checkpoints[i].type, checkpoints[i].size, color[1], color[2], color[3], color[4]) end end end end addEventHandler("onClientRender", root, checkAndFixTabData) ------------------------------------------------------------------------------------------------------------------------- function getAll(name) local result = {} for i,element in ipairs(getElementsByType(name)) do result[i] = {} result[i].id = getElementID(element) or i local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) } local rotation = 0 if getElementData(element,"rotation") then rotation = tonumber(getElementData(element,"rotation")) elseif getElementData(element,"rotZ") then rotation = tonumber(getElementData(element,"rotZ")) else rotation = 0 end local vehicle = tonumber(getElementData(element,"vehicle")) local size if getElementData(element,"size") then size = tonumber(getElementData(element,"size")) else size = 3.0 end local type if getElementData(element,"type") then type = tostring(getElementData(element,"type")) else type = "checkpoint" end result[i].position = position; result[i].rotation = rotation; result[i].vehicle = vehicle; result[i].size = size; result[i].type = type; result[i].element = element; end return result end I tried to make the 'size' a number with 'tonumber' but it still didn't work. I tried to round it up to an integer (although wiki says that it can be a float as well) - no change. I tried to get the 'size' attribute via searching the map's .map file = not working, same as before. When I output the 'size' in the chatbox it shows up as a number. There are no errors in debug whatsoever. Everything seems perfect yet the marker size is not the same size as the size of the checkpoint that's supposed to be there (checkpoints.size). And all of this happens on maps which were converted from a very old MTA map format to a newer one via the race wiki's batch converter. Maps made on the new MTA editor work fine - marker gets created and the size is the one that the checkpoint has in the .map file. Another note: both formats have the exact same way of indicating the checkpoint's size in the .map file. They use an attribute 'size' in an identical way, yet createMarker() ignores the value of 'size' on converted maps while it works fine on maps made on new editor. Below are examples of old and new .map format so you see that the attribute is the same in both formats: old format: <?xml version="1.0" encoding="utf-16"?> <map mod="deathmatch"> <checkpoint posX="2343.127930" posY="267.152954" posZ="25.335938" size="3.950000" color="#7bd465" id="checkpoint4" nextid="checkpoint5" /> </map> new format: <map edf:definitions="race,editor_main"> <checkpoint id="checkpoint () (5)" type="checkpoint" color="#F56D0999" size="10" alpha="255" interior="0" nextid="checkpoint () (6)" posX="-2204.84253" posY="508.3909" posZ="34.054" rotX="0" rotY="0" rotZ="0"></checkpoint> </map> All other attributes work perfect and marker gets created on the checkpoint's spot on both map formats, just the 'size' is ignored on older ones. HELP! This is driving me nuts because there're no errors or anything and the code does indeed work on new maps, so why not on converted old ones as well?!? Here's the other way I tried (via xmlLoadFile, etc)...not that it made a difference: server-side function onMapStarting(mapInfo) local mapRes = mapInfo.resname local mapMetaFile = xmlLoadFile(":"..mapRes.."/meta.xml") local mapMapAttribute local mapMapNode local mapFileName if mapMetaFile then mapMapAttribute = xmlFindChild(mapMetaFile, "map", 0) end if mapMapAttribute then mapMapNode = xmlNodeGetAttributes(mapMapAttribute) end if mapMapNode then for name, value in pairs(mapMapNode) do mapFileName = value end end if mapMetaFile then xmlUnloadFile(mapMetaFile) end if mapFileName then local mapFile = xmlLoadFile(":"..mapRes.."/"..mapFileName.."") local totalCPs = getAll("checkpoint") local checkpointsAttribute = {} local mapCPsNode = {} local CPsize = {} if mapFile then for i = 1, #totalCPs do checkpointsAttribute[i] = xmlFindChild(mapFile, "checkpoint", 0) if checkpointsAttribute[i] then mapCPsNode[i] = xmlNodeGetAttributes(checkpointsAttribute[i]) end if mapCPsNode[i] then for name, value in pairs(mapCPsNode[i]) do if name == "size" then CPsize[i] = tonumber(round(value)) end end end end triggerClientEvent(root, "getCPSizes", resourceRoot, CPsize) end end if mapFile then xmlUnloadFile(mapFile) end end addEventHandler("onMapStarting", root, onMapStarting) ------------------------------------------------------------------------------------------------------------------------- function getAll(name) local result = {} for i,element in ipairs(getElementsByType(name)) do result[i] = {} result[i].id = getElementID(element) or i local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) } local rotation = 0 if getElementData(element,"rotation") then rotation = tonumber(getElementData(element,"rotation")) elseif getElementData(element,"rotZ") then rotation = tonumber(getElementData(element,"rotZ")) else rotation = 0 end local vehicle = tonumber(getElementData(element,"vehicle")) local size if getElementData(element,"size") then size = tonumber(getElementData(element,"size")) else size = 3.0 end local type if getElementData(element,"type") then type = tostring(getElementData(element,"type")) else type = "checkpoint" end result[i].position = position; result[i].rotation = rotation; result[i].vehicle = vehicle; result[i].size = size; result[i].type = type; result[i].element = element; end return result end ------------------------------------------------------------------------------------------------------------------------- --http://lua-users.org/wiki/FormattingNumbers function round(val, decimal) if (decimal) then return math.floor( (val * 10^decimal) + 0.5) / (10^decimal) else return math.floor(val+0.5) end end client-side local checkpoints = {} local CPMarker = {} local CPsizes = {} ------------------------------------------------------------------------------------------------------------------------- addEvent("getCPSizes", true) function getCPSizes(checkpointSizes) CPsizes = checkpointSizes end addEventHandler("getCPSizes", root, getCPSizes) ------------------------------------------------------------------------------------------------------------------------- addEvent("onClientMapStarting", true) checkpoints = getAll("checkpoint") addEventHandler("onClientMapStarting", root, onClientMapStarting) ------------------------------------------------------------------------------------------------------------------------- function checkAndFixTabData() if checkpoints and #checkpoints > 0 then for i = 1, #checkpoints do local color = { 255, 255, 255, 128 } local CPposX, CPposY, CPposZ = unpack(checkpoints[i].position) if not isElement(CPMarker[i]) then CPMarker[i] = createMarker(CPposX, CPposY, CPposZ, checkpoints[i].type, tonumber(round(CPsizes[i])), color[1], color[2], color[3], color[4]) end end end end addEventHandler("onClientRender", root, checkAndFixTabData) ------------------------------------------------------------------------------------------------------------------------ function getAll(name) local result = {} for i,element in ipairs(getElementsByType(name)) do result[i] = {} result[i].id = getElementID(element) or i local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) } local rotation = 0 if getElementData(element,"rotation") then rotation = tonumber(getElementData(element,"rotation")) elseif getElementData(element,"rotZ") then rotation = tonumber(getElementData(element,"rotZ")) else rotation = 0 end local vehicle = tonumber(getElementData(element,"vehicle")) local size if getElementData(element,"size") then size = tonumber(getElementData(element,"size")) else size = 3.0 end local type if getElementData(element,"type") then type = tostring(getElementData(element,"type")) else type = "checkpoint" end result[i].position = position; result[i].rotation = rotation; result[i].vehicle = vehicle; result[i].size = size; result[i].type = type; result[i].element = element; end return result end ------------------------------------------------------------------------------------------------------------------------- --http://lua-users.org/wiki/FormattingNumbers function round(val, decimal) if (decimal) then return math.floor( (val * 10^decimal) + 0.5) / (10^decimal) else return math.floor(val+0.5) end end Nothing I try works. Out of any sort of ideas for this.
-
While we're at it. What about putting 'local' before my functions? Is that better than having them without it? I want to optimize my server a bit because maybe less powerful computers than mine could lag sometimes there at the moment.
-
I like the newly added functions. Good job as always, thanks for the early Christmas present
- 13 replies
-
- mtasa
- legacy build
- (and 6 more)
-
OK then, will update some files soon. Thanks for the info (you always explain things really well ).
-
Hello, @LosFaul recently told me that using this: local player = getElementsByType("player") for i = 1, #player do ... end is better than using this: for i, player in ipairs(getElementsByType("player")) do ... end Are there any huge benefits to using the first over the second method? Most of my scripts are made with the second one but if benefits are big I'd edit them to use the more efficient one. Thoughts?
-
Try this maybe. Flag files have lower letter names and admin panel shows big letters for countrycodes. Also just to be sure, forced the 'flag' to be a string. -- Script code exports.scoreboard:addScoreboardColumn('Country') function showcountry() local flag = exports.admin:getPlayerCountry ( source ) if flag then setElementData(source,"Country",":admin/client/images/flags/"..string.lower(tostring(flag))..".png") else flag = "N/A" end end addEventHandler("onPlayerJoin",getRootElement(),showcountry) -- Scoreboard code elseif column.name == "Country" then dxDrawImage( topX+theX, y+s(1), 16, 11, content, 0, 0, 0, cWhite, drawOverGUI ) Or have a look at how it's done in my scoreboard.zip here: http://www.mediafire.com/file/bk1ipa4vhq1swal/scoreboard.zip
-
Hm...still looks harder than normal lua, I'll read a bit, we'll see.
-
Too bad there's no tutorial for OOP around here. It's chinese for me
-
OK, so i wanted to write this a long time ago and the time has come. Why are MTA's default resources made in such a hard way? Why is every single thing connected to ten thousand other things and each of them is connected to another thousand things? Why do functions have ':' in their name? This makes it impossible to export those functions because of the two dots in their name. Can't things be done in an easy to understand way without links to hundreds of other functions and so on? I needed to get the 'getAll ()' function from the 'racemap.lua' file to use in my resource but that task became impossible the moment i saw how that function is created. Couldn't all needed things be included inside of it or atleast made in a simpler way to understand? And lastly, why do all default resources use OOP even on places where normal lua code can be used?
-
Yeah, I saw that but it's server-side, whereas my whole code is client-side. I managed to fix the problem like this: 1. Do not create the markers on map start. 2. If the isSpectatingGhost is 'false' - do nothing, but if it's 'true' - create 2 markers (and 2 radar blips) ahead of the ghost's current position. 3. If the ghost's position is in a radius of 45m to the position of a marker - destroy the marker (and the radar blip). 4. If I stop spectating the ghost (isSpectatingGhost == false) and markers (and blips) have been made - destroy all markers (and blips) that have been created (max can be 2). 5. All this in a for loop and onClientRender. Didn't want to do it like this, it would have been easier and more efficient to just set alpha of markers (and blips), but oh well, if no other way then it's fine. Thanks for the help anyway
-
Only if you export it (for a function): I think variables can't be used in another resource but not sure about it.
-
if isElement(CPMarker[i]) then local r, g, b, alpha = getMarkerColor(CPMarker[i]) if isSpectatingGhost == true then setMarkerColor(CPMarker[i], r, g, b, 128) end if isSpectatingGhost == false then setMarkerColor(CPMarker[i], 0, 0, 255, 0) end end If I change every other color value it works. Changing the alpha value does nothing, it stays the same no matter the value...just my luck OK, I found this here: This article needs checking. Reason(s): Client side only the alpha value defaults to 255 Any (other) way to make markers invisible/visible client-side?
-
Functions are visible between files btw. Unless they're local. You can make one file with useful functions and then another one with the main code. You can use the functions from the first file in the main one without a problem.
-
Hey guys, I have a problem with setting alpha on markers. I create the markers on map start like this: local checkpoints = {} local CPMarker = {} local CPBlip = {} addEvent("onClientMapStarting", true) function onClientMapStarting() checkpoints = getAll("checkpoint") if checkpoints and #checkpoints > 0 then for i = 1, #checkpoints do local color = { 0, 0, 255, 200 } local CPposX, CPposY, CPposZ = unpack(checkpoints[i].position) CPMarker[i] = createMarker(CPposX, CPposY, CPposZ, "checkpoint", checkpoints[i].size, color[1], color[2], color[3], color[4]) CPBlip[i] = createBlip(CPposX, CPposY, CPposZ, 0, 2, color[1], color[2], color[3], color[4]) setElementAlpha(CPMarker[i], 128) end end end addEventHandler("onClientMapStarting", root, onClientMapStarting) function getAll(name) local result = {} for i,element in ipairs(getElementsByType(name)) do result[i] = {} result[i].id = getElementID(element) or i local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) } local rotation = 0 if getElementData(element,"rotation") then rotation = tonumber(getElementData(element,"rotation")) elseif getElementData(element,"rotZ") then rotation = tonumber(getElementData(element,"rotZ")) end local vehicle = tonumber(getElementData(element,"vehicle")) local size = tonumber(getElementData(element,"size")) result[i].position = position; result[i].rotation = rotation; result[i].vehicle = vehicle; result[i].size = size; end return result end So for each checkpoint that the map has a marker gets created. Now I want to make those created markers invisible when a certain condition is met but setElementAlpha doesn't seem to be working. Note that when setting the alpha on map start, it works. But the following doesn't work: function checkAndFixTabData() local isSpectatingGhost = getElementData(localPlayer, "isSpectatingGhost") for i = 1, #CPMarker do if isElement(CPMarker[i]) then if isSpectatingGhost == true then setElementAlpha(CPMarker[i], 128) elseif isSpectatingGhost == false then setElementAlpha(CPMarker[i], 0) end end end end addEventHandler("onClientRender", root, checkAndFixTabData) Basically I want to make it invisible when I am not spectating the ghost vehicle but make the markers visible when I am spectating the ghost. So what's the problem?
-
I had this problem recently as well. Resource names are different but map name in meta is same as another map's. This also bugs toptimes as the map's toptimes are stored under its name from the meta.xml. So if you've made a toptime on one of the maps which has the same name as another one, the same toptime will show on the other map too - even if you've never played it before. You just have to manually rename one of the maps to a unique name in its meta.xml. No other way. PS: It'd be better if toptimes get stored under the map's resource name, not its meta one but oh well I can do this probably but it will delete all tops from my server so meh good luck
-
Here's an updated code if anyone needs it. With it you can use Q and E (and both) just like in normal spectating. Q - look left of vehicle, E - look right of vehicle and Q+E - look infront of vehicle: local AngX, AngZ, specDist, specTarget, ticks, speed, fixedCam = 0, 0, 0, nil, 0, 0.8, true ------------------------------------------------------------------------------------------------------------------------- function MoveMouse(rx, ry, x, y) if not isCursorShowing() and not isMTAWindowActive() and getKeyState("Q") == false and getKeyState("E") == false then fixedCam = false local sx, sy = guiGetScreenSize() ticks = getTickCount() AngX = (AngX + (x - (sx / 2)) / 10) % 360 AngZ = (AngZ + (y - (sy / 2)) / 10) % 360 if AngZ > 180 then if AngZ < 315 then AngZ = 315 end else if AngZ > 45 then AngZ = 45 end end end end ------------------------------------------------------------------------------------------------------------------------- function RenderVeiw() local ox, oy, oz local x, y, z local savedDis1 local savedSpeed if specTarget then x, y, z = getElementPosition(specTarget) end if x and y and z and AngX and AngZ and specDist then if getKeyState("Q") == true and getKeyState("E") == false and not isCursorShowing() and not isMTAWindowActive() then local rx, ry, rz = getElementRotation(specTarget) local dis = AngX - (270 - rz) local dis1 = math.abs(dis) if dis1 > 30 then if speed < 4 then speed = speed + 0.4 end elseif dis1 < 30 then if speed > 0.8 then speed = speed - 0.4 end elseif dis1 > speed then dis = dis / (dis1 / speed) end savedDis1 = dis1 savedSpeed = speed fixedCam = true AngX = AngX - dis elseif getKeyState("Q") == false and getKeyState("E") == true and not isCursorShowing() and not isMTAWindowActive() then local rx, ry, rz = getElementRotation(specTarget) local dis = AngX - (90 - rz) local dis1 = math.abs(dis) if dis1 > 30 then if speed < 4 then speed = speed + 0.4 end elseif dis1 < 30 then if speed > 0.8 then speed = speed - 0.4 end elseif dis1 > speed then dis = dis / (dis1 / speed) end savedDis1 = dis1 savedSpeed = speed fixedCam = true AngX = AngX - dis elseif getKeyState("Q") == true and getKeyState("E") == true and not isCursorShowing() and not isMTAWindowActive() then local rx, ry, rz = getElementRotation(specTarget) local dis = AngX - (180 - rz) local dis1 = math.abs(dis) if dis1 > 30 then if speed < 4 then speed = speed + 0.4 end elseif dis1 < 30 then if speed > 0.8 then speed = speed - 0.4 end elseif dis1 > speed then dis = dis / (dis1 / speed) end savedDis1 = dis1 savedSpeed = speed fixedCam = true AngX = AngX - dis elseif getKeyState("Q") == false and getKeyState("E") == false then if ticks + 1500 < getTickCount() then local rx, ry, rz = getElementRotation(specTarget) local dis = AngX - (360 - rz) local dis1 = math.abs(dis) if fixedCam == false then if dis1 > 30 then if speed < 4 then speed = speed + 0.4 end end if dis1 < 30 then if speed > 0.8 then speed = speed - 0.4 end end if dis1 > speed then dis = dis / (dis1 / speed) end if dis1 < speed then fixedCam = true end end if fixedCam == true then if dis1 > 30 then if speed < 4 then speed = speed + 0.4 end elseif dis1 < 30 then if speed > 0.8 then speed = speed - 0.4 end elseif dis1 > speed then dis = dis / (dis1 / speed) end end savedDis1 = dis1 savedSpeed = speed AngX = AngX - dis end end if isCursorShowing() or isMTAWindowActive() then if ticks + 1500 < getTickCount() then if savedDis1 < savedSpeed then fixedCam = true end end end ox = x - math.sin(math.rad(AngX)) * specDist oy = y - math.cos(math.rad(AngX)) * specDist oz = z + math.tan(math.rad(AngZ)) * specDist + 2 setCameraMatrix(ox, oy, oz, x, y, z) end end ------------------------------------------------------------------------------------------------------------------------- addEvent("setPlayerSpecOnElement", true) function PlayerSpecOnElement(target, distance) if target == nil or distance == nil or target == "None" then if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then removeEventHandler("onClientCursorMove", root, MoveMouse) movedMouse = false end if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then removeEventHandler("onClientRender", root, RenderVeiw) end specTarget = nil specDist = 0 return 1 end if specTarget then if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then removeEventHandler("onClientCursorMove", root, MoveMouse) movedMouse = false end if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then removeEventHandler("onClientRender", root, RenderVeiw) end end specTarget = target specDist = distance if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then removeEventHandler("onClientCursorMove", root, MoveMouse) movedMouse = false end if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == false then addEventHandler("onClientCursorMove", root, MoveMouse) movedMouse = true end if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then removeEventHandler("onClientRender", root, RenderVeiw) end if isEventHandlerAdded("onClientRender", root, RenderVeiw) == false then addEventHandler("onClientRender", root, RenderVeiw) end end addEventHandler("setPlayerSpecOnElement", root, PlayerSpecOnElement) ------------------------------------------------------------------------------------------------------------------------- function isEventHandlerAdded(sEventName, pElementAttachedTo, func) if type(sEventName) == "string" and isElement(pElementAttachedTo) and type(func) == "function" then local aAttachedFunctions = getEventHandlers(sEventName, pElementAttachedTo) if type(aAttachedFunctions) == "table" and #aAttachedFunctions > 0 then for i, v in ipairs(aAttachedFunctions) do if v == func then return true end end end end return false end ------------------------------------------------------------------------------------------------------------------------ function getAll(name) local result = {} for i,element in ipairs(getElementsByType(name)) do result[i] = {} result[i].id = getElementID(element) or i local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) } local rotation = 0 if getElementData(element,"rotation") then rotation = tonumber(getElementData(element,"rotation")) elseif getElementData(element,"rotZ") then rotation = tonumber(getElementData(element,"rotZ")) end local vehicle = tonumber(getElementData(element,"vehicle")) result[i].position = position; result[i].rotation = rotation; result[i].vehicle = vehicle; end return result end But I still can't figure out how to automatically fix the Z position of the camera If you know the maths behind it (you knew how to fix the X position to always be at the car's back) I'd be grateful if you tell me how to achieve this as well The camera just stays at one Z position, even if the vehicle is going up or down a hill and it looks bad. Need it to always stay behind the car just like it does on a normal straight road.
-
Well try to find code lines in that resource which might be responsible for vehicle sounds and comment them out to see if it's fixed.
-
How don't you know what resources are running on your server lmao So turn off all and enable them one by one until the bug appears again. The last started resource is the culprit.
-
Don't even have slightest idea how to do this, maybe some hint?
-
It didn't work at first but when I removed the 'ticks2' variable it worked fine. All I needed was "if dis1 < speed then". Now I'll try to set the camera's Z position according to the car's rear position. Currently it keeps the same Z position even if car goes down a hill for example (isn't pointing directly at it's back, but is below the gta textures sometimes). Hope I can do that alone , if not I'll reply here again. Thank you for everything!
-
OK, it works almost perfect. But do any of you know if there is a way to know when the camera has stopped moving itself and it's at the back of the target? What I mean is this: After not moving my mouse for some seconds the camera goes behind the object automatically. Can I somehow know when the animation of it going to the back has ended? I hope you understood me I need to know when the animation of the camera going to the object's rear has ended because I want to force it to stay behind the object then (if mouse is not moved). @orel56000 @idan1432
-
Depends on the amount of client files and the player's Internet speed
-
Never understood this. Yeah, sure - it makes stealing the script less possible but players have to download the same client files every time they join the server...instead of downloading them just once on their first join.
-
As stated in the wiki page: -- Return the max health. Make sure it can't be below 1 It means that if the value of 'maxhealth' is negative it will always return 1. Basically it checks to see which of the two values is bigger than the other and always returns the bigger one
-
@idan1432 you are amazing, I love you