first commit
This commit is contained in:
commit
a7466b2e68
|
@ -0,0 +1,93 @@
|
|||
MinHeap = {}
|
||||
MinHeap.__index = MinHeap
|
||||
|
||||
local floor = math.floor
|
||||
|
||||
function MinHeap.new()
|
||||
return setmetatable({ n = 0 }, MinHeap)
|
||||
end
|
||||
|
||||
function MinHeap:insertvalue(num)
|
||||
self[self.n] = num
|
||||
self.n = self.n + 1
|
||||
|
||||
local child = self.n - 1
|
||||
local parent, temp
|
||||
while child > 0 do
|
||||
parent = floor((child - 1)/2)
|
||||
if self[parent] <= self[child] then
|
||||
break
|
||||
end
|
||||
temp = self[parent]
|
||||
self[parent] = self[child]
|
||||
self[child] = temp
|
||||
child = parent
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function MinHeap:findindex(num, root)
|
||||
root = root or 0
|
||||
if root >= self.n or num < self[root] then
|
||||
return false
|
||||
end
|
||||
if num == self[root] then
|
||||
return root
|
||||
end
|
||||
return self:findindex(num, root*2 + 1) or self:findindex(num, root*2 + 2)
|
||||
end
|
||||
|
||||
function MinHeap:deleteindex(index)
|
||||
if index < 0 or index >= self.n then
|
||||
return false
|
||||
end
|
||||
local deleted = self[index]
|
||||
self[index] = self[self.n-1]
|
||||
self[self.n-1] = nil
|
||||
self.n = self.n - 1
|
||||
|
||||
local parent = index
|
||||
local child, temp
|
||||
while true do
|
||||
child = parent*2 + 1
|
||||
if child >= self.n then
|
||||
break
|
||||
end
|
||||
if child < self.n - 1 and self[child+1] < self[child] then
|
||||
child = child + 1
|
||||
end
|
||||
if self[parent] <= self[child] then
|
||||
break
|
||||
end
|
||||
temp = self[parent]
|
||||
self[parent] = self[child]
|
||||
self[child] = temp
|
||||
parent = child
|
||||
end
|
||||
return deleted
|
||||
end
|
||||
|
||||
function MinHeap:deletevalue(num)
|
||||
local index = self:findindex(num)
|
||||
if not index then
|
||||
return false
|
||||
end
|
||||
return self:deleteindex(index)
|
||||
end
|
||||
|
||||
function MinHeap:size()
|
||||
return self.n
|
||||
end
|
||||
|
||||
function MinHeap:empty()
|
||||
return self.n == 0
|
||||
end
|
||||
|
||||
function MinHeap:__tostring(index, depth)
|
||||
index = index or 0
|
||||
depth = depth or 0
|
||||
if index >= self.n then
|
||||
return ''
|
||||
end
|
||||
return (' '):rep(depth) .. tostring(self[index]) .. '\n' .. self:__tostring(index*2+1, depth+1) .. self:__tostring(index*2+2, depth+1)
|
||||
end
|
|
@ -0,0 +1,189 @@
|
|||
function aiGetClosestNode(x,y,z,path)
|
||||
local cDist = nil
|
||||
local cNode = nil
|
||||
local cNodeID = nil
|
||||
|
||||
for i,node in ipairs(path) do
|
||||
local dist = getDistanceBetweenPoints3D(x,y,z,node.x,node.y,node.z)
|
||||
if cDist == nil then
|
||||
cDist = dist
|
||||
cNodeID = i
|
||||
cNode = node
|
||||
end
|
||||
|
||||
if dist < cDist then
|
||||
cDist = dist
|
||||
cNodeID = i
|
||||
cNode = node
|
||||
end
|
||||
end
|
||||
|
||||
return cNodeID,cNode
|
||||
end
|
||||
|
||||
function aiGetNextNode(path,nodeID,minDist)
|
||||
minDist = minDist or 0
|
||||
local prevX = path[nodeID].x
|
||||
local prevY = path[nodeID].y
|
||||
local prevZ = path[nodeID].z
|
||||
local dist = 0
|
||||
nodeID = nodeID + 1
|
||||
local length = #path
|
||||
while nodeID <= length do
|
||||
local x = path[nodeID].x
|
||||
local y = path[nodeID].y
|
||||
local z = path[nodeID].z
|
||||
dist = dist + getDistanceBetweenPoints3D(x,y,z,prevX,prevY,prevZ)
|
||||
if dist >= minDist then
|
||||
return nodeID,path[nodeID]
|
||||
end
|
||||
prevX = x
|
||||
prevY = y
|
||||
prevZ = z
|
||||
nodeID = nodeID + 1
|
||||
end
|
||||
|
||||
nodeID = length
|
||||
return nodeID,path[nodeID]
|
||||
end
|
||||
|
||||
function handleGpsAi(driver)
|
||||
local gx = getElementData(driver,"gps-ai.x")
|
||||
local gy = getElementData(driver,"gps-ai.y")
|
||||
local gz = getElementData(driver,"gps-ai.z")
|
||||
local veh = getPedOccupiedVehicle(driver)
|
||||
local x,y,z = getElementPosition(veh)
|
||||
local rx,ry,rz = getElementRotation(veh)
|
||||
local speed = getElementSpeed(veh)
|
||||
|
||||
if not getElementData(driver,"gps-ai.path") then
|
||||
local path = calculatePathByCoords(x,y,z,gx,gy,gz)
|
||||
if not path then return end
|
||||
setElementData(driver,"gps-ai.path",path,false)
|
||||
end
|
||||
|
||||
local path = getElementData(driver,"gps-ai.path")
|
||||
local closestNodeID,closestNode = aiGetClosestNode(x,y,z,path)
|
||||
local checkNodeOneID,checkNodeOne = aiGetNextNode(path,closestNodeID,20 + ((speed * 0.15) * (speed * 0.01)))
|
||||
local checkNodeTwoID,checkNodeTwo = aiGetNextNode(path,closestNodeID,20 + ((speed * 0.4) * (speed * 0.01)))
|
||||
|
||||
--[[ hit = processLineOfSight(x,y,z,checkNodeOne.x,checkNodeOne.y,checkNodeOne.z + 0.5,true,false,false,true,false,false,false,false,nil,false,false)
|
||||
if hit then
|
||||
checkNodeOneID,checkNodeOne = aiGetNextNode(path,closestNodeID)
|
||||
end ]]--
|
||||
|
||||
local reqzOne = findRotation(x,y,checkNodeOne.x,checkNodeOne.y)
|
||||
local reqzTwo = findRotation(x,y,checkNodeTwo.x,checkNodeTwo.y)
|
||||
|
||||
reqzOneLocal = rz - reqzOne
|
||||
if reqzOneLocal > 180 then reqzOneLocal = reqzOneLocal - 360 end
|
||||
if reqzOneLocal < -180 then reqzOneLocal = reqzOneLocal + 360 end
|
||||
|
||||
reqzTwoLocal = rz - reqzTwo
|
||||
if reqzTwoLocal > 180 then reqzTwoLocal = reqzTwoLocal - 360 end
|
||||
if reqzTwoLocal < -180 then reqzTwoLocal = reqzTwoLocal + 360 end
|
||||
|
||||
local steeringAngleOne = reqzOneLocal
|
||||
if steeringAngleOne < 0 then
|
||||
steeringAngleOne = 0 - steeringAngleOne
|
||||
end
|
||||
steeringAmountOne = steeringAngleOne / 180
|
||||
|
||||
local steeringAngleTwo = reqzTwoLocal
|
||||
if steeringAngleTwo < 0 then
|
||||
steeringAngleTwo = 0 - steeringAngleTwo
|
||||
end
|
||||
steeringAmountTwo = steeringAngleTwo / 180
|
||||
|
||||
local brake = false
|
||||
--[[ if steeringAngleOne > steeringAngleTwo then
|
||||
regzTwo = regzOne
|
||||
regzTwoLocal = regzOneLocal
|
||||
steeringAngleTwo = steeringAngleOne
|
||||
steeringAmountTwo = steeringAmountOne
|
||||
brake = true
|
||||
end ]]--
|
||||
|
||||
local maxSpeed = getElementData(driver,"gps-ai.maxSpeed")
|
||||
if steeringAngleTwo > 10 then
|
||||
local owo = steeringAmountTwo * 2.5
|
||||
if owo > 1 then owo = 1 end
|
||||
local nMaxSpeed = 15 + (130 * (1 - owo))
|
||||
if nMaxSpeed < maxSpeed then maxSpeed = nMaxSpeed end
|
||||
end
|
||||
|
||||
if brake then maxSpeed = maxSpeed * 0.5 end
|
||||
|
||||
if speed < maxSpeed then
|
||||
setPedControlState(driver,"accelerate",true)
|
||||
setPedAnalogControlState(driver,"brake_reverse",0)
|
||||
else
|
||||
setPedControlState(driver,"accelerate",false)
|
||||
end
|
||||
|
||||
if speed > maxSpeed + 5 then
|
||||
setPedAnalogControlState(driver,"brake_reverse",0.8)
|
||||
end
|
||||
|
||||
local currentSteer = getPedAnalogControlState(driver,"vehicle_right") - getPedAnalogControlState(driver,"vehicle_left")
|
||||
local steerSpeed = 0.2
|
||||
|
||||
if reqzOneLocal < 0 then
|
||||
currentSteer = currentSteer - steerSpeed
|
||||
end
|
||||
|
||||
if reqzOneLocal > 0 then
|
||||
currentSteer = currentSteer + steerSpeed
|
||||
end
|
||||
steerLimit = steeringAngleOne / 10
|
||||
|
||||
if steerLimit < 0.4 then steerLimit = 0.4 end
|
||||
if steerLimit > 1 then steerLimit = 1 end
|
||||
if currentSteer > steerLimit then currentSteer = steerLimit end
|
||||
if currentSteer < 0 - steerLimit then currentSteer = 0 - steerLimit end
|
||||
|
||||
if currentSteer > 0 then
|
||||
setPedAnalogControlState(driver,"vehicle_left",0)
|
||||
setPedAnalogControlState(driver,"vehicle_right",currentSteer)
|
||||
end
|
||||
|
||||
if currentSteer < 0 then
|
||||
setPedAnalogControlState(driver,"vehicle_right",0)
|
||||
setPedAnalogControlState(driver,"vehicle_left",0 - currentSteer)
|
||||
end
|
||||
|
||||
-- DEBUG --
|
||||
local resx,resy = guiGetScreenSize()
|
||||
dxDrawLine3D(x,y,z,checkNodeOne.x,checkNodeOne.y,checkNodeOne.z + 1,tocolor(255,0,0,128),10)
|
||||
dxDrawLine3D(x,y,z,checkNodeTwo.x,checkNodeTwo.y,checkNodeTwo.z + 1,tocolor(255,255,0,128),10)
|
||||
|
||||
local debugText = ""
|
||||
debugText = debugText .. "Required Z 1: " ..reqzOne
|
||||
debugText = debugText .. "\nRequired Z 2: " ..reqzTwo
|
||||
debugText = debugText .. "\n"
|
||||
debugText = debugText .. "\nRequired Z 1 - LOCAL: " ..reqzOneLocal
|
||||
debugText = debugText .. "\nMax speed: " ..maxSpeed.. " (" ..steeringAmountTwo.. ")"
|
||||
local px,py,pz = getElementPosition(driver)
|
||||
local dbx,dby,dbz = getScreenFromWorldPosition(px,py,pz + 1)
|
||||
dxDrawText(debugText,dbx + 1,dby + 1,dbx + 1,dby + 1,tocolor(0,0,0),1,"default-bold","center","center",false,true,true)
|
||||
dxDrawText(debugText,dbx,dby,dbx,dby,tocolor(255,255,0),1,"default-bold","center","center",false,true,true)
|
||||
end
|
||||
|
||||
function handleGpsAiFrame()
|
||||
for _,ped in ipairs(getElementsByType("ped")) do
|
||||
if getElementData(ped,"gps-ai.x") then
|
||||
handleGpsAi(ped)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
addEventHandler("onClientRender",root,handleGpsAiFrame)
|
||||
|
||||
function getElementSpeed(theElement)
|
||||
return (Vector3(getElementVelocity(theElement)) * 180).length
|
||||
end
|
||||
|
||||
function findRotation( x1, y1, x2, y2 )
|
||||
local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
|
||||
return t < 0 and t + 360 or t
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
addCommandHandler('drive', function(player, command, tox, toy, toz, maxSpeed)
|
||||
if not getPedOccupiedVehicle(player) or getPedOccupiedVehicleSeat(player) ~= 0 then
|
||||
outputChatBox("You need to be driving a vehicle.",player,255,0,0)
|
||||
--return
|
||||
end
|
||||
|
||||
x,y,z = getElementPosition(player)
|
||||
veh = getPedOccupiedVehicle(player)
|
||||
maxSpeed = maxSpeed or 50
|
||||
driver = createPed(107,x,y,z)
|
||||
setElementData(driver,"gps-ai.x",tox)
|
||||
setElementData(driver,"gps-ai.y",toy)
|
||||
setElementData(driver,"gps-ai.z",toz)
|
||||
setElementData(driver,"gps-ai.maxSpeed",tonumber(maxSpeed))
|
||||
warpPedIntoVehicle(player,veh,1)
|
||||
warpPedIntoVehicle(driver,veh,0)
|
||||
end)
|
|
@ -0,0 +1,87 @@
|
|||
local floor = math.floor
|
||||
|
||||
addCommandHandler('path',
|
||||
function(command, node1, node2)
|
||||
if not tonumber(node1) or not tonumber(node2) then
|
||||
outputChatBox("Usage: /path node1 node2", 255, 0, 0)
|
||||
return
|
||||
end
|
||||
local path = server.calculatePathByNodeIDs(tonumber(node1), tonumber(node2))
|
||||
if not path then
|
||||
outputConsole('No path found')
|
||||
return
|
||||
end
|
||||
server.spawnPlayer(getLocalPlayer(), path[1].x, path[1].y, path[1].z)
|
||||
fadeCamera(true)
|
||||
setCameraTarget(getLocalPlayer())
|
||||
|
||||
removeLinePoints ( )
|
||||
table.each(getElementsByType('marker'), destroyElement)
|
||||
for i,node in ipairs(path) do
|
||||
createMarker(node.x, node.y, node.z, 'corona', 5, 50, 0, 255, 200)
|
||||
addLinePoint ( node.x, node.y )
|
||||
end
|
||||
end
|
||||
)
|
||||
addCommandHandler('path2',
|
||||
function(command, tox, toy, toz)
|
||||
if not tonumber(tox) or not tonumber(toy) then
|
||||
outputChatBox("Usage: /path2 x y z (z is optional)", 255, 0, 0)
|
||||
return
|
||||
end
|
||||
local x,y,z = getElementPosition(getLocalPlayer())
|
||||
local path = calculatePathByCoords(x, y, z, tox, toy, toz)
|
||||
if not path then
|
||||
outputConsole('No path found')
|
||||
return
|
||||
end
|
||||
|
||||
removeLinePoints ( )
|
||||
table.each(getElementsByType('marker'), destroyElement)
|
||||
for i,node in ipairs(path) do
|
||||
createMarker(node.x, node.y, node.z, 'corona', 5, 50, 0, 255, 200)
|
||||
addLinePoint ( node.x, node.y )
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
local function getAreaID(x, y)
|
||||
return math.floor((y + 3000)/750)*8 + math.floor((x + 3000)/750)
|
||||
end
|
||||
|
||||
local function getNodeByID(db, nodeID)
|
||||
local areaID = floor(nodeID / 65536)
|
||||
return db[areaID][nodeID]
|
||||
end
|
||||
|
||||
--[[
|
||||
addEventHandler('onClientRender', getRootElement(),
|
||||
function()
|
||||
local db = vehicleNodes
|
||||
|
||||
local camX, camY, camZ = getCameraMatrix()
|
||||
local x, y, z = getElementPosition(getLocalPlayer())
|
||||
local areaID = getAreaID(x, y)
|
||||
local drawn = {}
|
||||
for id,node in pairs(db[areaID]) do
|
||||
if getDistanceBetweenPoints3D(x, y, z, node.x, node.y, z) < 300 then
|
||||
--[/[
|
||||
local screenX, screenY = getScreenFromWorldPosition(node.x, node.y, node.z)
|
||||
if screenX then
|
||||
dxDrawText(tostring(id), screenX - 10, screenY - 5)
|
||||
end
|
||||
--]/]
|
||||
--[/[
|
||||
for neighbourid,distance in pairs(node.neighbours) do
|
||||
if not drawn[neighbourid .. '-' .. id] then
|
||||
local neighbour = getNodeByID(db, neighbourid)
|
||||
dxDrawLine3D(node.x, node.y, node.z + 1, neighbour.x, neighbour.y, neighbour.z + 1, tocolor(0, 0, 200, 255), 3)
|
||||
drawn[id .. '-' .. neighbourid] = true
|
||||
end
|
||||
end
|
||||
--]/]
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
--]]
|
|
@ -0,0 +1,109 @@
|
|||
local root = getRootElement()
|
||||
local floor = math.floor
|
||||
|
||||
local allowedRPC = {
|
||||
calculatePathByCoords = true,
|
||||
calculatePathByNodeIDs = true,
|
||||
spawnPlayer = true
|
||||
}
|
||||
|
||||
local function getAreaID(x, y)
|
||||
return floor((y + 3000)/750)*8 + floor((x + 3000)/750)
|
||||
end
|
||||
|
||||
local function getNodeByID(db, nodeID)
|
||||
local areaID = floor(nodeID / 65536)
|
||||
return db[areaID][nodeID]
|
||||
end
|
||||
|
||||
local function findNodeClosestToPoint(db, x, y, z)
|
||||
local areaID = getAreaID(x, y)
|
||||
local minDist, minNode
|
||||
local nodeX, nodeY, dist
|
||||
for id,node in pairs(db[areaID]) do
|
||||
nodeX, nodeY = node.x, node.y
|
||||
dist = (x - nodeX)*(x - nodeX) + (y - nodeY)*(y - nodeY)
|
||||
if not minDist or dist < minDist then
|
||||
minDist = dist
|
||||
minNode = node
|
||||
end
|
||||
end
|
||||
return minNode
|
||||
end
|
||||
|
||||
local function calculatePath(db, nodeFrom, nodeTo)
|
||||
local next = next
|
||||
|
||||
local g = { [nodeFrom] = 0 } -- { node = g }
|
||||
local hcache = {} -- { node = h }
|
||||
local parent = {} -- { node = parent }
|
||||
local openheap = MinHeap.new()
|
||||
|
||||
local function h(node)
|
||||
if hcache[node] then
|
||||
return hcache[node]
|
||||
end
|
||||
local x, y, z = node.x - nodeTo.x, node.y - nodeTo.y, node.z - nodeTo.z
|
||||
hcache[node] = x*x + y*y + z*z
|
||||
return hcache[node]
|
||||
end
|
||||
local nodeMT = {
|
||||
__lt = function(a, b)
|
||||
return g[a] + h(a) < g[b] + h(b)
|
||||
end,
|
||||
__le = function(a, b)
|
||||
if not g[a] or not g[b] then
|
||||
outputConsole(debug.traceback())
|
||||
end
|
||||
return g[a] + h(a) <= g[b] + h(b)
|
||||
end
|
||||
}
|
||||
setmetatable(nodeFrom, nodeMT)
|
||||
openheap:insertvalue(nodeFrom)
|
||||
|
||||
local current
|
||||
while not openheap:empty() do
|
||||
current = openheap:deleteindex(0)
|
||||
if current == nodeTo then
|
||||
break
|
||||
end
|
||||
|
||||
local successors = {}
|
||||
for id,distance in pairs(current.neighbours) do
|
||||
local successor = getNodeByID(db, id)
|
||||
local successor_g = g[current] + distance*distance
|
||||
if not g[successor] or g[successor] > successor_g then
|
||||
setmetatable(successor, nodeMT)
|
||||
|
||||
g[successor] = successor_g
|
||||
openheap:insertvalue(successor)
|
||||
parent[successor] = current
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if current == nodeTo then
|
||||
local path = {}
|
||||
repeat
|
||||
table.insert(path, 1, current)
|
||||
current = parent[current]
|
||||
until not current
|
||||
return path
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function calculatePathByCoords(x1, y1, z1, x2, y2, z2)
|
||||
return calculatePath(vehicleNodes, findNodeClosestToPoint(vehicleNodes, x1, y1, z1), findNodeClosestToPoint(vehicleNodes, x2, y2, z2))
|
||||
end
|
||||
|
||||
function calculatePathByNodeIDs(node1, node2)
|
||||
node1 = getNodeByID(vehicleNodes, node1)
|
||||
node2 = getNodeByID(vehicleNodes, node2)
|
||||
if node1 and node2 then
|
||||
return calculatePath(vehicleNodes, node1, node2)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,128 @@
|
|||
local ENABLE_FAILISH_ATTEMPT_AT_ANTI_ALIASING = false
|
||||
|
||||
local OVERLAY_WIDTH = 256
|
||||
local OVERLAY_HEIGHT = 256
|
||||
local OVERLAY_LINE_WIDTH = 5
|
||||
local OVERLAY_LINE_COLOR = tocolor ( 0, 200, 0, 255 )
|
||||
local OVERLAY_LINE_AA = tocolor ( 0, 200, 0, 200 )
|
||||
|
||||
local linePoints = { }
|
||||
local renderStuff = { }
|
||||
|
||||
function removeLinePoints ( )
|
||||
linePoints = { }
|
||||
for name, data in pairs ( renderStuff ) do
|
||||
unloadTile ( name )
|
||||
end
|
||||
end
|
||||
|
||||
function addLinePoint ( posX, posY )
|
||||
-- Calculate the row and column of the radar tile we will be targeting
|
||||
local row = 11 - math.floor ( ( posY + 3000 ) / 500 )
|
||||
local col = math.floor ( ( posX + 3000 ) / 500 )
|
||||
|
||||
-- If it's off the map, don't bother
|
||||
if row < 0 or row > 11 or col < 0 or col > 11 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check the start position of the tile
|
||||
local startX = col * 500 - 3000
|
||||
local startY = 3000 - row * 500
|
||||
|
||||
-- Now get the tile position (We don't want to calculate this for every point on render)
|
||||
local tileX = ( posX - startX ) / 500 * OVERLAY_WIDTH
|
||||
local tileY = ( startY - posY ) / 500 * OVERLAY_HEIGHT
|
||||
|
||||
-- Now calulcate the ID and get the name of the tile
|
||||
local id = col + row * 12
|
||||
local name = string.format ( "radar%02d", id )
|
||||
|
||||
-- Make sure the line point table exists
|
||||
if not linePoints [ name ] then
|
||||
linePoints [ name ] = { }
|
||||
end
|
||||
|
||||
-- Now add this point
|
||||
table.insert ( linePoints[name], { posX = tileX, posY = tileY } )
|
||||
|
||||
-- Success!
|
||||
return true
|
||||
end
|
||||
|
||||
function loadTile ( name )
|
||||
-- Create our fabulous shader. Abort on failure
|
||||
local shader = dxCreateShader ( "overlay.fx" )
|
||||
if not shader then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Create a render target. Again, abort on failure (don't forget to delete the shader!)
|
||||
local rt = dxCreateRenderTarget ( OVERLAY_WIDTH, OVERLAY_HEIGHT, true )
|
||||
if not rt then
|
||||
destroyElement ( shader )
|
||||
return false
|
||||
end
|
||||
|
||||
-- Mix 'n match
|
||||
dxSetShaderValue ( shader, "gOverlay", rt )
|
||||
|
||||
-- Start drawing
|
||||
dxSetRenderTarget ( rt )
|
||||
|
||||
-- Get the points involved, and get the starting position
|
||||
local points = linePoints [ name ]
|
||||
local prevX, prevY = points [ 1 ].posX, points [ 1 ] .posY
|
||||
|
||||
-- Loop through all points we have to draw, and draw them
|
||||
for index, point in ipairs ( points ) do
|
||||
local newX = point.posX
|
||||
local newY = point.posY
|
||||
|
||||
if ENABLE_FAILISH_ATTEMPT_AT_ANTI_ALIASING then
|
||||
dxDrawLine ( prevX - 1, prevY - 1, newX - 1, newY - 1, OVERLAY_LINE_AA, OVERLAY_LINE_WIDTH )
|
||||
dxDrawLine ( prevX + 1, prevY - 1, newX + 1, newY - 1, OVERLAY_LINE_AA, OVERLAY_LINE_WIDTH )
|
||||
dxDrawLine ( prevX - 1, prevY + 1, newX - 1, newY + 1, OVERLAY_LINE_AA, OVERLAY_LINE_WIDTH )
|
||||
dxDrawLine ( prevX + 1, prevY + 1, newX + 1, newY + 1, OVERLAY_LINE_AA, OVERLAY_LINE_WIDTH )
|
||||
end
|
||||
|
||||
dxDrawLine ( prevX, prevY, newX, newY, OVERLAY_LINE_COLOR, OVERLAY_LINE_WIDTH )
|
||||
|
||||
prevX = newX
|
||||
prevY = newY
|
||||
end
|
||||
|
||||
-- Now let's show our fabulous work to the commoners!
|
||||
engineApplyShaderToWorldTexture ( shader, name )
|
||||
|
||||
-- Store the stuff in memories
|
||||
renderStuff [ name ] = { shader = shader, rt = rt }
|
||||
|
||||
-- We won
|
||||
return true
|
||||
end
|
||||
|
||||
function unloadTile ( name )
|
||||
destroyElement ( renderStuff[name].shader )
|
||||
destroyElement ( renderStuff[name].rt )
|
||||
renderStuff[name] = nil
|
||||
return true
|
||||
end
|
||||
|
||||
addEventHandler ( "onClientHUDRender", getRootElement ( ),
|
||||
function ( )
|
||||
local visibleTileNames = table.merge ( engineGetVisibleTextureNames ( "radar??" ), engineGetVisibleTextureNames ( "radar???" ) )
|
||||
|
||||
for name, data in pairs ( renderStuff ) do
|
||||
if not table.find ( visibleTileNames, name ) then
|
||||
unloadTile ( name )
|
||||
end
|
||||
end
|
||||
|
||||
for index, name in ipairs ( visibleTileNames ) do
|
||||
if linePoints [ name ] and not renderStuff [ name ] then
|
||||
loadTile ( name )
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
|
@ -0,0 +1,17 @@
|
|||
<meta>
|
||||
<info author="arc_"/>
|
||||
|
||||
<!-- <script src="vehiclenodes_.lua" type="client"/> -->
|
||||
<script src="util.lua" type="client"/>
|
||||
<script src="client.lua" type="client"/>
|
||||
<script src="linedrawer.lua" type="client"/>
|
||||
|
||||
<file src="overlay.fx"/>
|
||||
|
||||
<script src="vehiclenodes.lua" type="client"/>
|
||||
<script src="MinHeap.lua" type="client"/>
|
||||
<script src="gps.lua" type="client"/>
|
||||
|
||||
<script src="ai.server.lua" type="server"/>
|
||||
<script src="ai.client.lua" type="client"/>
|
||||
</meta>
|
|
@ -0,0 +1,20 @@
|
|||
texture gOverlay;
|
||||
|
||||
technique TexOverlay
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
// We don't do a damn thing here
|
||||
}
|
||||
|
||||
pass P1
|
||||
{
|
||||
// Draw the overlay on top, if we have one
|
||||
Texture[0] = gOverlay;
|
||||
|
||||
// Make sure we can use alpha. This shader wouldn't have much use without it
|
||||
AlphaBlendEnable = TRUE;
|
||||
SrcBlend = SRCALPHA;
|
||||
DestBlend = INVSRCALPHA;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
local CRs = {}
|
||||
|
||||
local _resume = coroutine.resume
|
||||
function coroutine.resume(cr, ...)
|
||||
local ret = { _resume(cr, ...) }
|
||||
if coroutine.status(cr) == 'dead' then
|
||||
CRs[CRs[cr]] = nil
|
||||
CRs[cr] = nil
|
||||
end
|
||||
if not ret[1] then
|
||||
outputDebugString(ret[2], 1)
|
||||
return false
|
||||
end
|
||||
table.remove(ret, 1)
|
||||
return unpack(ret)
|
||||
end
|
||||
|
||||
local serverMT = {}
|
||||
function serverMT:__index(fnName)
|
||||
return function(...)
|
||||
triggerServerEvent('onServerCallback', getLocalPlayer(), CRs[coroutine.running()], fnName, ...)
|
||||
return coroutine.yield()
|
||||
end
|
||||
end
|
||||
server = setmetatable({}, serverMT)
|
||||
|
||||
addEvent('onServerCallbackReply', true)
|
||||
addEventHandler('onServerCallbackReply', getResourceRootElement(getThisResource()),
|
||||
function(crID, ...)
|
||||
coroutine.resume(CRs[crID], ...)
|
||||
end,
|
||||
false
|
||||
)
|
||||
|
||||
local function wrapHandler(fn)
|
||||
return function(...)
|
||||
local cr = coroutine.create(fn)
|
||||
local id = #CRs + 1
|
||||
CRs[id] = cr
|
||||
CRs[cr] = id
|
||||
coroutine.resume(cr, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local _addEventHandler = addEventHandler
|
||||
function addEventHandler(event, elem, fn, getPropagated)
|
||||
return _addEventHandler(
|
||||
event,
|
||||
elem,
|
||||
(event == 'onClientRender' or event == 'onClientPreRender') and fn or wrapHandler(fn),
|
||||
getPropagated
|
||||
)
|
||||
end
|
||||
|
||||
local _addCommandHandler = addCommandHandler
|
||||
function addCommandHandler(command, fn)
|
||||
return _addCommandHandler(command, wrapHandler(fn))
|
||||
end
|
||||
|
||||
|
||||
|
||||
function table.each(t, callback, ...)
|
||||
for k,v in pairs(t) do
|
||||
callback(v, ...)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function table.merge ( ... )
|
||||
local ret = { }
|
||||
|
||||
for index, tbl in ipairs ( {...} ) do
|
||||
for index, val in ipairs ( tbl ) do
|
||||
table.insert ( ret, val )
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function table.find ( tbl, val )
|
||||
for index, value in ipairs ( tbl ) do
|
||||
if value == val then
|
||||
return index
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue