Advertisement
Guest User

unit_teleport.lua

a guest
Nov 28th, 2012
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.07 KB | None | 0 0
  1. function gadget:GetInfo()
  2. return {
  3. name = "Teleporter",
  4. desc = "Implements mass teleporter",
  5. author = "Google Frog",
  6. date = "29 Feb 2012",
  7. license = "GNU GPL, v2 or later",
  8. layer = 0,
  9. enabled = true -- loaded by default?
  10. }
  11. end
  12.  
  13. include("LuaRules/Configs/customcmds.h.lua")
  14. -------------------------------------------------------------------------------------
  15. -------------------------------------------------------------------------------------
  16.  
  17. --local BEACON_PLACE_RANGE_SQR = 80000^2 -- causes SIGFPE, max tested value is ~46340^2 (see http://code.google.com/p/zero-k/issues/detail?id=1506)
  18. --local BEACON_PLACE_RANGE_MOVE = 75000
  19. local BEACON_WAIT_RANGE_MOVE = 150
  20. local BEACON_TELEPORT_RADIUS = 200
  21. local BEACON_TELEPORT_RADIUS_SQR = BEACON_TELEPORT_RADIUS^2
  22.  
  23. if (gadgetHandler:IsSyncedCode()) then
  24.  
  25. -------------------------------------------------------------------------------------
  26. -------------------------------------------------------------------------------------
  27. -- SYNCED
  28. -------------------------------------------------------------------------------------
  29. -------------------------------------------------------------------------------------
  30.  
  31. local placeBeaconCmdDesc = {
  32. id = CMD_PLACE_BEACON,
  33. type = CMDTYPE.ICON_MAP,
  34. name = 'Beacon',
  35. cursor = 'Unload units',
  36. action = 'placebeacon',
  37. tooltip = 'Place teleport entrance at selected location.',
  38. }
  39.  
  40. local waitAtBeaconCmdDesc = {
  41. id = CMD_WAIT_AT_BEACON,
  42. type = CMDTYPE.ICON_UNIT,
  43. name = 'Beacon Queue',
  44. cursor = 'Load units',
  45. action = 'beaconqueue',
  46. tooltip = 'Wait to be teleported by a beacon.',
  47. }
  48.  
  49. local function isUnitAirborne(unitID)
  50. x, y, z = Spring.GetUnitBasePosition(unitID)
  51. gy = Spring.GetGroundHeight(x, z)
  52. diff = y-gy
  53. return diff>Spring.GetUnitHeight(unitID)
  54. end
  55.  
  56. local function magnitudeOfThreeDVector(x,y,z)
  57. return math.sqrt((x*x)+(y*y)+(z*z))
  58. end
  59.  
  60. local function capUnitSpeed(unitID, speedCap, slowPower)
  61. local vx,vy,vz = Spring.GetUnitVelocity(unitID)
  62. if(magnitudeOfThreeDVector(vx,vy,vz) > speedCap) then
  63. newx = vx*slowPower*-1
  64. newy = vy*slowPower*-1
  65. newz = vz*slowPower*-1
  66. Spring.AddUnitImpulse(unitID,newx,newy,newz)
  67. end
  68. end
  69.  
  70. local function FindLaunchSpeed(gravity, relX,relY,relZ, apexHeight, startX, startY,startZ)
  71. local yVel = math.sqrt(4*(gravity/2)*(-1*(math.max(apexHeight, apexHeight+relY))))
  72. local timeOfFlight = (-yVel - math.sqrt(yVel^2 - 4*(gravity/2)*(-relY)))/(2*(-gravity/2))
  73. local isPossible = "true"
  74. if (timeOfFlight ~= timeOfFlight) then --NaN check
  75. isPossible = "NeedNegativeGravity"
  76. return
  77. end
  78. ----
  79. local xzDistance = math.sqrt(relX*relX+relZ*relZ)
  80. local xzVel = xzDistance/timeOfFlight
  81. local directionxz_radian = math.atan2(relZ/xzDistance, relX/xzDistance)
  82. local xVel = math.cos(directionxz_radian)*xzVel
  83. local zVel = math.sin(directionxz_radian)*xzVel
  84.  
  85. if startX and startZ and startZ then
  86. local x =nil
  87. local z =nil
  88. for frame=0, timeOfFlight*0.75 do
  89. x = startX + xVel*frame
  90. z = startZ + zVel*frame
  91. if (Spring.GetGroundHeight(x,z) - 30) > startY+(yVel*frame + gravity*frame*frame/2) then
  92. isPossible = "obstacle"
  93. break
  94. end
  95. end
  96. end
  97. return isPossible, xVel,yVel,zVel, timeOfFlight
  98. end
  99. -------------------------------------------------------------------------------------
  100. -------------------------------------------------------------------------------------
  101.  
  102. local teleDef = {
  103. [UnitDefNames["amphtele"].id] = true,
  104. }
  105.  
  106. local beaconDef = UnitDefNames["tele_beacon"].id
  107.  
  108. -- frames to teleport = unit mass * COST_FACTOR
  109. local COST_FACTOR = 0.5
  110.  
  111. local offset = {
  112. [0] = {x = 1, z = 0},
  113. [1] = {x = 1, z = 1},
  114. [2] = {x = 0, z = 1},
  115. [3] = {x = -1, z = 1},
  116. [4] = {x = 0, z = -1},
  117. [5] = {x = -1, z = -1},
  118. [6] = {x = 1, z = -1},
  119. [7] = {x = -1, z = 0},
  120. }
  121.  
  122. -------------------------------------------------------------------------------------
  123. -------------------------------------------------------------------------------------
  124.  
  125. local teleID = {count = 0, data = {}}
  126. local tele = {}
  127. local beacon = {}
  128.  
  129. local beaconWaiter = {}
  130. local teleportingUnit = {}
  131.  
  132. --[[
  133. local nearRead = 1
  134. local nearWrite = 2
  135. local nearBeacon = {
  136. [1] = {},
  137. [2] = {},
  138. }--]]
  139.  
  140. local checkFrame = {}
  141. local launchedUnits={}
  142.  
  143. -------------------------------------------------------------------------------------
  144. -------------------------------------------------------------------------------------
  145. -- Most script interaction
  146.  
  147. local function callScript(unitID, funcName, args)
  148. local func = Spring.UnitScript.GetScriptEnv(unitID)
  149. if func then
  150. func = func[funcName]
  151. if func then
  152. return Spring.UnitScript.CallAsUnit(unitID,func, args)
  153. end
  154. end
  155. return false
  156. end
  157.  
  158. local function backUpTheDamnQueue(teleportieeID)
  159. if launchedUnits[teleportieeID] and Spring.ValidUnitID(teleportieeID) and UnitDefs[unitDefID] then --find out if this unit is in our launch list
  160. local myQueue = launchedUnits[teleportieeID].queue --retrieve saved command queue
  161. local tmpQueue ={}
  162. tmpQueue[1]={CMD.STOP,{},{""}} --add 1st row with STOP (to flush existing command)
  163. for i=2, #myQueue do --copied from unit_jumpjet.lua by quantum. Convert command queue readable by "Spring.GiveOrderArrayToUnitArray", also start at index 2 to skip "enter teleport beacon" command at 1st row
  164. local cmd = myQueue[i]
  165. local cmdOpt = cmd.options
  166. local opts = {"shift"} -- appending
  167. if (cmdOpt.alt) then opts[#opts+1] = "alt" end
  168. if (cmdOpt.ctrl) then opts[#opts+1] = "ctrl" end
  169. if (cmdOpt.right) then opts[#opts+1] = "right" end
  170. tmpQueue[#tmpQueue+1] = {cmd.id, cmd.params, opts}
  171. end
  172. Spring.GiveOrderArrayToUnitArray({teleportieeID},tmpQueue) --restore old command queue
  173. end
  174. end
  175.  
  176. local function changeSpeed(tid, bid, speed)
  177. local func = Spring.UnitScript.GetScriptEnv(tid).activity_mode
  178. Spring.UnitScript.CallAsUnit(tid,func,speed)
  179. if bid then
  180. local func = Spring.UnitScript.GetScriptEnv(bid).activity_mode
  181. Spring.UnitScript.CallAsUnit(bid,func,speed)
  182. end
  183. end
  184.  
  185. local function interruptTeleport(unitID, doNotChangeSpeed)
  186. if tele[unitID].teleportiee then
  187. teleportingUnit[tele[unitID].teleportiee] = nil
  188. end
  189. tele[unitID].teleFrame = false
  190. tele[unitID].cost = false
  191.  
  192. Spring.SetUnitRulesParam(unitID,"teleportend",0)
  193.  
  194. if tele[unitID].link then
  195. local func = Spring.UnitScript.GetScriptEnv(tele[unitID].link).endTeleOutLoop
  196. Spring.UnitScript.CallAsUnit(tele[unitID].link,func)
  197. Spring.SetUnitRulesParam(tele[unitID].link,"teleportend",0)
  198. end
  199.  
  200. if not doNotChangeSpeed and tele[unitID].deployed then
  201. changeSpeed(unitID, tele[unitID].link, 2)
  202. end
  203. end
  204.  
  205. function GG.tele_ableToDeploy(unitID)
  206. return tele[unitID].link and not tele[unitID].deployed
  207. end
  208.  
  209. function GG.tele_deployTeleport(unitID)
  210. tele[unitID].deployed = true
  211. checkFrame[Spring.GetGameFrame() + 1] = true
  212.  
  213. changeSpeed(unitID, tele[unitID].link, 2)
  214. end
  215.  
  216. function GG.tele_undeployTeleport(unitID)
  217. if tele[unitID].deployed then
  218. interruptTeleport(unitID)
  219. end
  220. tele[unitID].deployed = false
  221. changeSpeed(unitID, tele[unitID].link, 1)
  222. end
  223.  
  224. function GG.tele_createBeacon(unitID,x,z)
  225. local y = Spring.GetGroundHeight(x,z)
  226. local place, feature = Spring.TestBuildOrder(beaconDef, x, y, z, 1)
  227. changeSpeed(unitID, nil, 1)
  228. if place == 2 and feature == nil then
  229. if tele[unitID].link and Spring.ValidUnitID(tele[unitID].link) then
  230. Spring.DestroyUnit(tele[unitID].link, true)
  231. end
  232. Spring.PlaySoundFile("sounds/misc/teleport2.wav", 10, x, Spring.GetGroundHeight(x,z) or 0, z)
  233. local beaconID = Spring.CreateUnit(beaconDef, x, y, z, 1, Spring.GetUnitTeam(unitID))
  234. Spring.SetUnitPosition(beaconID, x, y, z)
  235. tele[unitID].link = beaconID
  236. beacon[beaconID] = {link = unitID, x = x, z = z}
  237. end
  238. Spring.GiveOrderToUnit(unitID,CMD.WAIT, {}, {})
  239. Spring.GiveOrderToUnit(unitID,CMD.WAIT, {}, {})
  240. end
  241.  
  242. local function undeployTeleport(unitID)
  243. if tele[unitID].deployed then
  244. local func = Spring.UnitScript.GetScriptEnv(unitID).UndeployTeleport
  245. Spring.UnitScript.CallAsUnit(unitID,func)
  246. GG.tele_undeployTeleport(unitID)
  247. end
  248. end
  249.  
  250.  
  251. -------------------------------------------------------------------------------------
  252. -------------------------------------------------------------------------------------
  253. -- Handle Teleportation
  254.  
  255. function gadget:AllowCommand(unitID, unitDefID, teamID,
  256. cmdID, cmdParams, cmdOptions)
  257.  
  258. if teleportingUnit[unitID] and cmdID ~= CMD.INSERT and cmdID ~= CMD.REMOVE and cmdID ~= CMD.FIRESTATE and cmdID ~= CMD.MOVESTATE and cmdID ~= CMD.CLOAK then
  259. interruptTeleport(teleportingUnit[unitID])
  260. end
  261.  
  262. local ud = UnitDefs[unitDefID]
  263.  
  264. if not ud
  265. or
  266. (ud.speed == 0 or ud.isBomber or ud.isFighter)
  267. or
  268. not (
  269. (cmdID == CMD.GUARD and cmdParams[1] and beacon[cmdParams[1]])
  270. or
  271. (cmdID == CMD.INSERT and cmdParams[2] == CMD.GUARD and beacon[cmdParams[4]])
  272. ) then
  273. return true
  274. end
  275.  
  276. local bid = (cmdID == CMD.INSERT and cmdParams[4]) or cmdParams[1]
  277.  
  278. if Spring.GetUnitAllyTeam(unitID) ~= Spring.GetUnitAllyTeam(bid) then
  279. return false
  280. end
  281.  
  282. -- NOTE: param 4 is the first real command param for command insert
  283. beaconWaiter[unitID] = {lastSetMove = false,}
  284. local bx,by,bz = Spring.GetUnitPosition(bid)
  285. local params = {bx, by, bz, bid, Spring.GetGameFrame()}
  286.  
  287. if cmdID == CMD.INSERT then
  288. Spring.GiveOrderToUnit(unitID,CMD.INSERT,{cmdParams[1],CMD_WAIT_AT_BEACON,cmdParams[3], unpack(params)}, {"alt"})
  289. else
  290. local opt = (cmdOptions.shift and {"shift"}) or {}
  291. Spring.GiveOrderToUnit(unitID,CMD_WAIT_AT_BEACON, params, opt)
  292. end
  293.  
  294. return false
  295. end
  296. -------------------------------------------------------------------------------------
  297. -------------------------------------------------------------------------------------
  298. -- Create the beacon
  299.  
  300.  
  301. function gadget:CommandFallback(unitID, unitDefID, teamID, -- keeps getting
  302. cmdID, cmdParams, cmdOptions) -- called until
  303.  
  304. if cmdID == CMD_PLACE_BEACON and tele[unitID] then
  305. local f = Spring.GetGameFrame()
  306. --if not (tele[unitID].lastSetMove and tele[unitID].lastSetMove + 16 == f) then
  307. -- Spring.SetUnitMoveGoal(unitID, cmdParams[1], cmdParams[2], cmdParams[3], BEACON_PLACE_RANGE_MOVE)
  308. --end
  309. tele[unitID].lastSetMove = f
  310.  
  311. local tx, ty, tz = Spring.GetUnitBasePosition(unitID)
  312.  
  313. local ux,_,uz = Spring.GetUnitPosition(unitID)
  314. if --[[BEACON_PLACE_RANGE_SQR > (cmdParams[1]-ux)^2 + (cmdParams[3]-uz)^2 and]] ty == Spring.GetGroundHeight(tx, tz) then
  315. local cx, cz = math.floor((cmdParams[1]+8)/16)*16, math.floor((cmdParams[3]+8)/16)*16
  316. local inLos = Spring.IsPosInLos(cx,0,cz,Spring.GetUnitAllyTeam(unitID))
  317. local blocked = false
  318. if (inLos) then
  319. local place, feature = Spring.TestBuildOrder(beaconDef, cx, 0, cz, 1)
  320. if not (place == 2 and feature == nil) then
  321. blocked = true
  322. end
  323. end
  324.  
  325. if not blocked then
  326. Spring.SetUnitMoveGoal(unitID, ux,Spring.GetGroundHeight(ux,uz),uz,BEACON_PLACE_RANGE_MOVE)
  327. --Spring.Echo("moveto source 289")
  328. Spring.MoveCtrl.Enable(unitID)
  329. Spring.SetUnitVelocity(unitID, 0, 0, 0)
  330. local func = Spring.UnitScript.GetScriptEnv(unitID).Create_Beacon
  331. Spring.UnitScript.CallAsUnit(unitID,func,cx,cz)
  332. end
  333. return true, true -- command was used and remove it
  334. end
  335.  
  336. return true, false -- command was used but don't remove it
  337. end
  338.  
  339. if cmdID == CMD_WAIT_AT_BEACON and beaconWaiter[unitID] then
  340.  
  341. local ud = UnitDefs[UnitDefID]
  342.  
  343. if ud and ((not beacon[cmdParams[4]]) or ud.speed == 0 or ud.isBomber or ud.isFighter) then
  344. return true, true -- command was used and remove it
  345. end
  346.  
  347. local f = Spring.GetGameFrame()
  348. if not ((beaconWaiter[unitID].lastSetMove and beaconWaiter[unitID].lastSetMove + 16 == f)) then
  349. Spring.SetUnitMoveGoal(unitID, cmdParams[1], cmdParams[2], cmdParams[3], BEACON_WAIT_RANGE_MOVE)
  350. --Spring.Echo("moveto source 312")
  351. end
  352. beaconWaiter[unitID].lastSetMove = f
  353.  
  354. local ux,_,uz = Spring.GetUnitPosition(unitID)
  355. if BEACON_TELEPORT_RADIUS_SQR > (cmdParams[1]-ux)^2 + (cmdParams[3]-uz)^2 then
  356.  
  357. if not beaconWaiter[unitID].waitingAtBeacon then
  358. Spring.SetUnitMoveGoal(unitID, ux,Spring.GetGroundHeight(ux,uz),uz,BEACON_PLACE_RANGE_MOVE)
  359. --Spring.Echo("moveto source 321")
  360. beaconWaiter[unitID].waitingAtBeacon = true
  361. end
  362.  
  363. --local bid = cmdParams[4]
  364. --local tid = beacon[bid].link
  365. --nearBeacon[bid] = true
  366. elseif teleportingUnit[unitID] then
  367. interruptTeleport(teleportingUnit[unitID])
  368. end
  369.  
  370. return true, false -- command was used but don't remove it
  371. end
  372.  
  373. return false
  374. end
  375.  
  376. function gadget:GameFrame(f)
  377.  
  378. for i = 1, teleID.count do
  379. local tid = teleID.data[i]
  380. local bid = tele[tid].link
  381. if tele[tid].teleFrame then
  382. local stunned_or_inbuild = Spring.GetUnitIsStunned(tid) or Spring.GetUnitIsStunned(bid)
  383. if stunned_or_inbuild then
  384. if not tele[tid].stunned then
  385. tele[tid].stunned = true
  386.  
  387. Spring.SetUnitRulesParam(tid,"teleportend",tele[tid].teleFrame - f)
  388. Spring.SetUnitRulesParam(bid,"teleportend",tele[tid].teleFrame - f)
  389. end
  390.  
  391. tele[tid].teleFrame = tele[tid].teleFrame + 1
  392. elseif tele[tid].stunned then
  393. checkFrame[tele[tid].teleFrame] = true
  394.  
  395. Spring.SetUnitRulesParam(tid,"teleportend",tele[tid].teleFrame)
  396. Spring.SetUnitRulesParam(bid,"teleportend",tele[tid].teleFrame)
  397.  
  398. tele[tid].stunned = false
  399. end
  400. end
  401. end
  402.  
  403. if f%8 == 0 or checkFrame[f] then
  404.  
  405. if checkFrame[f] then
  406. checkFrame[f] = nil
  407. end
  408.  
  409. for i = 1, teleID.count do
  410. local tid = teleID.data[i]
  411. local bid = tele[tid].link
  412.  
  413. if bid and tele[tid].deployed then
  414.  
  415. --Spring.Echo("activated teleporter!")
  416. --checking for flyers
  417. --Spring.Echo(f)
  418. local xxx,yyy,zzz = Spring.GetUnitPosition(tid)
  419. local maybeFlyers = Spring.GetUnitsInSphere(xxx,yyy,zzz,200,Spring.GetUnitTeam(tid))
  420. if(maybeFlyers ~= nil) then
  421. for index,value in pairs(maybeFlyers) do
  422. local ud = Spring.GetUnitDefID(value)
  423. ud = ud and UnitDefs[ud]
  424. if ((not (ud.floater or ud.canFly or value==tid)) and isUnitAirborne(value)) then
  425. capUnitSpeed(value,3,1)
  426. --Spring.Echo("capping unit speed")
  427. --backup the damn queue
  428. backUpTheDamnQueue(value)
  429. end
  430. end
  431. end
  432.  
  433. local teleFinished = tele[tid].teleFrame and f >= tele[tid].teleFrame
  434.  
  435. if teleFinished then
  436.  
  437. local teleportiee = tele[tid].teleportiee
  438.  
  439. local cQueue = Spring.GetCommandQueue(teleportiee, 1)
  440. if cQueue and #cQueue > 0 and cQueue[1].id == CMD_WAIT_AT_BEACON and cQueue[1].params[4] == bid then
  441. local ud = Spring.GetUnitDefID(teleportiee)
  442. ud = ud and UnitDefs[ud]
  443. if ud then
  444. local size = ud.xsize
  445. local ux,uy,uz = Spring.GetUnitPosition(teleportiee)
  446. local tx, ty, tz = Spring.GetUnitPosition(tid)
  447. local dx, dz = tx + offset[tele[tid].offsetIndex].x*(size*4+40), tz + offset[tele[tid].offsetIndex].z*(size*4+40)
  448. local dy
  449.  
  450. if ud.floater or ud.canFly then
  451. dy = uy - math.max(0, Spring.GetGroundHeight(ux,uz)) + math.max(0, Spring.GetGroundHeight(dx,dz))
  452. else
  453. dy = uy - Spring.GetGroundHeight(ux,uz) + Spring.GetGroundHeight(dx,dz)
  454. end
  455.  
  456. Spring.PlaySoundFile("sounds/misc/teleport.wav", 10, ux, uy, uz)
  457. Spring.PlaySoundFile("sounds/misc/teleport2.wav", 10, dx, dy, dz)
  458.  
  459. Spring.SpawnCEG("teleport_out", ux, uy, uz, 0, 0, 0, size)
  460.  
  461.  
  462. teleportingUnit[teleportiee] = nil
  463.  
  464. if not callScript(teleportiee, "unit_teleported", {dx, dy, dz}) then
  465.  
  466. --this is where the magic happens
  467. local thisGravity = -1*Game.gravity/30/30
  468. local relX = ux-tx
  469. local relY = uy-ty
  470. local relZ = uz-tz
  471. local isPossible, xvelocity, yvelocity, zvelocity, flightTime = FindLaunchSpeed(thisGravity, relX, relY, relZ, 3000, ux, uy, uz)
  472.  
  473. --Spring.Echo(xvelocity)
  474. --Spring.Echo(yvelocity)
  475. --Spring.Echo(zvelocity)
  476.  
  477. Spring.SetUnitVelocity(teleportiee, 0,0.1,0) --it can only reset velocity, other value won't work. Bug
  478. Spring.AddUnitImpulse(teleportiee,1,1,1)
  479. Spring.AddUnitImpulse(teleportiee,-1,-1,-1)
  480. Spring.AddUnitImpulse(teleportiee,xvelocity,yvelocity,zvelocity)
  481. --Spring.Echo(isUnitAirborne(teleportiee))
  482.  
  483.  
  484. local myQueue = Spring.GetCommandQueue(teleportiee) --backup current command queue
  485. Spring.GiveOrderToUnit(teleportiee, CMD.INSERT, {0, CMD.MOVE, CMD.OPT_INTERNAL, dx, dy, dz}, {"alt"}) --insert MOVE command toward destination for visual purpose
  486. launchedUnits[teleportiee]={queue = myQueue, destinationx= dx, destinationy= dy, destinationz =dz}
  487.  
  488. --if GG.FallDamage then --WIP
  489. -- GG.FallDamage.ExcludeFriendlyCollision(teleportiee)
  490. --end
  491. end
  492.  
  493. local ux, uy, uz = Spring.GetUnitPosition(teleportiee)
  494. Spring.SpawnCEG("teleport_in", ux, uy, uz, 0, 0, 0, size)
  495.  
  496. Spring.SetUnitMoveGoal(teleportiee, dx,Spring.GetGroundHeight(dx,dz),dz,BEACON_PLACE_RANGE_MOVE)
  497. --Spring.Echo("moveto on line 439")
  498.  
  499.  
  500. Spring.GiveOrderToUnit(teleportiee,CMD.REMOVE, {cQueue[1].tag}, {})
  501.  
  502. Spring.GiveOrderToUnit(teleportiee,CMD.WAIT, {}, {})
  503. Spring.GiveOrderToUnit(teleportiee,CMD.WAIT, {}, {})
  504. end
  505. end
  506.  
  507. interruptTeleport(tid, true)
  508. end
  509.  
  510. if not tele[tid].teleFrame then
  511.  
  512. local bx, bz = beacon[bid].x, beacon[bid].z
  513. local tx, _, tz = Spring.GetUnitPosition(tid)
  514. local units = Spring.GetUnitsInCylinder(bx, bz, BEACON_TELEPORT_RADIUS)
  515. local allyTeam = Spring.GetUnitAllyTeam(bid)
  516.  
  517. local teleportiee = false
  518. local bestPriority = false
  519. local teleTarget = false
  520.  
  521. for i = 1, #units do
  522. local nid = units[i]
  523. if allyTeam == Spring.GetUnitAllyTeam(nid) then
  524. local cQueue = Spring.GetCommandQueue(nid, 1)
  525. if #cQueue > 0 and cQueue[1].id == CMD_WAIT_AT_BEACON and cQueue[1].params[4] == bid and
  526. ((not bestPriority) or cQueue[1].params[5] < bestPriority) then
  527. local ud = Spring.GetUnitDefID(nid)
  528. ud = ud and UnitDefs[ud]
  529. if ud then
  530. local size = ud.xsize
  531. local startCheck = math.floor(math.random(8))
  532. local direction = (math.random() < 0.5 and -1) or 1
  533. for j = 0, 7 do
  534. local spot = (j*direction+startCheck)%8
  535. local place, feature = Spring.TestBuildOrder(ud.id, tx + offset[spot].x*(size*4+40), 0 ,tz + offset[spot].z*(size*4+40), 1)
  536. if (place == 2 and feature == nil) or ud.canFly then
  537. teleportiee = nid
  538. bestPriority = cQueue[1].params[5]
  539. teleTarget = spot
  540. break
  541. end
  542. end
  543. end
  544. end
  545. end
  546. end
  547.  
  548. if teleportiee then
  549. local ud = Spring.GetUnitDefID(teleportiee)
  550. ud = ud and UnitDefs[ud]
  551. if ud then
  552. local cost = math.floor(ud.mass*COST_FACTOR + math.random())
  553. --Spring.Echo(cost/30)
  554. tele[tid].teleportiee = teleportiee
  555. tele[tid].teleFrame = f + cost
  556. tele[tid].offsetIndex = teleTarget
  557. tele[tid].cost = cost
  558.  
  559. Spring.SetUnitRulesParam(tid,"teleportcost",tele[tid].cost)
  560. Spring.SetUnitRulesParam(bid,"teleportcost",tele[tid].cost)
  561.  
  562. Spring.SetUnitRulesParam(tid,"teleportend",tele[tid].teleFrame)
  563. Spring.SetUnitRulesParam(bid,"teleportend",tele[tid].teleFrame)
  564.  
  565. checkFrame[tele[tid].teleFrame] = true
  566. teleportingUnit[teleportiee] = tid
  567.  
  568. changeSpeed(tid, bid, 3)
  569.  
  570. local func = Spring.UnitScript.GetScriptEnv(bid).startTeleOutLoop
  571. Spring.UnitScript.CallAsUnit(bid,func, teleportiee, tid)
  572. end
  573. else
  574. if teleFinished then
  575. changeSpeed(tid, bid, 2)
  576. end
  577. end
  578. end
  579. end
  580. end
  581. end
  582.  
  583. end
  584.  
  585.  
  586. function gadget:UnitPreDamaged(teleportieeID, unitDefID, unitTeam, damage, paralyzer, weaponDefID, attackerID, attackerDefID, attackerTeam) --copied from "unit_fall_damage.lua" gadget by googlefrog.
  587. if launchedUnits[teleportieeID] and (weaponDefID == -2) and attackerID == nil and Spring.ValidUnitID(teleportieeID) and UnitDefs[unitDefID] then --find out if this unit is in our launch list
  588. local vx,vy,vz=Spring.GetUnitVelocity(teleportieeID) --find out if unit is still bouncing
  589. local fixX = 0-vx
  590. local fixY = 0-vy
  591. local fixZ = 0-vz
  592. Spring.AddUnitImpulse(teleportieeID,fixX,fixY,fixZ) --apply negative impulse (brake) propotional to unit speed
  593.  
  594. local myQueue = launchedUnits[teleportieeID].queue --retrieve saved command queue
  595. local tmpQueue ={}
  596. tmpQueue[1]={CMD.STOP,{},{""}} --add 1st row with STOP (to flush existing command)
  597. for i=2, #myQueue do --copied from unit_jumpjet.lua by quantum. Convert command queue readable by "Spring.GiveOrderArrayToUnitArray", also start at index 2 to skip "enter teleport beacon" command at 1st row
  598. local cmd = myQueue[i]
  599. local cmdOpt = cmd.options
  600. local opts = {"shift"} -- appending
  601. if (cmdOpt.alt) then opts[#opts+1] = "alt" end
  602. if (cmdOpt.ctrl) then opts[#opts+1] = "ctrl" end
  603. if (cmdOpt.right) then opts[#opts+1] = "right" end
  604. tmpQueue[#tmpQueue+1] = {cmd.id, cmd.params, opts}
  605. end
  606. Spring.GiveOrderArrayToUnitArray({teleportieeID},tmpQueue) --restore old command queue
  607.  
  608. local _,_,_,x,y,z=Spring.GetUnitPosition(teleportieeID,true) --check unit mid position
  609. local nearX = math.abs(x-launchedUnits[teleportieeID].destinationx) < 50 --is near to actual landing position in x direction?
  610. local nearZ = math.abs(z-launchedUnits[teleportieeID].destinationz) < 50 --is near to actual landing position in z direction?
  611. launchedUnits[teleportieeID] = nil --remove unit from launch list
  612. if GG.FallDamage then
  613. GG.FallDamage.IncludeFriendlyCollision(teleportieeID)
  614. end
  615. if nearX and nearZ then
  616. return 0 -- as cheat: hitting ground don't hurt unit.
  617. else
  618. return damage
  619. end
  620. end
  621. return damage
  622. end
  623.  
  624. -------------------------------------------------------------------------------------
  625. -------------------------------------------------------------------------------------
  626.  
  627. function gadget:UnitCreated(unitID, unitDefID, unitTeam)
  628. if teleDef[unitDefID] then
  629. Spring.InsertUnitCmdDesc(unitID, placeBeaconCmdDesc)
  630.  
  631. teleID.count = teleID.count + 1
  632. teleID.data[teleID.count] = unitID
  633. tele[unitID] = {
  634. index = teleID.count,
  635. lastSetMove = false,
  636. link = false,
  637. teleportiee = false,
  638. teleFrame = false,
  639. offsetIndex = false,
  640. deployed = false,
  641. cost = false,
  642. stunned = Spring.GetUnitIsStunned(unitID),
  643. }
  644. end
  645. end
  646.  
  647. -- Tele automatically undeploy
  648. function gadget:UnitTaken(unitID, unitDefID, oldTeamID, teamID)
  649.  
  650. if beacon[unitID] then
  651. local _,_,_,_,_,oldA = Spring.GetTeamInfo(oldTeamID)
  652. local _,_,_,_,_,newA = Spring.GetTeamInfo(teamID)
  653. if newA ~= oldA then
  654. undeployTeleport(beacon[unitID].link)
  655. end
  656. end
  657. end
  658.  
  659. function gadget:UnitDestroyed(unitID, unitDefID, unitTeam)
  660.  
  661. if teleportingUnit[unitID] then
  662. interruptTeleport(teleportingUnit[unitID])
  663. end
  664.  
  665. if tele[unitID] then
  666. if tele[unitID].link and Spring.ValidUnitID(tele[unitID].link) then
  667. Spring.DestroyUnit(tele[unitID].link, true)
  668. end
  669. tele[teleID.data[teleID.count]].index = tele[unitID].index
  670. teleID.data[tele[unitID].index] = teleID.data[teleID.count]
  671. teleID.data[teleID.count] = nil
  672. tele[unitID] = nil
  673. teleID.count = teleID.count - 1
  674. end
  675. if beacon[unitID] then
  676. undeployTeleport(beacon[unitID].link)
  677. tele[beacon[unitID].link].link = false
  678. interruptTeleport(beacon[unitID].link)
  679. beacon[unitID] = nil
  680. end
  681. end
  682.  
  683. function gadget:Initialize()
  684. _G.tele = tele
  685.  
  686. for _, unitID in ipairs(Spring.GetAllUnits()) do
  687. local unitDefID = Spring.GetUnitDefID(unitID)
  688. local team = Spring.GetUnitTeam(unitID)
  689. gadget:UnitCreated(unitID, unitDefID, team)
  690. end
  691. end
  692.  
  693. else
  694. -------------------------------------------------------------------------------------
  695. -------------------------------------------------------------------------------------
  696. -- UNSYNCED
  697. -------------------------------------------------------------------------------------
  698. -------------------------------------------------------------------------------------
  699. function gadget:Initialize()
  700. gadgetHandler:RegisterCMDID(CMD_PLACE_BEACON)
  701. gadgetHandler:RegisterCMDID(CMD_WAIT_AT_BEACON)
  702.  
  703. Spring.AssignMouseCursor("Beacon", "cursorunload", true)
  704. Spring.AssignMouseCursor("Beacon Queue", "cursorpickup", true)
  705. Spring.SetCustomCommandDrawData(CMD_PLACE_BEACON, "Beacon", {0.2, 0.8, 0, 1})
  706. Spring.SetCustomCommandDrawData(CMD_WAIT_AT_BEACON, "Beacon Queue", {0.1, 0.1, 1, 1})
  707. end
  708.  
  709.  
  710. local glVertex = gl.Vertex
  711. local spIsUnitInView = Spring.IsUnitInView
  712. local spGetUnitPosition = Spring.GetUnitPosition
  713. local spGetUnitLosState = Spring.GetUnitLosState
  714. local spValidUnitID = Spring.ValidUnitID
  715. local spGetMyTeamID = Spring.GetMyTeamID
  716. local spGetMyAllyTeamID = Spring.GetMyAllyTeamID
  717. local spGetModKeyState = Spring.GetModKeyState
  718. local spAreTeamsAllied = Spring.AreTeamsAllied
  719.  
  720. local myTeam = spGetMyTeamID()
  721.  
  722. local function DrawFunc(u1, u2)
  723. glVertex(spGetUnitPosition(u1))
  724. glVertex(spGetUnitPosition(u2))
  725. end
  726.  
  727. function gadget:DrawWorld()
  728.  
  729. local spec, fullview = Spring.GetSpectatingState()
  730. spec = spec or fullview
  731.  
  732. if SYNCED.tele and snext(SYNCED.tele) then
  733. gl.PushAttrib(GL.LINE_BITS)
  734.  
  735. gl.DepthTest(true)
  736.  
  737. gl.LineWidth(2)
  738. gl.LineStipple('')
  739. local tele = SYNCED.tele
  740. local alt,ctrl,meta,shift = spGetModKeyState()
  741. for tid, data in spairs(tele) do
  742. local bid = data.link
  743. local team = Spring.GetUnitTeam(tid)
  744. if spValidUnitID(tid) and spValidUnitID(bid) and (spec or spAreTeamsAllied(myTeam, team)) and (shift or (Spring.IsUnitSelected(tid) or Spring.IsUnitSelected(bid))) then
  745.  
  746. gl.Color(0.1, 0.3, 1, 0.9)
  747. gl.BeginEnd(GL.LINES, DrawFunc, bid, tid)
  748.  
  749. local x,y,z = spGetUnitPosition(bid)
  750.  
  751. gl.DrawGroundCircle(x,y,z, BEACON_TELEPORT_RADIUS, 32)
  752. end
  753.  
  754. end
  755.  
  756. gl.DepthTest(false)
  757. gl.Color(1,1,1,1)
  758. gl.LineStipple(false)
  759.  
  760. gl.PopAttrib()
  761. end
  762.  
  763. end
  764.  
  765.  
  766. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement