Jump to content

Jayceon

Members
  • Posts

    91
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Jayceon

  1. To achieve the desired result, you need to calculate the chain length, for example, with getDistanceBetweenPoints3D. In the dxDrawMaterialSectionLine3D function, the U Section Size needs to be the same as the texture width (16), and the V Section Size needs to be the texture height (64). However, this alone does not yield the desired results. You also need to multiply the V Section Size with the calculated chain length, divide by the texture aspect ratio (in your case, 64/16) and finally, multiply by the line thickness ("width"). I recommend to create a helper drawing function for this, with arguments: start position, end position, chain thickness.

    • Thanks 1
  2. You can rotate it via setElementMatrix:
     

    function setMarkerHeading(markerElement, rotationDegrees)
    	local markerMatrix = getElementMatrix(markerElement)
    
    	-- Convert degrees to radians
    	rotationDegrees = math.rad(rotationDegrees)
    
    	-- Rotate around Z axis
    	local cosAngle = math.cos(rotationDegrees)
    	local sinAngle = math.sin(rotationDegrees)
    
    	markerMatrix[1][1] = cosAngle
    	markerMatrix[1][2] = sinAngle
    	markerMatrix[1][3] = 0
    
    	markerMatrix[2][1] = -sinAngle
    	markerMatrix[2][2] = cosAngle
    	markerMatrix[2][3] = 0
    
    	markerMatrix[3][1] = 0
    	markerMatrix[3][2] = 0
    	markerMatrix[3][3] = 1
    
    	-- Apply updated matrix
    	return setElementMatrix(markerElement, markerMatrix)
    end

    It's only rotates it around the Z axis like in Single-Player, if you want to rotate it in more axes you should search for rotation matrix in your preferred search engine.

    • Thanks 1
  3. Hi.

    I've put together a code for you in which the door movement works as expected, there is one up and down movement involved at a certain camera/vehicle angle (see the pictures below).

    If you don't need that up/down movement either, we can remove it.

    Spoiler

    spacer.pngspacer.png

    local cameraElement = getCamera()
    local oldCursorRelX = 0.5
    local oldCursorRelY = 0.5
    local moveSensitivity = 2
    
    function moveDoor(cursorRelX, cursorRelY)
    	if not isCursorShowing() then
    		return
    	end
    
    	local vehicleElement = getPedOccupiedVehicle(localPlayer)
    	if not isElement(vehicleElement) then
    		return
    	end
    
    	local cameraMatrix = getElementMatrix(cameraElement)
    	local vehicleMatrix = getElementMatrix(vehicleElement)
    
    	local dotProductX = cameraMatrix[1][1] * vehicleMatrix[1][1] + cameraMatrix[1][2] * vehicleMatrix[1][2]
    	local dotProductY = cameraMatrix[3][1] * vehicleMatrix[1][1] + cameraMatrix[3][2] * vehicleMatrix[1][2]
    
    	local cursorDeltaX = (cursorRelX - oldCursorRelX) * moveSensitivity
    	local cursorDeltaY = (cursorRelY - oldCursorRelY) * moveSensitivity
    
    	oldCursorRelX = cursorRelX
    	oldCursorRelY = cursorRelY
    
    	local dotProductCombined = cursorDeltaX * -dotProductX + cursorDeltaY * dotProductY
    	local openRatio = getVehicleDoorOpenRatio(vehicleElement, 2) + dotProductCombined
    
    	if openRatio < 0 then
    		openRatio = 0
    	elseif openRatio > 1 then
    		openRatio = 1
    	end
    
    	setVehicleDoorOpenRatio(vehicleElement, 2, openRatio)
    end
    
    bindKey("f1", "down",
    	function ()
    		addEventHandler("onClientCursorMove", root, moveDoor)
    	end
    )
    
    bindKey("f2", "down",
    	function ()
    		removeEventHandler("onClientCursorMove", root, moveDoor)
    	end
    )

     

    • Thanks 1
  4. You can convert the normal vectors to euler angles with the following function, you can use the phi for the so called Z rotation and the theta for one of the remaining (check it which one is better for you). It's a working function, I had a fun time with it shooting trash cans everywhere :D

    function directionToEuler(dirX, dirY, dirZ)
    	local radius = (dirX*dirX + dirY*dirY + dirZ*dirZ) ^ 0.5
    	local theta = math.deg(math.acos(dirZ / radius))
    	local phi = math.deg(math.atan2(dirY, dirX)) % 360
    	return theta, phi
    end

     

    • Like 2
  5. First, you don't need to convert the normal vectors to euler angles, beacuse the fxAddSparks function needs a direction vector that is exactly what normal vectors is.

    Second, you need to extend the TargetEndX/Y/Z values a bit because sometimes it's too short and the raycast returns false.

     

    For scaling:
     

    TargetEndX = TargetX + (TargetEndX - TargetX) * 5
    TargetEndY = TargetY + (TargetEndY - TargetY) * 5
    TargetEndZ = TargetZ + (TargetEndZ - TargetZ) * 5

     

    • Thanks 1
  6. On 09/05/2020 at 13:22, IIYAMA said:

    I am not sure, I don't have anybody that I can test it with. For hardware that can run basic GTA properly, it should be fine.

    If anybody that has an old computer, I would be very happy if that person could make a benchmark.

    The CPU usage was normal (average 0.62% in IPB when flying around the map) on my Intel Celeron E3200 (2.40 GHz)

    This PC only have a integrated video card with 128 MB dedicated video memory, so the only problem is the lower fps because a lot of objects drawed. (Tested on a green venturas map with the forest generator publiced by Essle ~ Total 2124 tree objects created)

    But yeah, this is a great work :)

     

    • Like 2
  7. fileDelete download the file and then delete (and not secure bc the file visible for 3-5 seconds while the server is still downloading), cache false not download the file but load it into the memory.

    • Like 1
  8. Try this:

    texture cj_ped_torso;
    texture cj_ped_head;
    texture cj_ped_legs;
    texture cj_ped_feet;
    
    technique TexReplace
    {
    	pass P0
    	{
    		DepthBias = -0.0002;
    		Texture[0] = cj_ped_torso;
    	}
    	pass P1
    	{
    		DepthBias = -0.0002;
    		Texture[0] = cj_ped_head;
    	}
    	pass P2
    	{
    		DepthBias = -0.0002;
    		Texture[0] = cj_ped_legs;
    	}
    	pass P3
    	{
    		DepthBias = -0.0002;
    		Texture[0] = cj_ped_feet;
    	}
    }

     

  9. function getRandomSpawnPoint(cityName)
    	if spawnPositions[cityName] then
    		local realTime = getRealTime()
    		math.randomseed(realTime.second + realTime.minute + realTime.hour)
    		
    		local minX = math.min(spawnPositions[cityName].minPos[1], spawnPositions[cityName].maxPos[1])
    		local minY = math.min(spawnPositions[cityName].minPos[2], spawnPositions[cityName].maxPos[2])
    		local maxX = math.max(spawnPositions[cityName].minPos[1], spawnPositions[cityName].maxPos[1])
    		local maxY = math.max(spawnPositions[cityName].minPos[2], spawnPositions[cityName].maxPos[2])
    
    		return math.random(minX, maxX), math.random(minY, maxY)
    	end
    end

     

  10. You need a color shader, or a renderTarget -> draw the texture image then draw one rectangle with the selected color -> create texture from the renderTarget pixels then destroy renderTarget.

    What did I say before?

    function changeTextureColor(textureElement, red, green, blue, alpha)
    	local textureWidth, textureHeight = dxGetMaterialSize(textureElement) -- get the texture size
      	local tempRenderTarget = dxCreateRenderTarget(textureWidth, textureHeight) -- create render target with texture size
      
      	dxSetRenderTarget(tempRenderTarget) -- start rt
      	dxDrawImage(0, 0, textureWidth, textureHeight, textureElement) -- draw the texture image to the rt
      	dxDrawRectangle(0, 0, textureWidth, textureHeight, tocolor(red, green, blue, alpha)) -- draw the selected color rectangle to the rt
      	-- you can add custom texts to texture etc..
      	dxSetRenderTarget() -- end rt
      	
      	local rt_pixels = dxConvertPixels(dxGetTexturePixels(tempRenderTarget), "png") -- get the rt pixels and convert to png
      	destroyElement(tempRenderTarget) -- destroy rt because I converted to texture
      
      	return dxCreateTexture(rt_pixels) -- return the new texture element
    end

     

    Or the shader way (I dont tested the shader):

    float red;
    float green;
    float blue;
    float alpha;
    
    technique colorChange
    {
        pass P0
        {
            MaterialAmbient = float4(red, green, blue, alpha);
        }
    }
    -- You need to divide the r/g/b with 255 because shader color float range is 0-1.
    
    local selectedRed = 128
    local selectedGreen = 64
    local selectedBlue = 32
    local selectedAlpha = 200
    
    dxSetShaderValue(colorChangeShader, "red", selectedRed / 255)
    dxSetShaderValue(colorChangeShader, "green", selectedGreen / 255)
    dxSetShaderValue(colorChangeShader, "blue", selectedBlue / 255)
    dxSetShaderValue(colorChangeShader, "alpha", selectedAlpha / 255)
    
    -- then apply the shader to the world texture

     

    • Thanks 1
  11. local screenX, screenY = guiGetScreenSize()
    
    local repBarTexture = dxCreateTexture("reputation.png")
    local barWidth, barHeight = dxGetMaterialSize(repBarTexture)
    
    local maxRep = 200
    local currentRep = 100
    local repBarPosX = currentRep * (barWidth - 1) / maxRep
    
    local repBarPixels = dxGetTexturePixels(repBarTexture)
    local r, g, b = dxGetPixelColor(repBarPixels, math.floor(repBarPosX), barHeight / 2)
    
    outputChatBox("HEX: " .. string.format("#%.2X%.2X%.2X", r, g, b) .. ", R: " .. r .. ", G: " .. g .. ", B: " .. b)
    
    local barX = (screenX - barWidth) / 2
    local barY = (screenY - barHeight) / 2
    
    addEventHandler("onClientRender", getRootElement(),
    	function ()
    		dxDrawImage(barX, barY, barWidth, barHeight, repBarTexture)
    
    		dxDrawRectangle(barX + repBarPosX - 2, barY - 3, 4, barHeight + 6, tocolor(255, 255, 255))
    	end
    )

     

  12. I solved this problem with a 8x8 circle image. Added image to the every node position in RT and looks better.

    What I mean?

     

    dxSetRenderTarget(gpsRouteImage)
    dxSetBlendMode("modulate_add")
    
    for i = 2, #gpsLines do
    	if gpsLines[i - 1] then
    		local x0 = gpsLines[i][1] - routeStartPosX + 8
    		local y0 = gpsLines[i][2] - routeStartPosY + 8
    		local x1 = gpsLines[i - 1][1] - routeStartPosX + 8
    		local y1 = gpsLines[i - 1][2] - routeStartPosY + 8
    
    		dxDrawImage(x0 - 4, y0 - 4, 8, 8, "dot.png")
    		dxDrawLine(x0, y0, x1, y1, tocolor(255, 255, 255), 9)
    	end
    end
    
    dxSetBlendMode("blend")
    dxSetRenderTarget()

     

    • Thanks 2
  13. customBoundaries = {
      	-- this boundary is between the big brown building(s) and the skatepark on the road in LS
    	["test"] = {
    		{x = 1842.2908935547, y = -1412.469360351},
    		{x = 1856.8596191406, y = -1412.555664062},
    		{x = 1851.5925292969, y = -1436.5225830078},
    		{x = 1842.0438232422, y = -1424.5217285156},
    	},
    }
    
    local colorOfBounds = tocolor(255, 0, 0)
    
    bindKey("e", "down",
    	function ()
    		if isElementWithinBoundary(localPlayer, "test") then
    			colorOfBounds = tocolor(0, 255, 0)
    		else
    			colorOfBounds = tocolor(255, 0, 0)
    		end
    	end
    )
    
    addEventHandler("onClientRender", getRootElement(),
    	function ()
    		local localX, localY, localZ = getElementPosition(localPlayer)
    		local boundary = "test"
    
    		for i = 1, #customBoundaries[boundary] do
    			local currentPoint = customBoundaries[boundary][i]
    			local nextPoint = customBoundaries[boundary][i + 1]
    
    			if currentPoint then
    				if i == #customBoundaries[boundary] then
    					nextPoint = customBoundaries[boundary][1]
    					dxDrawLine3D(currentPoint.x, currentPoint.y, localZ, nextPoint.x, nextPoint.y, localZ, colorOfBounds, 3)
    				end
    
    				dxDrawLine3D(currentPoint.x, currentPoint.y, localZ, nextPoint.x, nextPoint.y, localZ, colorOfBounds, 3)
    			end
    		end
    	end
    )
    
    function isElementWithinBoundary(element, boundary)
    	if isElement(element) and boundary and customBoundaries[boundary] and #customBoundaries[boundary] >= 3 then
    		local pointX, pointY, pointZ = getElementPosition(element)
    		local intersections = 0
    
    		for i = 1, #customBoundaries[boundary] do
    			local currentPoint = customBoundaries[boundary][i]
    
    			if currentPoint then
    				local nextPoint = customBoundaries[boundary][i + 1]
    				local previousPoint = customBoundaries[boundary][i - 1]
    
    				if i == 1 then
    					previousPoint = customBoundaries[boundary][1]
    				elseif i == #customBoundaries[boundary] then
    					nextPoint = customBoundaries[boundary][1]
    				end
    
    				if areIntersecting(pointX, pointY, previousPoint.x, previousPoint.y, currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y) then
    					intersections = intersections + 1
    				end
    			end
    		end
    
    		if intersections > 0 then
    			return true
    		end
    	end
    
    	return false
    end
    
    function sign(x1, y1, x2, y2, x3, y3)
    	return (x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3)
    end
    
    function areIntersecting(pointX, pointY, x1, y1, x2, y2, x3, y3)
    	local b1 = sign(pointX, pointY, x1, y1, x2, y2) < 0
    	local b2 = sign(pointX, pointY, x2, y2, x3, y3) < 0
    	local b3 = sign(pointX, pointY, x3, y3, x1, y1) < 0
    
    	return b1 == b2 and b2 == b3
    end

     

    Tested. Works with 3 or more points.

    Yes, you can check the element within the the polygon.

    • Like 1
  14. When you export function and call it in another resource you use those formats:

    exports.resname:functionName(arguments)

    or

    exports["resname"]:functionName(arguments)

    Then:

    --script1.lua
    function output()
        print ("ok")
    end
    
    --script1 meta.xml
    <meta>
        <script src="script1.lua" type="server"/>
    
        <export function="output"/>
    </meta>
      
    --script2.lua
    exports.script1:output()
      
    --script2 meta.xml
    <meta>
        <include resource="script1"/>
        <script src="script2.lua" type="server"/>
    </meta>

     

  15. You can put <include resource="resname" /> or use fileOpen, fileRead, pcall and loadstring functions.

    local fileHandler = fileOpen(":resfolder/otherScript.lua")
    if fileHandler then
      local fileContent = fileRead(fileHandler, fileGetSize(fileHandler))
      fileClose(fileHandler)
      pcall(loadstring(fileContent))
    end

     

×
×
  • Create New...