Guest User

Untitled

a guest
Sep 7th, 2013
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.89 KB | None | 0 0
  1. g_Root = getRootElement()
  2. g_ResRoot = getResourceRootElement(getThisResource())
  3. g_Me = getLocalPlayer()
  4. g_ArmedVehicleIDs = table.create({ 425, 447, 520, 430, 464, 432 }, true)
  5. g_WaterCraftIDs = table.create({ 539, 460, 417, 447, 472, 473, 493, 595, 484, 430, 453, 452, 446, 454 }, true)
  6. g_ModelForPickupType = { nitro = 2221, repair = 2222, vehiclechange = 2223 }
  7. g_HunterID = 425
  8.  
  9. g_Checkpoints = {}
  10. g_Pickups = {}
  11. g_VisiblePickups = {}
  12. g_Objects = {}
  13.  
  14. -- set update handlers
  15. g_PickupStartTick = getTickCount()
  16. addEventHandler('onClientRender', g_Root, updateBars)
  17. g_WaterCheckTimer = setTimer(checkWater, 1000, 0)
  18.  
  19. -- load pickup models and textures
  20. for name,id in pairs(g_ModelForPickupType) do
  21. engineImportTXD(engineLoadTXD('model/' .. name .. '.txd'), id)
  22. engineReplaceModel(engineLoadDFF('model/' .. name .. '.dff', id), id)
  23. -- Double draw distance for pickups
  24. engineSetModelLODDistance( id, 60 )
  25. end
  26.  
  27. if isVersion101Compatible() then
  28. -- Dont clip vehicles (1.0.1 function)
  29. setCameraClip ( true, false )
  30. end
  31.  
  32. -- Init presentation screens
  33. TravelScreen.init()
  34. TitleScreen.init()
  35.  
  36. -- Show title screen now
  37. TitleScreen.show()
  38.  
  39. setPedCanBeKnockedOffBike(g_Me, false)
  40. end
  41. )
  42.  
  43.  
  44. -------------------------------------------------------
  45. -- Title screen - Shown when player first joins the game
  46. -------------------------------------------------------
  47. TitleScreen = {}
  48. TitleScreen.startTime = 0
  49.  
  50. function TitleScreen.init()
  51. local screenWidth, screenHeight = guiGetScreenSize()
  52. local adjustY = math.clamp( -30, -15 + (-30- -15) * (screenHeight - 480)/(900 - 480), -15 );
  53. g_GUI['titleImage'] = guiCreateStaticImage(screenWidth/2-256, screenHeight/2-256+adjustY, 512, 512, 'img/title.png', false)
  54. g_dxGUI['titleText1'] = dxText:create('', 30, screenHeight-67, false, 'bankgothic', 0.70, 'left' )
  55. g_dxGUI['titleText2'] = dxText:create('', 120, screenHeight-67, false, 'bankgothic', 0.70, 'left' )
  56. g_dxGUI['titleText1']:text( 'KEYS: \n' ..
  57. 'F4 \n' ..
  58. 'F5 \n' ..
  59. 'ENTER' )
  60. g_dxGUI['titleText2']:text( '\n' ..
  61. '- TRAFFIC ARROWS \n' ..
  62. '- TOP TIMES \n' ..
  63. '- RETRY' )
  64. hideGUIComponents('titleImage','titleText1','titleText2')
  65. end
  66.  
  67. function TitleScreen.show()
  68. showGUIComponents('titleImage','titleText1','titleText2')
  69. guiMoveToBack(g_GUI['titleImage'])
  70. TitleScreen.startTime = getTickCount()
  71. TitleScreen.bringForward = 0
  72. addEventHandler('onClientRender', g_Root, TitleScreen.update)
  73. end
  74.  
  75. function TitleScreen.update()
  76. local secondsLeft = TitleScreen.getTicksRemaining() / 1000
  77. local alpha = math.min(1,math.max( secondsLeft ,0))
  78. guiSetAlpha(g_GUI['titleImage'], alpha)
  79. g_dxGUI['titleText1']:color(220,220,220,255*alpha)
  80. g_dxGUI['titleText2']:color(220,220,220,255*alpha)
  81. if alpha == 0 then
  82. hideGUIComponents('titleImage','titleText1','titleText2')
  83. removeEventHandler('onClientRender', g_Root, TitleScreen.update)
  84. end
  85. end
  86.  
  87. function TitleScreen.getTicksRemaining()
  88. return math.max( 0, TitleScreen.startTime - TitleScreen.bringForward + 10000 - getTickCount() )
  89. end
  90.  
  91. -- Start the fadeout as soon as possible
  92. function TitleScreen.bringForwardFadeout(maxSkip)
  93. local ticksLeft = TitleScreen.getTicksRemaining()
  94. local bringForward = ticksLeft - 1000
  95. outputDebug( 'MISC', 'bringForward ' .. bringForward )
  96. if bringForward > 0 then
  97. TitleScreen.bringForward = math.min(TitleScreen.bringForward + bringForward,maxSkip)
  98. outputDebug( 'MISC', 'TitleScreen.bringForward ' .. TitleScreen.bringForward )
  99. end
  100. end
  101. -------------------------------------------------------
  102.  
  103.  
  104. -------------------------------------------------------
  105. -- Travel screen - Message for client feedback when loading maps
  106. -------------------------------------------------------
  107. TravelScreen = {}
  108. TravelScreen.startTime = 0
  109.  
  110. function TravelScreen.init()
  111. local screenWidth, screenHeight = guiGetScreenSize()
  112. g_GUI['travelImage'] = guiCreateStaticImage(screenWidth/2-256, screenHeight/2-90, 512, 256, 'img/travelling.png', false, nil)
  113. g_dxGUI['travelText1'] = dxText:create('Travelling to', screenWidth/2, screenHeight/2-130, false, 'bankgothic', 0.60, 'center' )
  114. g_dxGUI['travelText2'] = dxText:create('', screenWidth/2, screenHeight/2-100, false, 'bankgothic', 0.70, 'center' )
  115. g_dxGUI['travelText3'] = dxText:create('', screenWidth/2, screenHeight/2-70, false, 'bankgothic', 0.70, 'center' )
  116. g_dxGUI['travelText1']:color(240,240,240)
  117. hideGUIComponents('travelImage', 'travelText1', 'travelText2', 'travelText3')
  118. end
  119.  
  120. function TravelScreen.show( mapName, authorName )
  121. TravelScreen.startTime = getTickCount()
  122. g_dxGUI['travelText2']:text(mapName)
  123. g_dxGUI['travelText3']:text(authorName and "Author: " .. authorName or "")
  124. showGUIComponents('travelImage', 'travelText1', 'travelText2', 'travelText3')
  125. guiMoveToBack(g_GUI['travelImage'])
  126. end
  127.  
  128. function TravelScreen.hide()
  129. hideGUIComponents('travelImage', 'travelText1', 'travelText2', 'travelText3')
  130. end
  131.  
  132. function TravelScreen.getTicksRemaining()
  133. return math.max( 0, TravelScreen.startTime + 3000 - getTickCount() )
  134. end
  135. -------------------------------------------------------
  136.  
  137.  
  138. -- Called from server
  139. function notifyLoadingMap( mapName, authorName )
  140. fadeCamera( false, 0.0, 0,0,0 ) -- fadeout, instant, black
  141. TravelScreen.show( mapName, authorName )
  142. end
  143.  
  144.  
  145. -- Called from server
  146. function initRace(vehicle, checkpoints, objects, pickups, mapoptions, ranked, duration, gameoptions, mapinfo, playerInfo)
  147. outputDebug( 'MISC', 'initRace start' )
  148. unloadAll()
  149.  
  150. g_Players = getElementsByType('player')
  151. g_MapOptions = mapoptions
  152. g_GameOptions = gameoptions
  153. g_MapInfo = mapinfo
  154. g_PlayerInfo = playerInfo
  155. triggerEvent('onClientMapStarting', g_Me, mapinfo )
  156.  
  157. g_dxGUI.mapdisplay:text("Map: "..g_MapInfo.name)
  158.  
  159. fadeCamera(true)
  160. showHUD(false)
  161.  
  162. g_Vehicle = vehicle
  163. setVehicleDamageProof(g_Vehicle, true)
  164. OverrideClient.updateVars(g_Vehicle)
  165.  
  166. --local x, y, z = getElementPosition(g_Vehicle)
  167. setCameraBehindVehicle(vehicle)
  168. --alignVehicleToGround(vehicle)
  169. updateVehicleWeapons()
  170. setCloudsEnabled(g_GameOptions.cloudsenable)
  171. setBlurLevel(0)
  172. g_dxGUI.mapdisplay:visible(g_GameOptions.showmapname)
  173. if engineSetAsynchronousLoading then
  174. engineSetAsynchronousLoading( g_GameOptions.asyncloading )
  175. end
  176.  
  177. -- checkpoints
  178. g_Checkpoints = checkpoints
  179.  
  180. -- pickups
  181. local object
  182. local pos
  183. local colshape
  184. for i,pickup in pairs(pickups) do
  185. pos = pickup.position
  186. object = createObject(g_ModelForPickupType[pickup.type], pos[1], pos[2], pos[3])
  187. setElementCollisionsEnabled(object, false)
  188. colshape = createColSphere(pos[1], pos[2], pos[3], 3.5)
  189. g_Pickups[colshape] = { object = object }
  190. for k,v in pairs(pickup) do
  191. g_Pickups[colshape][k] = v
  192. end
  193. g_Pickups[colshape].load = true
  194. if g_Pickups[colshape].type == 'vehiclechange' then
  195. g_Pickups[colshape].label = dxText:create(getVehicleNameFromModel(g_Pickups[colshape].vehicle), 0.5, 0.5)
  196. g_Pickups[colshape].label:color(255, 255, 255, 0)
  197. g_Pickups[colshape].label:type("shadow",2)
  198. end
  199. end
  200.  
  201. -- objects
  202. g_Objects = {}
  203. local pos, rot
  204. for i,object in ipairs(objects) do
  205. pos = object.position
  206. rot = object.rotation
  207. g_Objects[i] = createObject(object.model, pos[1], pos[2], pos[3], rot[1], rot[2], rot[3])
  208. end
  209.  
  210. if #g_Checkpoints > 0 then
  211. g_CurrentCheckpoint = 0
  212. showNextCheckpoint()
  213. end
  214.  
  215. -- GUI
  216. g_dxGUI.timepassed:text('0:00:00')
  217. showGUIComponents('healthbar', 'speedbar', 'timepassed')
  218. hideGUIComponents('timeleftbg', 'timeleft')
  219. if ranked then
  220. showGUIComponents('ranknum', 'ranksuffix')
  221. else
  222. hideGUIComponents('ranknum', 'ranksuffix')
  223. end
  224. if #g_Checkpoints > 0 then
  225. showGUIComponents('checkpoint')
  226. else
  227. hideGUIComponents('checkpoint')
  228. end
  229.  
  230. g_HurryDuration = g_GameOptions.hurrytime
  231. if duration then
  232. launchRace(duration)
  233. end
  234.  
  235. fadeCamera( false, 0.0 )
  236.  
  237. -- Editor start
  238. if isEditor() then
  239. editorInitRace()
  240. return
  241. end
  242.  
  243. -- Min 3 seconds on travel message
  244. local delay = TravelScreen.getTicksRemaining()
  245. delay = math.max(50,delay)
  246. setTimer(TravelScreen.hide,delay,1)
  247.  
  248. -- Delay readyness until after title
  249. TitleScreen.bringForwardFadeout(3000)
  250. delay = delay + math.max( 0, TitleScreen.getTicksRemaining() - 1500 )
  251.  
  252. -- Do fadeup and then tell server client is ready
  253. setTimer(fadeCamera, delay + 750, 1, true, 10.0)
  254. setTimer(fadeCamera, delay + 1500, 1, true, 2.0)
  255.  
  256. setTimer( function() triggerServerEvent('onNotifyPlayerReady', g_Me) end, delay + 3500, 1 )
  257. outputDebug( 'MISC', 'initRace end' )
  258. setTimer( function() setCameraBehindVehicle( g_Vehicle ) end, delay + 300, 1 )
  259. end
  260.  
  261. -- Called from the server when settings are changed
  262. function updateOptions ( gameoptions, mapoptions )
  263. -- Update
  264. g_GameOptions = gameoptions
  265. g_MapOptions = mapoptions
  266.  
  267. -- Apply
  268. updateVehicleWeapons()
  269. setCloudsEnabled(g_GameOptions.cloudsenable)
  270. setBlurLevel(g_GameOptions.blurlevel)
  271. g_dxGUI.mapdisplay:visible(g_GameOptions.showmapname)
  272. if engineSetAsynchronousLoading then
  273. engineSetAsynchronousLoading( g_GameOptions.asyncloading )
  274. end
  275. end
  276.  
  277. function launchRace(duration)
  278. g_Players = getElementsByType('player')
  279.  
  280. if type(duration) == 'number' then
  281. showGUIComponents('timeleftbg', 'timeleft')
  282. guiLabelSetColor(g_GUI.timeleft, 255, 255, 255)
  283. g_Duration = duration
  284. addEventHandler('onClientRender', g_Root, updateTime)
  285. end
  286.  
  287. setVehicleDamageProof(g_Vehicle, false)
  288.  
  289. g_StartTick = getTickCount()
  290. end
  291.  
  292.  
  293. addEventHandler('onClientElementStreamIn', g_Root,
  294. function()
  295. local colshape = table.find(g_Pickups, 'object', source)
  296. if colshape then
  297. local pickup = g_Pickups[colshape]
  298. if pickup.label then
  299. pickup.label:color(255, 255, 255, 0)
  300. pickup.label:visible(false)
  301. pickup.labelInRange = false
  302. end
  303. g_VisiblePickups[colshape] = source
  304. end
  305. end
  306. )
  307.  
  308. addEventHandler('onClientElementStreamOut', g_Root,
  309. function()
  310. local colshape = table.find(g_VisiblePickups, source)
  311. if colshape then
  312. local pickup = g_Pickups[colshape]
  313. if pickup.label then
  314. pickup.label:color(255, 255, 255, 0)
  315. pickup.label:visible(false)
  316. pickup.labelInRange = nil
  317. end
  318. g_VisiblePickups[colshape] = nil
  319. end
  320. end
  321. )
  322.  
  323. function updatePickups()
  324. local angle = math.fmod((getTickCount() - g_PickupStartTick) * 360 / 2000, 360)
  325. local g_Pickups = g_Pickups
  326. local pickup, x, y, cX, cY, cZ, pickX, pickY, pickZ
  327. for colshape,elem in pairs(g_VisiblePickups) do
  328. pickup = g_Pickups[colshape]
  329. if pickup.load then
  330. setElementRotation(elem, 0, 0, angle)
  331. if pickup.label then
  332. cX, cY, cZ = getCameraMatrix()
  333. pickX, pickY, pickZ = unpack(pickup.position)
  334. x, y = getScreenFromWorldPosition(pickX, pickY, pickZ + 2.85, 0.08 )
  335. local distanceToPickup = getDistanceBetweenPoints3D(cX, cY, cZ, pickX, pickY, pickZ)
  336. if distanceToPickup > 80 then
  337. pickup.labelInRange = false
  338. pickup.label:visible(false)
  339. elseif x then
  340. if distanceToPickup < 60 then
  341. if isLineOfSightClear(cX, cY, cZ, pickX, pickY, pickZ, true, false, false, true, false) then
  342. if not pickup.labelInRange then
  343. if pickup.anim then
  344. pickup.anim:remove()
  345. end
  346. pickup.anim = Animation.createAndPlay(
  347. pickup.label,
  348. Animation.presets.dxTextFadeIn(500)
  349. )
  350. pickup.labelInRange = true
  351. pickup.labelVisible = true
  352. end
  353. if not pickup.labelVisible then
  354. pickup.label:color(255, 255, 255, 255)
  355. end
  356. pickup.label:visible(true)
  357. else
  358. pickup.label:color(255, 255, 255, 0)
  359. pickup.labelVisible = false
  360. pickup.label:visible(false)
  361. end
  362. else
  363. if pickup.labelInRange then
  364. if pickup.anim then
  365. pickup.anim:remove()
  366. end
  367. pickup.anim = Animation.createAndPlay(
  368. pickup.label,
  369. Animation.presets.dxTextFadeOut(1000)
  370. )
  371. pickup.labelInRange = false
  372. pickup.labelVisible = false
  373. pickup.label:visible(true)
  374. end
  375. end
  376. local scale = (60/distanceToPickup)*0.7
  377. pickup.label:scale(scale)
  378. pickup.label:position(x, y, false)
  379. else
  380. pickup.label:color(255, 255, 255, 0)
  381. pickup.labelVisible = false
  382. pickup.label:visible(false)
  383. end
  384. if Spectate.fadedout then
  385. pickup.label:visible(false) -- Hide pickup labels when screen is black
  386. end
  387. end
  388. else
  389. if pickup.label then
  390. pickup.label:visible(false)
  391. if pickup.labelInRange then
  392. pickup.label:color(255, 255, 255, 0)
  393. pickup.labelInRange = false
  394. end
  395. end
  396. end
  397. end
  398. end
  399. addEventHandler('onClientRender', g_Root, updatePickups)
  400.  
  401. addEventHandler('onClientColShapeHit', g_Root,
  402. function(elem)
  403. local pickup = g_Pickups[source]
  404. outputDebug( 'CHECKPOINT', 'onClientColShapeHit'
  405. .. ' elem:' .. tostring(elem)
  406. .. ' g_Vehicle:' .. tostring(g_Vehicle)
  407. .. ' isVehicleBlown(g_Vehicle):' .. tostring(isVehicleBlown(g_Vehicle))
  408. .. ' g_Me:' .. tostring(g_Me)
  409. .. ' getElementHealth(g_Me):' .. tostring(getElementHealth(g_Me))
  410. .. ' source:' .. tostring(source)
  411. .. ' pickup:' .. tostring(pickup)
  412. )
  413. if elem ~= g_Vehicle or not pickup or isVehicleBlown(g_Vehicle) or getElementHealth(g_Me) == 0 then
  414. return
  415. end
  416. if pickup.load then
  417. handleHitPickup(pickup)
  418. end
  419. end
  420. )
  421.  
  422. function handleHitPickup(pickup)
  423. if pickup.type == 'vehiclechange' then
  424. if pickup.vehicle == getElementModel(g_Vehicle) then
  425. return
  426. end
  427. local health = nil
  428. g_PrevVehicleHeight = getElementDistanceFromCentreOfMassToBaseOfModel(g_Vehicle)
  429. alignVehicleWithUp()
  430. if checkModelIsAirplane(pickup.vehicle) then -- Hack fix for Issue #4104
  431. health = getElementHealth(g_Vehicle)
  432. end
  433. setElementModel(g_Vehicle, pickup.vehicle)
  434. if health then
  435. fixVehicle(g_Vehicle)
  436. setElementHealth(g_Vehicle, health)
  437. end
  438. vehicleChanging(g_MapOptions.classicchangez, pickup.vehicle)
  439. elseif pickup.type == 'nitro' then
  440. addVehicleUpgrade(g_Vehicle, 1010)
  441. elseif pickup.type == 'repair' then
  442. fixVehicle(g_Vehicle)
  443. end
  444. triggerServerEvent('onPlayerPickUpRacePickupInternal', g_Me, pickup.id, pickup.respawn)
  445. playSoundFrontEnd(46)
  446. end
  447.  
  448. function removeVehicleNitro()
  449. removeVehicleUpgrade(g_Vehicle, 1010)
  450. end
  451.  
  452. function unloadPickup(pickupID)
  453. for colshape,pickup in pairs(g_Pickups) do
  454. if pickup.id == pickupID then
  455. pickup.load = false
  456. setElementAlpha(pickup.object, 0)
  457. return
  458. end
  459. end
  460. end
  461.  
  462. function loadPickup(pickupID)
  463. for colshape,pickup in pairs(g_Pickups) do
  464. if pickup.id == pickupID then
  465. setElementAlpha(pickup.object, 255)
  466. pickup.load = true
  467. if isElementWithinColShape(g_Vehicle, colshape) then
  468. handleHitPickup(pickup)
  469. end
  470. return
  471. end
  472. end
  473. end
  474.  
  475. function vehicleChanging( changez, newModel )
  476. if getElementModel(g_Vehicle) ~= newModel then
  477. outputConsole( "Vehicle change model mismatch (" .. tostring(getElementModel(g_Vehicle)) .. "/" .. tostring(newModel) .. ")" )
  478. end
  479. local newVehicleHeight = getElementDistanceFromCentreOfMassToBaseOfModel(g_Vehicle)
  480. local x, y, z = getElementPosition(g_Vehicle)
  481. if g_PrevVehicleHeight and newVehicleHeight > g_PrevVehicleHeight then
  482. z = z - g_PrevVehicleHeight + newVehicleHeight
  483. end
  484. if changez then
  485. z = z + 1
  486. end
  487. setElementPosition(g_Vehicle, x, y, z)
  488. g_PrevVehicleHeight = nil
  489. updateVehicleWeapons()
  490. checkVehicleIsHelicopter()
  491. end
  492.  
  493. function updateVehicleWeapons()
  494. if g_Vehicle then
  495. local weapons = not g_ArmedVehicleIDs[getElementModel(g_Vehicle)] or g_MapOptions.vehicleweapons
  496. toggleControl('vehicle_fire', weapons)
  497. if getElementModel(g_Vehicle) == g_HunterID and not g_MapOptions.hunterminigun then
  498. weapons = false
  499. end
  500. toggleControl('vehicle_secondary_fire', weapons)
  501. end
  502. end
  503.  
  504. function vehicleUnloading()
  505. g_Vehicle = nil
  506. end
  507.  
  508. function updateBars()
  509. if g_Vehicle then
  510. g_GUI.healthbar:setProgress(getElementHealth(g_Vehicle))
  511. local vx, vy, vz = getElementVelocity(g_Vehicle)
  512. g_GUI.speedbar:setProgress(math.sqrt(vx*vx + vy*vy + vz*vz))
  513. end
  514. end
  515.  
  516. function updateTime()
  517. local tick = getTickCount()
  518. local msPassed = tick - g_StartTick
  519. if not isPlayerFinished(g_Me) then
  520. g_dxGUI.timepassed:text(msToTimeStr(msPassed))
  521. end
  522. local timeLeft = g_Duration - msPassed
  523. guiSetText(g_GUI.timeleft, msToTimeStr(timeLeft > 0 and timeLeft or 0))
  524. if g_HurryDuration and g_GUI.hurry == nil and timeLeft <= g_HurryDuration then
  525. startHurry()
  526. end
  527. end
  528.  
  529. addEventHandler('onClientElementDataChange', g_Me,
  530. function(dataName)
  531. if dataName == 'race rank' and not Spectate.active then
  532. setRankDisplay( getElementData(g_Me, 'race rank') )
  533. end
  534. end,
  535. false
  536. )
  537.  
  538. function setRankDisplay( rank )
  539. if not tonumber(rank) then
  540. g_dxGUI.ranknum:text('')
  541. g_dxGUI.ranksuffix:text('')
  542. return
  543. end
  544. g_dxGUI.ranknum:text(tostring(rank))
  545. g_dxGUI.ranksuffix:text( (rank < 10 or rank > 20) and ({ [1] = 'st', [2] = 'nd', [3] = 'rd' })[rank % 10] or 'th' )
  546. end
  547.  
  548.  
  549. addEventHandler('onClientElementDataChange', g_Root,
  550. function(dataName)
  551. if dataName == 'race.finished' then
  552. if isPlayerFinished(source) then
  553. Spectate.dropCamera( source, 2000 )
  554. end
  555. end
  556. if dataName == 'race.spectating' then
  557. if isPlayerSpectating(source) then
  558. Spectate.validateTarget( source ) -- No spectate at this player
  559. end
  560. end
  561. end
  562. )
  563.  
  564.  
  565. function checkWater()
  566. if g_Vehicle then
  567. if not g_WaterCraftIDs[getElementModel(g_Vehicle)] then
  568. local x, y, z = getElementPosition(g_Me)
  569. local waterZ = getWaterLevel(x, y, z)
  570. if waterZ and z < waterZ - 0.5 and not isPlayerRaceDead(g_Me) and not isPlayerFinished(g_Me) and g_MapOptions then
  571. if g_MapOptions.firewater then
  572. blowVehicle ( g_Vehicle, true )
  573. else
  574. setElementHealth(g_Me,0)
  575. triggerServerEvent('onRequestKillPlayer',g_Me)
  576. end
  577. end
  578. end
  579. -- Check stalled vehicle
  580. if not getVehicleEngineState( g_Vehicle ) then
  581. setVehicleEngineState( g_Vehicle, true )
  582. end
  583. -- Check dead vehicle
  584. if getElementHealth( g_Vehicle ) == 0 and not isPlayerRaceDead(g_Me) and not isPlayerFinished(g_Me)then
  585. setElementHealth(g_Me,0)
  586. triggerServerEvent('onRequestKillPlayer',g_Me)
  587. end
  588. end
  589. end
  590.  
  591. function showNextCheckpoint(bOtherPlayer)
  592. g_CurrentCheckpoint = g_CurrentCheckpoint + 1
  593. local i = g_CurrentCheckpoint
  594. g_dxGUI.checkpoint:text((i - 1) .. ' / ' .. #g_Checkpoints)
  595. if i > 1 then
  596. destroyCheckpoint(i-1)
  597. else
  598. createCheckpoint(1)
  599. end
  600. makeCheckpointCurrent(i,bOtherPlayer)
  601. if i < #g_Checkpoints then
  602. local curCheckpoint = g_Checkpoints[i]
  603. local nextCheckpoint = g_Checkpoints[i+1]
  604. local nextMarker = createCheckpoint(i+1)
  605. setMarkerTarget(curCheckpoint.marker, unpack(nextCheckpoint.position))
  606. end
  607. if not Spectate.active then
  608. setElementData(g_Me, 'race.checkpoint', i)
  609. end
  610. end
  611.  
  612. -------------------------------------------------------------------------------
  613. -- Show checkpoints and rank info that is relevant to the player being spectated
  614. local prevWhich = nil
  615. local cpValuePrev = nil
  616. local rankValuePrev = nil
  617.  
  618. function updateSpectatingCheckpointsAndRank()
  619. local which = getWhichDataSourceToUse()
  620.  
  621. -- Do nothing if we are keeping the last thing displayed
  622. if which == "keeplast" then
  623. return
  624. end
  625.  
  626. local dataSourceChangedToLocal = which ~= prevWhich and which=="local"
  627. local dataSourceChangedFromLocal = which ~= prevWhich and prevWhich=="local"
  628. prevWhich = which
  629.  
  630. if dataSourceChangedFromLocal or dataSourceChangedToLocal then
  631. cpValuePrev = nil
  632. rankValuePrev = nil
  633. end
  634.  
  635. if Spectate.active or dataSourceChangedToLocal then
  636. local watchedPlayer = getWatchedPlayer()
  637.  
  638. if g_CurrentCheckpoint and g_Checkpoints and #g_Checkpoints > 0 then
  639. local cpValue = getElementData(watchedPlayer, 'race.checkpoint') or 0
  640. if cpValue > 0 and cpValue <= #g_Checkpoints then
  641. if cpValue ~= cpValuePrev then
  642. cpValuePrev = cpValue
  643. setCurrentCheckpoint( cpValue, Spectate.active and watchedPlayer ~= g_Me )
  644. end
  645. end
  646. end
  647.  
  648. local rankValue = getElementData(watchedPlayer, 'race rank') or 0
  649. if rankValue ~= rankValuePrev then
  650. rankValuePrev = rankValue
  651. setRankDisplay( rankValue )
  652. end
  653. end
  654. end
  655.  
  656. -- "local" If not spectating
  657. -- "spectarget" If spectating valid target
  658. -- "keeplast" If spectating nil target and dropcam
  659. -- "local" If spectating nil target and no dropcam
  660. function getWhichDataSourceToUse()
  661. if not Spectate.active then return "local" end
  662. if Spectate.target then return "spectarget" end
  663. if Spectate.hasDroppedCamera() then return "keeplast" end
  664. return "local"
  665. end
  666.  
  667. function getWatchedPlayer()
  668. if not Spectate.active then return g_Me end
  669. if Spectate.target then return Spectate.target end
  670. if Spectate.hasDroppedCamera() then return nil end
  671. return g_Me
  672. end
  673. -------------------------------------------------------------------------------
  674.  
  675. function checkpointReached(elem)
  676. outputDebug( 'CP', 'checkpointReached'
  677. .. ' ' .. tostring(g_CurrentCheckpoint)
  678. .. ' elem:' .. tostring(elem)
  679. .. ' g_Vehicle:' .. tostring(g_Vehicle)
  680. .. ' isVehicleBlown(g_Vehicle):' .. tostring(isVehicleBlown(g_Vehicle))
  681. .. ' g_Me:' .. tostring(g_Me)
  682. .. ' getElementHealth(g_Me):' .. tostring(getElementHealth(g_Me))
  683. )
  684. if elem ~= g_Vehicle or isVehicleBlown(g_Vehicle) or getElementHealth(g_Me) == 0 or Spectate.active then
  685. return
  686. end
  687.  
  688. if g_Checkpoints[g_CurrentCheckpoint].vehicle and g_Checkpoints[g_CurrentCheckpoint].vehicle ~= getElementModel(g_Vehicle) then
  689. g_PrevVehicleHeight = getElementDistanceFromCentreOfMassToBaseOfModel(g_Vehicle)
  690. local health = nil
  691. alignVehicleWithUp()
  692. if checkModelIsAirplane(g_Checkpoints[g_CurrentCheckpoint].vehicle) then -- Hack fix for Issue #4104
  693. health = getElementHealth(g_Vehicle)
  694. end
  695. setElementModel(g_Vehicle, g_Checkpoints[g_CurrentCheckpoint].vehicle)
  696. if health then
  697. fixVehicle(g_Vehicle)
  698. setElementHealth(g_Vehicle, health)
  699. end
  700. vehicleChanging(g_MapOptions.classicchangez, g_Checkpoints[g_CurrentCheckpoint].vehicle)
  701. end
  702. triggerServerEvent('onPlayerReachCheckpointInternal', g_Me, g_CurrentCheckpoint)
  703. playSoundFrontEnd(43)
  704. if g_CurrentCheckpoint < #g_Checkpoints then
  705. showNextCheckpoint()
  706. else
  707. g_dxGUI.checkpoint:text(#g_Checkpoints .. ' / ' .. #g_Checkpoints)
  708. local rc = getRadioChannel()
  709. setRadioChannel(0)
  710. addEventHandler("onClientPlayerRadioSwitch", g_Root, onChange)
  711. playSound("audio/mission_accomplished.mp3")
  712. setTimer(changeRadioStation, 8000, 1, rc)
  713. if g_GUI.hurry then
  714. Animation.createAndPlay(g_GUI.hurry, Animation.presets.guiFadeOut(500), destroyElement)
  715. g_GUI.hurry = false
  716. end
  717. destroyCheckpoint(#g_Checkpoints)
  718. triggerEvent('onClientPlayerFinish', g_Me)
  719. toggleAllControls(false, true, false)
  720. end
  721. end
  722.  
  723. function onChange()
  724. cancelEvent()
  725. end
  726.  
  727. function changeRadioStation(rc)
  728. removeEventHandler("onClientPlayerRadioSwitch", g_Root, onChange)
  729. setRadioChannel(tonumber(rc))
  730. end
  731.  
  732. function startHurry()
  733. if not isPlayerFinished(g_Me) then
  734. local screenWidth, screenHeight = guiGetScreenSize()
  735. local w, h = resAdjust(370), resAdjust(112)
  736. g_GUI.hurry = guiCreateStaticImage(screenWidth/2 - w/2, screenHeight - h - 40, w, h, 'img/hurry.png', false, nil)
  737. guiSetAlpha(g_GUI.hurry, 0)
  738. Animation.createAndPlay(g_GUI.hurry, Animation.presets.guiFadeIn(800))
  739. Animation.createAndPlay(g_GUI.hurry, Animation.presets.guiPulse(1000))
  740. end
  741. guiLabelSetColor(g_GUI.timeleft, 255, 0, 0)
  742. end
  743.  
  744. function setTimeLeft(timeLeft)
  745. g_Duration = (getTickCount() - g_StartTick) + timeLeft
  746. end
  747.  
  748. -----------------------------------------------------------------------
  749. -- Spectate
  750. -----------------------------------------------------------------------
  751. Spectate = {}
  752. Spectate.active = false
  753. Spectate.target = nil
  754. Spectate.blockUntilTimes = {}
  755. Spectate.savePos = false
  756. Spectate.manual = false
  757. Spectate.droppedCameraTimer = Timer:create()
  758. Spectate.tickTimer = Timer:create()
  759. Spectate.fadedout = true
  760. Spectate.blockManual = false
  761. Spectate.blockManualTimer = nil
  762.  
  763.  
  764. -- Request to switch on
  765. function Spectate.start(type)
  766. outputDebug( 'SPECTATE', 'Spectate.start '..type )
  767. assert(type=='manual' or type=='auto', "Spectate.start : type == auto or manual")
  768. Spectate.blockManual = false
  769. if type == 'manual' then
  770. if Spectate.active then
  771. return -- Ignore if manual request and already on
  772. end
  773. Spectate.savePos = true -- Savepos and start if manual request and was off
  774. elseif type == 'auto' then
  775. Spectate.savePos = false -- Clear restore pos if an auto spectate is requested
  776. end
  777. if not Spectate.active then
  778. Spectate._start() -- Switch on here, if was off
  779. end
  780. end
  781.  
  782.  
  783. -- Request to switch off
  784. function Spectate.stop(type)
  785. outputDebug( 'SPECTATE', 'Spectate.stop '..type )
  786. assert(type=='manual' or type=='auto', "Spectate.stop : type == auto or manual")
  787. if type == 'auto' then
  788. Spectate.savePos = false -- Clear restore pos if an auto spectate is requested
  789. end
  790. if Spectate.active then
  791. Spectate._stop() -- Switch off here, if was on
  792. end
  793. end
  794.  
  795.  
  796. function Spectate._start()
  797. outputDebug( 'SPECTATE', 'Spectate._start ' )
  798. triggerServerEvent('onClientNotifySpectate', g_Me, true )
  799. assert(not Spectate.active, "Spectate._start - not Spectate.active")
  800. local screenWidth, screenHeight = guiGetScreenSize()
  801. g_GUI.specprev = guiCreateStaticImage(screenWidth/2 - 100 - 58, screenHeight - 123, 58, 82, 'img/specprev.png', false, nil)
  802. g_GUI.specprevhi = guiCreateStaticImage(screenWidth/2 - 100 - 58, screenHeight - 123, 58, 82, 'img/specprev_hi.png', false, nil)
  803. g_GUI.specnext = guiCreateStaticImage(screenWidth/2 + 100, screenHeight - 123, 58, 82, 'img/specnext.png', false, nil)
  804. g_GUI.specnexthi = guiCreateStaticImage(screenWidth/2 + 100, screenHeight - 123, 58, 82, 'img/specnext_hi.png', false, nil)
  805. g_GUI.speclabel = guiCreateLabel(screenWidth/2 - 100, screenHeight - 100, 200, 70, '', false)
  806. Spectate.updateGuiFadedOut()
  807. guiLabelSetHorizontalAlign(g_GUI.speclabel, 'center')
  808. hideGUIComponents('specprevhi', 'specnexthi')
  809. if Spectate.savePos then
  810. savePosition()
  811. end
  812. Spectate.setTarget( Spectate.findNewTarget(g_Me,1) )
  813. bindKey('arrow_l', 'down', Spectate.previous)
  814. bindKey('arrow_r', 'down', Spectate.next)
  815. MovePlayerAway.start()
  816. Spectate.setTarget( Spectate.target )
  817. Spectate.validateTarget(Spectate.target)
  818. Spectate.tickTimer:setTimer( Spectate.tick, 500, 0 )
  819. end
  820.  
  821. -- Stop spectating. Will restore position if Spectate.savePos is set
  822. function Spectate._stop()
  823. Spectate.cancelDropCamera()
  824. Spectate.tickTimer:killTimer()
  825. triggerServerEvent('onClientNotifySpectate', g_Me, false )
  826. outputDebug( 'SPECTATE', 'Spectate._stop ' )
  827. assert(Spectate.active, "Spectate._stop - Spectate.active")
  828. for i,name in ipairs({'specprev', 'specprevhi', 'specnext', 'specnexthi', 'speclabel'}) do
  829. if g_GUI[name] then
  830. destroyElement(g_GUI[name])
  831. g_GUI[name] = nil
  832. end
  833. end
  834. unbindKey('arrow_l', 'down', Spectate.previous)
  835. unbindKey('arrow_r', 'down', Spectate.next)
  836. MovePlayerAway.stop()
  837. setCameraTarget(g_Me)
  838. Spectate.target = nil
  839. Spectate.active = false
  840. if Spectate.savePos then
  841. Spectate.savePos = false
  842. restorePosition()
  843. end
  844. end
  845.  
  846. function Spectate.previous(bGUIFeedback)
  847. Spectate.setTarget( Spectate.findNewTarget(Spectate.target,-1) )
  848. if bGUIFeedback then
  849. setGUIComponentsVisible({ specprev = false, specprevhi = true })
  850. setTimer(setGUIComponentsVisible, 100, 1, { specprevhi = false, specprev = true })
  851. end
  852. end
  853.  
  854. function Spectate.next(bGUIFeedback)
  855. Spectate.setTarget( Spectate.findNewTarget(Spectate.target,1) )
  856. if bGUIFeedback then
  857. setGUIComponentsVisible({ specnext = false, specnexthi = true })
  858. setTimer(setGUIComponentsVisible, 100, 1, { specnexthi = false, specnext = true })
  859. end
  860. end
  861.  
  862. ---------------------------------------------
  863. -- Step along to the next player to spectate
  864. local playersRankSorted = {}
  865. local playersRankSortedTime = 0
  866.  
  867. function Spectate.findNewTarget(current,dir)
  868.  
  869. -- Time to update sorted list?
  870. local bUpdateSortedList = ( getTickCount() - playersRankSortedTime > 1000 )
  871.  
  872. -- Need to update sorted list because g_Players has changed size?
  873. bUpdateSortedList = bUpdateSortedList or ( #playersRankSorted ~= #g_Players )
  874.  
  875. if not bUpdateSortedList then
  876. -- Check playersRankSorted contains the same elements as g_Players
  877. for _,item in ipairs(playersRankSorted) do
  878. if not table.find(g_Players, item.player) then
  879. bUpdateSortedList = true
  880. break
  881. end
  882. end
  883. end
  884.  
  885. -- Update sorted list if required
  886. if bUpdateSortedList then
  887. -- Remake list
  888. playersRankSorted = {}
  889. for _,player in ipairs(g_Players) do
  890. local rank = tonumber(getElementData(player, 'race rank')) or 0
  891. table.insert( playersRankSorted, {player=player, rank=rank} )
  892. end
  893. -- Sort it by rank
  894. table.sort(playersRankSorted, function(a,b) return(a.rank > b.rank) end)
  895.  
  896. playersRankSortedTime = getTickCount()
  897. end
  898.  
  899. -- Find next player in list
  900. local pos = table.find(playersRankSorted, 'player', current) or 1
  901. for i=1,#playersRankSorted do
  902. pos = ((pos + dir - 1) % #playersRankSorted ) + 1
  903. if Spectate.isValidTarget(playersRankSorted[pos].player) then
  904. return playersRankSorted[pos].player
  905. end
  906. end
  907. return nil
  908. end
  909. ---------------------------------------------
  910.  
  911. function Spectate.isValidTarget(player)
  912. if player == nil then
  913. return true
  914. end
  915. if player == g_Me or isPlayerFinished(player) or isPlayerRaceDead(player) or isPlayerSpectating(player) then
  916. return false
  917. end
  918. if ( Spectate.blockUntilTimes[player] or 0 ) > getTickCount() then
  919. return false
  920. end
  921. if not table.find(g_Players, player) or not isElement(player) then
  922. return false
  923. end
  924. local x,y,z = getElementPosition(player)
  925. if z > 20000 then
  926. return false
  927. end
  928. if x > -1 and x < 1 and y > -1 and y < 1 then
  929. return false
  930. end
  931. return true
  932. end
  933.  
  934. -- If player is the current target, check to make sure is valid
  935. function Spectate.validateTarget(player)
  936. if Spectate.active and player == Spectate.target then
  937. if not Spectate.isValidTarget(player) then
  938. Spectate.previous(false)
  939. end
  940. end
  941. end
  942.  
  943. function Spectate.dropCamera( player, time )
  944. if Spectate.active and player == Spectate.target then
  945. if not Spectate.hasDroppedCamera() then
  946. setCameraMatrix( getCameraMatrix() )
  947. Spectate.target = nil
  948. Spectate.droppedCameraTimer:setTimer(Spectate.cancelDropCamera, time, 1, player )
  949. end
  950. end
  951. end
  952.  
  953. function Spectate.hasDroppedCamera()
  954. return Spectate.droppedCameraTimer:isActive()
  955. end
  956.  
  957. function Spectate.cancelDropCamera()
  958. if Spectate.hasDroppedCamera() then
  959. Spectate.droppedCameraTimer:killTimer()
  960. Spectate.tick()
  961. end
  962. end
  963.  
  964.  
  965. function Spectate.setTarget( player )
  966. if Spectate.hasDroppedCamera() then
  967. return
  968. end
  969.  
  970. Spectate.active = true
  971. Spectate.target = player
  972. if Spectate.target then
  973. if Spectate.getCameraTargetPlayer() ~= Spectate.target then
  974. setCameraTarget(Spectate.target)
  975. end
  976. guiSetText(g_GUI.speclabel, 'Currently spectating:\n' .. getPlayerName(Spectate.target))
  977. else
  978. local x,y,z = getElementPosition(g_Me)
  979. x = x - ( x % 32 )
  980. y = y - ( y % 32 )
  981. z = getGroundPosition ( x, y, 5000 ) or 40
  982. setCameraTarget( g_Me )
  983. setCameraMatrix( x,y,z+10,x,y+50,z+60)
  984. guiSetText(g_GUI.speclabel, 'Currently spectating:\n No one to spectate')
  985. end
  986. if Spectate.active and Spectate.savePos then
  987. guiSetText(g_GUI.speclabel, guiGetText(g_GUI.speclabel) .. "\n\nPress 'B' to join")
  988. end
  989. end
  990.  
  991. function Spectate.blockAsTarget( player, ticks )
  992. Spectate.blockUntilTimes[player] = getTickCount() + ticks
  993. Spectate.validateTarget(player)
  994. end
  995.  
  996. function Spectate.tick()
  997. if Spectate.target and Spectate.getCameraTargetPlayer() and Spectate.getCameraTargetPlayer() ~= Spectate.target then
  998. if Spectate.isValidTarget(Spectate.target) then
  999. setCameraTarget(Spectate.target)
  1000. return
  1001. end
  1002. end
  1003. if not Spectate.target or ( Spectate.getCameraTargetPlayer() and Spectate.getCameraTargetPlayer() ~= Spectate.target ) or not Spectate.isValidTarget(Spectate.target) then
  1004. Spectate.previous(false)
  1005. end
  1006. end
  1007.  
  1008. function Spectate.getCameraTargetPlayer()
  1009. local element = getCameraTarget()
  1010. if element and getElementType(element) == "vehicle" then
  1011. element = getVehicleController(element)
  1012. end
  1013. return element
  1014. end
  1015.  
  1016.  
  1017. g_SavedPos = {}
  1018. function savePosition()
  1019. g_SavedPos.x, g_SavedPos.y, g_SavedPos.z = getElementPosition(g_Me)
  1020. g_SavedPos.rz = getPedRotation(g_Me)
  1021. g_SavedPos.vx, g_SavedPos.vy, g_SavedPos.vz = getElementPosition(g_Vehicle)
  1022. g_SavedPos.vrx, g_SavedPos.vry, g_SavedPos.vrz = getElementRotation(g_Vehicle)
  1023. end
  1024.  
  1025. function restorePosition()
  1026. setElementPosition( g_Me, g_SavedPos.x, g_SavedPos.y, g_SavedPos.z )
  1027. setPedRotation( g_Me, g_SavedPos.rz )
  1028. setElementPosition( g_Vehicle, g_SavedPos.vx, g_SavedPos.vy, g_SavedPos.vz )
  1029. setElementRotation( g_Vehicle, g_SavedPos.vrx, g_SavedPos.vry, g_SavedPos.vrz )
  1030. end
  1031.  
  1032.  
  1033. addEvent ( "onClientScreenFadedOut", true )
  1034. addEventHandler ( "onClientScreenFadedOut", g_Root,
  1035. function()
  1036. Spectate.fadedout = true
  1037. Spectate.updateGuiFadedOut()
  1038. end
  1039. )
  1040.  
  1041. addEvent ( "onClientScreenFadedIn", true )
  1042. addEventHandler ( "onClientScreenFadedIn", g_Root,
  1043. function()
  1044. Spectate.fadedout = false
  1045. Spectate.updateGuiFadedOut()
  1046. end
  1047. )
  1048.  
  1049. addEvent ( "onClientPreRender", true )
  1050. addEventHandler ( "onClientPreRender", g_Root,
  1051. function()
  1052. if isPlayerRaceDead( g_Me ) then
  1053. setCameraMatrix( getCameraMatrix() )
  1054. end
  1055. updateSpectatingCheckpointsAndRank()
  1056. end
  1057. )
  1058.  
  1059. function Spectate.updateGuiFadedOut()
  1060. if g_GUI and g_GUI.specprev then
  1061. if Spectate.fadedout then
  1062. setGUIComponentsVisible({ specprev = false, specnext = false, speclabel = false })
  1063. else
  1064. setGUIComponentsVisible({ specprev = true, specnext = true, speclabel = true })
  1065. end
  1066. end
  1067. end
  1068.  
  1069. -----------------------------------------------------------------------
  1070.  
  1071. -----------------------------------------------------------------------
  1072. -- MovePlayerAway - Super hack - Fixes the spec cam problem
  1073. -----------------------------------------------------------------------
  1074. MovePlayerAway = {}
  1075. MovePlayerAway.timer = Timer:create()
  1076. MovePlayerAway.posX = 0
  1077. MovePlayerAway.posY = 0
  1078. MovePlayerAway.posZ = 0
  1079. MovePlayerAway.rotZ = 0
  1080. MovePlayerAway.health = 0
  1081.  
  1082. function MovePlayerAway.start()
  1083. local element = g_Vehicle or getPedOccupiedVehicle(g_Me) or g_Me
  1084. MovePlayerAway.posX, MovePlayerAway.posY, MovePlayerAway.posZ = getElementPosition(element)
  1085. MovePlayerAway.posZ = 34567 + math.random(0,4000)
  1086. MovePlayerAway.rotZ = 0
  1087. MovePlayerAway.health = math.max(1,getElementHealth(element))
  1088. setElementHealth( element, 2000 )
  1089. setElementHealth( g_Me, 90 )
  1090. MovePlayerAway.update(true)
  1091. MovePlayerAway.timer:setTimer(MovePlayerAway.update,500,0)
  1092. triggerServerEvent("onRequestMoveAwayBegin", g_Me)
  1093. end
  1094.  
  1095.  
  1096. function MovePlayerAway.update(nozcheck)
  1097. -- Move our player far away
  1098. local camTarget = getCameraTarget()
  1099. if not getPedOccupiedVehicle(g_Me) then
  1100. setElementPosition( g_Me, MovePlayerAway.posX-10, MovePlayerAway.posY-10, MovePlayerAway.posZ )
  1101. end
  1102. if getPedOccupiedVehicle(g_Me) then
  1103. if not nozcheck then
  1104. if camTarget then
  1105. MovePlayerAway.posX, MovePlayerAway.posY = getElementPosition(camTarget)
  1106. if getElementType(camTarget) ~= "vehicle" then
  1107. outputDebug( 'SPECTATE', 'camera target type:' .. getElementType(camTarget) )
  1108. end
  1109. if getElementType(camTarget) == 'ped' then
  1110. MovePlayerAway.rotZ = getPedRotation(camTarget)
  1111. else
  1112. _,_, MovePlayerAway.rotZ = getElementRotation(camTarget)
  1113. end
  1114. end
  1115. end
  1116. local vehicle = g_Vehicle
  1117. if vehicle then
  1118. fixVehicle( vehicle )
  1119. setElementFrozen ( vehicle, true )
  1120. setElementPosition( vehicle, MovePlayerAway.posX, MovePlayerAway.posY, MovePlayerAway.posZ )
  1121. setElementVelocity( vehicle, 0,0,0 )
  1122. setVehicleTurnVelocity( vehicle, 0,0,0 )
  1123. setElementRotation ( vehicle, 0,0,MovePlayerAway.rotZ )
  1124. end
  1125. end
  1126. setElementHealth( g_Me, 90 )
  1127.  
  1128. if camTarget and camTarget ~= getCameraTarget() then
  1129. setCameraTarget(camTarget)
  1130. end
  1131. end
  1132.  
  1133. function MovePlayerAway.stop()
  1134. triggerServerEvent("onRequestMoveAwayEnd", g_Me)
  1135. if MovePlayerAway.timer:isActive() then
  1136. MovePlayerAway.timer:killTimer()
  1137. local vehicle = g_Vehicle
  1138. if vehicle then
  1139. setElementVelocity( vehicle, 0,0,0 )
  1140. setVehicleTurnVelocity( vehicle, 0,0,0 )
  1141. setElementFrozen ( vehicle, false )
  1142. setVehicleDamageProof ( vehicle, false )
  1143. setElementHealth ( vehicle, MovePlayerAway.health )
  1144. end
  1145. setElementVelocity( g_Me, 0,0,0 )
  1146. end
  1147. end
  1148.  
  1149. -----------------------------------------------------------------------
  1150. -- Camera transition for our player's respawn
  1151. -----------------------------------------------------------------------
  1152. function remoteStopSpectateAndBlack()
  1153. Spectate.stop('auto')
  1154. fadeCamera(false,0.0, 0,0,0) -- Instant black
  1155. end
  1156.  
  1157. function remoteSoonFadeIn( bNoCameraMove )
  1158. setTimer(fadeCamera,250+500,1,true,1.0) -- And up
  1159. if not bNoCameraMove then
  1160. setTimer( function() setCameraBehindVehicle( g_Vehicle ) end ,250+500-150,1 )
  1161. end
  1162. setTimer(checkVehicleIsHelicopter,250+500,1)
  1163. end
  1164. -----------------------------------------------------------------------
  1165.  
  1166. function raceTimeout()
  1167. removeEventHandler('onClientRender', g_Root, updateTime)
  1168. if g_CurrentCheckpoint then
  1169. destroyCheckpoint(g_CurrentCheckpoint)
  1170. destroyCheckpoint(g_CurrentCheckpoint + 1)
  1171. end
  1172. guiSetText(g_GUI.timeleft, msToTimeStr(0))
  1173. if g_GUI.hurry then
  1174. Animation.createAndPlay(g_GUI.hurry, Animation.presets.guiFadeOut(500), destroyElement)
  1175. g_GUI.hurry = nil
  1176. end
  1177. triggerEvent("onClientPlayerOutOfTime", g_Me)
  1178. toggleAllControls(false, true, false)
  1179. end
  1180.  
  1181. function unloadAll()
  1182. triggerEvent('onClientMapStopping', g_Me)
  1183. for i=1,#g_Checkpoints do
  1184. destroyCheckpoint(i)
  1185. end
  1186. g_Checkpoints = {}
  1187. g_CurrentCheckpoint = nil
  1188.  
  1189. for colshape,pickup in pairs(g_Pickups) do
  1190. destroyElement(colshape)
  1191. if pickup.object then
  1192. destroyElement(pickup.object)
  1193. end
  1194. if pickup.label then
  1195. pickup.label:destroy()
  1196. end
  1197. end
  1198. g_Pickups = {}
  1199. g_VisiblePickups = {}
  1200.  
  1201. table.each(g_Objects, destroyElement)
  1202. g_Objects = {}
  1203.  
  1204. setElementData(g_Me, 'race.checkpoint', nil)
  1205.  
  1206. g_Vehicle = nil
  1207. removeEventHandler('onClientRender', g_Root, updateTime)
  1208.  
  1209. toggleAllControls(true)
  1210.  
  1211. if g_GUI then
  1212. hideGUIComponents('timeleftbg', 'timeleft', 'healthbar', 'speedbar', 'ranknum', 'ranksuffix', 'checkpoint', 'timepassed')
  1213. if g_GUI.hurry then
  1214. Animation.createAndPlay(g_GUI.hurry, Animation.presets.guiFadeOut(500), destroyElement)
  1215. g_GUI.hurry = nil
  1216. end
  1217. end
  1218. TimerManager.destroyTimersFor("map")
  1219. g_StartTick = nil
  1220. g_HurryDuration = nil
  1221. if Spectate.active then
  1222. Spectate.stop('auto')
  1223. end
  1224. end
  1225.  
  1226. function createCheckpoint(i)
  1227. local checkpoint = g_Checkpoints[i]
  1228. if checkpoint.marker then
  1229. return
  1230. end
  1231. local pos = checkpoint.position
  1232. local color = checkpoint.color or { 0, 0, 255 }
  1233. checkpoint.marker = createMarker(pos[1], pos[2], pos[3], checkpoint.type or 'checkpoint', checkpoint.size, color[1], color[2], color[3])
  1234. if (not checkpoint.type or checkpoint.type == 'checkpoint') and i == #g_Checkpoints then
  1235. setMarkerIcon(checkpoint.marker, 'finish')
  1236. end
  1237. if checkpoint.type == 'ring' and i < #g_Checkpoints then
  1238. setMarkerTarget(checkpoint.marker, unpack(g_Checkpoints[i+1].position))
  1239. end
  1240. checkpoint.blip = createBlip(pos[1], pos[2], pos[3], 0, isCurrent and 2 or 1, color[1], color[2], color[3])
  1241. setBlipOrdering(checkpoint.blip, 1)
  1242. return checkpoint.marker
  1243. end
  1244.  
  1245. function makeCheckpointCurrent(i,bOtherPlayer)
  1246. local checkpoint = g_Checkpoints[i]
  1247. local pos = checkpoint.position
  1248. local color = checkpoint.color or { 255, 0, 0 }
  1249. if not checkpoint.blip then
  1250. checkpoint.blip = createBlip(pos[1], pos[2], pos[3], 0, 2, color[1], color[2], color[3])
  1251. setBlipOrdering(checkpoint.blip, 1)
  1252. else
  1253. setBlipSize(checkpoint.blip, 2)
  1254. end
  1255.  
  1256. if not checkpoint.type or checkpoint.type == 'checkpoint' then
  1257. checkpoint.colshape = createColCircle(pos[1], pos[2], checkpoint.size + 4)
  1258. else
  1259. checkpoint.colshape = createColSphere(pos[1], pos[2], pos[3], checkpoint.size + 4)
  1260. end
  1261. if not bOtherPlayer then
  1262. addEventHandler('onClientColShapeHit', checkpoint.colshape, checkpointReached)
  1263. end
  1264. end
  1265.  
  1266. function destroyCheckpoint(i)
  1267. local checkpoint = g_Checkpoints[i]
  1268. if checkpoint and checkpoint.marker then
  1269. destroyElement(checkpoint.marker)
  1270. checkpoint.marker = nil
  1271. destroyElement(checkpoint.blip)
  1272. checkpoint.blip = nil
  1273. if checkpoint.colshape then
  1274. destroyElement(checkpoint.colshape)
  1275. checkpoint.colshape = nil
  1276. end
  1277. end
  1278. end
  1279.  
  1280. function setCurrentCheckpoint(i, bOtherPlayer)
  1281. destroyCheckpoint(g_CurrentCheckpoint)
  1282. destroyCheckpoint(g_CurrentCheckpoint + 1)
  1283. createCheckpoint(i)
  1284. g_CurrentCheckpoint = i - 1
  1285. showNextCheckpoint(bOtherPlayer)
  1286. end
  1287.  
  1288. function isPlayerRaceDead(player)
  1289. return not getElementHealth(player) or getElementHealth(player) < 1e-45 or isPlayerDead(player)
  1290. end
  1291.  
  1292. function isPlayerFinished(player)
  1293. return getElementData(player, 'race.finished')
  1294. end
  1295.  
  1296. function isPlayerSpectating(player)
  1297. return getElementData(player, 'race.spectating')
  1298. end
  1299.  
  1300. addEventHandler('onClientPlayerJoin', g_Root,
  1301. function()
  1302. table.insertUnique(g_Players, source)
  1303. end
  1304. )
  1305.  
  1306. addEventHandler('onClientPlayerSpawn', g_Root,
  1307. function()
  1308. Spectate.blockAsTarget( source, 2000 ) -- No spectate at this player for 2 seconds
  1309. end
  1310. )
  1311.  
  1312. addEventHandler('onClientPlayerWasted', g_Root,
  1313. function()
  1314. if not g_StartTick then
  1315. return
  1316. end
  1317. local player = source
  1318. local vehicle = getPedOccupiedVehicle(player)
  1319. if player == g_Me then
  1320. if #g_Players > 1 and (g_MapOptions.respawn == 'none' or g_MapOptions.respawntime >= 10000) then
  1321. if Spectate.blockManualTimer and isTimer(Spectate.blockManualTimer) then
  1322. killTimer(Spectate.blockManualTimer)
  1323. end
  1324. TimerManager.createTimerFor("map"):setTimer(Spectate.start, 2000, 1, 'auto')
  1325. end
  1326. else
  1327. Spectate.dropCamera( player, 1000 )
  1328. end
  1329. end
  1330. )
  1331.  
  1332. addEventHandler('onClientPlayerQuit', g_Root,
  1333. function()
  1334. table.removevalue(g_Players, source)
  1335. Spectate.blockUntilTimes[source] = nil
  1336. Spectate.validateTarget(source) -- No spectate at this player
  1337. end
  1338. )
  1339.  
  1340. addEventHandler('onClientResourceStop', g_ResRoot,
  1341. function()
  1342. unloadAll()
  1343. removeEventHandler('onClientRender', g_Root, updateBars)
  1344. killTimer(g_WaterCheckTimer)
  1345. showHUD(true)
  1346. setPedCanBeKnockedOffBike(g_Me, true)
  1347. end
  1348. )
  1349.  
  1350. ------------------------
  1351. -- Make vehicle upright
  1352.  
  1353. function directionToRotation2D( x, y )
  1354. return rem( math.atan2( y, x ) * (360/6.28) - 90, 360 )
  1355. end
  1356.  
  1357. function alignVehicleWithUp()
  1358. local vehicle = g_Vehicle
  1359. if not vehicle then return end
  1360.  
  1361. local matrix = getElementMatrix( vehicle )
  1362. local Right = Vector3D:new( matrix[1][1], matrix[1][2], matrix[1][3] )
  1363. local Fwd = Vector3D:new( matrix[2][1], matrix[2][2], matrix[2][3] )
  1364. local Up = Vector3D:new( matrix[3][1], matrix[3][2], matrix[3][3] )
  1365.  
  1366. local Velocity = Vector3D:new( getElementVelocity( vehicle ) )
  1367. local rz
  1368.  
  1369. if Velocity:Length() > 0.05 and Up.z < 0.001 then
  1370. -- If velocity is valid, and we are upside down, use it to determine rotation
  1371. rz = directionToRotation2D( Velocity.x, Velocity.y )
  1372. else
  1373. -- Otherwise use facing direction to determine rotation
  1374. rz = directionToRotation2D( Fwd.x, Fwd.y )
  1375. end
  1376.  
  1377. setElementRotation( vehicle, 0, 0, rz )
  1378. end
  1379.  
  1380.  
  1381. ------------------------
  1382. -- Script integrity test
  1383.  
  1384. setTimer(
  1385. function ()
  1386. if g_Vehicle and not isElement(g_Vehicle) then
  1387. outputChatBox( "Race integrity test fail (client): Your vehicle has been destroyed. Please panic." )
  1388. end
  1389. end,
  1390. 1000,0
  1391. )
  1392.  
  1393. ---------------------------------------------------------------------------
  1394. --
  1395. -- Commands and binds
  1396. --
  1397. --
  1398. --
  1399. ---------------------------------------------------------------------------
  1400.  
  1401.  
  1402. function kill()
  1403. if Spectate.active then
  1404. if Spectate.savePos then
  1405. triggerServerEvent('onClientRequestSpectate', g_Me, false )
  1406. end
  1407. else
  1408. Spectate.blockManual = true
  1409. triggerServerEvent('onRequestKillPlayer', g_Me)
  1410. Spectate.blockManualTimer = setTimer(function() Spectate.blockManual = false end, 3000, 1)
  1411. end
  1412. end
  1413. addCommandHandler('kill',kill)
  1414. addCommandHandler('Commit suicide',kill)
  1415. bindKey ( next(getBoundKeys"enter_exit"), "down", "Commit suicide" )
  1416.  
  1417.  
  1418. function spectate()
  1419. if Spectate.active then
  1420. if Spectate.savePos then
  1421. triggerServerEvent('onClientRequestSpectate', g_Me, false )
  1422. end
  1423. else
  1424. if not Spectate.blockManual then
  1425. triggerServerEvent('onClientRequestSpectate', g_Me, true )
  1426. end
  1427. end
  1428. end
  1429. addCommandHandler('spectate',spectate)
  1430. addCommandHandler('Toggle spectator',spectate)
  1431. bindKey("b","down","Toggle spectator")
  1432.  
  1433. function setPipeDebug(bOn)
  1434. g_bPipeDebug = bOn
  1435. outputConsole( 'bPipeDebug set to ' .. tostring(g_bPipeDebug) )
  1436. end
Advertisement
Add Comment
Please, Sign In to add comment