PageRenderTime 37ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/[gamemodes]/[race]/race/edf/edf_client_cp_lines.lua

https://gitlab.com/yasin3223/mtasa-resources
Lua | 206 lines | 148 code | 35 blank | 23 comment | 18 complexity | 85b02ebd3253a0909cb25e2491afbd3f MD5 | raw file
  1. --
  2. -- edf_client_cp_lines.lua
  3. --
  4. -- Visualization of checkpoint connections for race
  5. -- Use command 'cplines' to toggle display
  6. --
  7. local showHelpText = false
  8. local showCheckpointLines = true
  9. local updatesPerFrame = 10 -- How many checkpoints to update per frame
  10. local lineList = {}
  11. local curIdx = 0
  12. local startTime = getTickCount()
  13. --
  14. -- Handle cplines command
  15. --
  16. addCommandHandler( "cplines",
  17. function(command, arg1, arg2)
  18. if arg1 == "0" then
  19. showCheckpointLines = false
  20. elseif arg1 == "1" then
  21. showCheckpointLines = true
  22. else
  23. showCheckpointLines = not showCheckpointLines
  24. end
  25. outputChatBox( "cplines is now " .. (showCheckpointLines and 1 or 0) )
  26. end
  27. )
  28. function drawCheckpointConnections()
  29. local checkpoints = getElementsByType("checkpoint")
  30. -- Trim line list
  31. while #lineList > #checkpoints do
  32. table.remove( lineList, #lineList )
  33. end
  34. -- Update line list (a few cps at a time)
  35. local numToDo = math.min( updatesPerFrame, #checkpoints )
  36. for i=1,numToDo do
  37. curIdx = curIdx % #checkpoints
  38. local checkpoint = checkpoints[curIdx + 1]
  39. lineList[curIdx + 1] = false
  40. local nextID = exports.edf:edfGetElementProperty ( checkpoint, "nextid" )
  41. if isElement(nextID) then
  42. local dx,dy,dz = exports.edf:edfGetElementPosition(nextID)
  43. if dx then
  44. local sx,sy,sz = exports.edf:edfGetElementPosition(checkpoint)
  45. if sx then
  46. -- Make arrow points
  47. local s = Vector3D:new(sx,sy,sz+1)
  48. local d = Vector3D:new(dx,dy,dz+1)
  49. local dir = d:SubV(s)
  50. local length = dir:Length()
  51. local mid = s:AddV(dir:Mul(0.5))
  52. dir:Normalize()
  53. local left = dir:CrossV(Vector3D:new(0,0,1))
  54. left.z = 0
  55. left:Normalize()
  56. left = left:Mul(2)
  57. local p = d:SubV(dir:Mul(3))
  58. local p1 = p:AddV(left)
  59. local p2 = p:SubV(left)
  60. lineList[curIdx + 1] = {s=s,d=d,p1=p1,p2=p2,m=mid,length=length}
  61. end
  62. end
  63. end
  64. curIdx = curIdx + 1
  65. end
  66. -- Draw line list
  67. if showCheckpointLines then
  68. local postGui = not isCursorShowing() and not isMTAWindowActive()
  69. local camX,camY,camZ = getCameraMatrix()
  70. for i,line in ipairs(lineList) do
  71. if line then
  72. local dist = getDistanceBetweenPoints3D( camX, camY, camZ, line.m.x, line.m.y, line.m.z )
  73. local maxdist = math.max(300,line.length / 1.5)
  74. if dist < maxdist then
  75. -- Alpha calculation
  76. local alpha = math.unlerpclamped( maxdist, dist, 10 ) * 255
  77. -- Color calculation
  78. local pos = i / #lineList
  79. local invpos = 1 - pos
  80. local color = tocolor(pos*255,0,invpos*255,alpha)
  81. -- Line width - Make it bigger if far away, to stop shimmering
  82. local width = 10
  83. if dist > 100 then
  84. width = width + (dist-100)/20
  85. end
  86. dxDrawLine3D ( line.s.x,line.s.y,line.s.z, line.d.x,line.d.y,line.d.z, color, width, postGui )
  87. dxDrawLine3D ( line.d.x,line.d.y,line.d.z, line.p1.x,line.p1.y,line.p1.z, color, width, postGui )
  88. dxDrawLine3D ( line.d.x,line.d.y,line.d.z, line.p2.x,line.p2.y,line.p2.z, color, width, postGui )
  89. end
  90. end
  91. end
  92. end
  93. -- Draw help text
  94. if startTime then
  95. local delta = getTickCount() - startTime
  96. if delta > 14000 then
  97. startTime = false
  98. end
  99. if showHelpText then
  100. local scx,scy = guiGetScreenSize()
  101. local alpha = math.unlerpclamped( 2000, delta, 4000 ) * math.unlerpclamped( 14000, delta, 10000 )
  102. local x,y = 10, scy * 0.6
  103. local font = "default-bold"
  104. local scale = 2
  105. local postGui = true
  106. dxDrawRectangle( x-5, y-5, scale*300, scale*32+10, tocolor(0,0,0,alpha*128), postGui )
  107. dxDrawText( "race edf commands:", x, y, x, y, tocolor(255,255,0,alpha*255), scale, font, "left", "top", false, false, postGui )
  108. dxDrawText( "cplines - toggle checkpoint connections", x, y + scale*16, x, y, tocolor(255,255,255,alpha*255), scale, font, "left", "top", false, false, postGui )
  109. end
  110. end
  111. end
  112. addEventHandler('onClientHUDRender', root, drawCheckpointConnections)
  113. ---------------------------------------------------------------------------
  114. -- mafs
  115. ---------------------------------------------------------------------------
  116. function math.lerp(from,alpha,to)
  117. return from + (to-from) * alpha
  118. end
  119. function math.unlerp(from,pos,to)
  120. if ( to == from ) then
  121. return 1
  122. end
  123. return ( pos - from ) / ( to - from )
  124. end
  125. function math.clamp(low,value,high)
  126. return math.max(low,math.min(value,high))
  127. end
  128. function math.unlerpclamped(from,pos,to)
  129. return math.clamp(0,math.unlerp(from,pos,to),1)
  130. end
  131. ---------------------------------------------------------------------------
  132. -- Vector3D
  133. ---------------------------------------------------------------------------
  134. Vector3D = {
  135. new = function(self, _x, _y, _z)
  136. local newVector = { x = _x or 0.0, y = _y or 0.0, z = _z or 0.0 }
  137. return setmetatable(newVector, { __index = Vector3D })
  138. end,
  139. Copy = function(self)
  140. return Vector3D:new(self.x, self.y, self.z)
  141. end,
  142. Normalize = function(self)
  143. local mod = self:Length()
  144. self.x = self.x / mod
  145. self.y = self.y / mod
  146. self.z = self.z / mod
  147. end,
  148. Dot = function(self, V)
  149. return self.x * V.x + self.y * V.y + self.z * V.z
  150. end,
  151. Length = function(self)
  152. return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
  153. end,
  154. AddV = function(self, V)
  155. return Vector3D:new(self.x + V.x, self.y + V.y, self.z + V.z)
  156. end,
  157. SubV = function(self, V)
  158. return Vector3D:new(self.x - V.x, self.y - V.y, self.z - V.z)
  159. end,
  160. CrossV = function(self, V)
  161. return Vector3D:new(self.y * V.z - self.z * V.y,
  162. self.z * V.x - self.x * V.z,
  163. self.x * V.y - self.y * V.z)
  164. end,
  165. Mul = function(self, n)
  166. return Vector3D:new(self.x * n, self.y * n, self.z * n)
  167. end,
  168. Div = function(self, n)
  169. return Vector3D:new(self.x / n, self.y / n, self.z / n)
  170. end,
  171. }