Advertisement
Guest User

TFS Pathing Upgrade

a guest
Apr 10th, 2014
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.05 KB | None | 0 0
  1. local progress = false
  2. local nodes = {}
  3. local currentNode = 0
  4. local startPos = {}
  5. local endPos = {}
  6. local found = false
  7. local dirListi = {}
  8. local path = {}
  9. local openNodes = true
  10. local complete = false
  11. local count = 30
  12. local timeToPath = 0
  13.  
  14. local directionsList = {
  15.     {-1, 0},
  16.     {0, 1},
  17.     {1, 0},
  18.     {0, -1},
  19.     {-1, -1},
  20.     {1, -1},
  21.     {1, 1},
  22.     {-1, 1},
  23. }
  24.  
  25. local function newLuaNode()
  26.     openNodes = true
  27.     currentNode = currentNode + 1
  28.     nodes[currentNode] = {place=currentNode, children = {}, active = 1}
  29.     return nodes[currentNode]
  30. end
  31.  
  32. local function getWalkCost(fromPos, toPos)
  33.     if(math.abs(fromPos.x - toPos.x) == math.abs(fromPos.y - toPos.y)) then
  34.         return 3
  35.     else
  36.         return 1
  37.     end
  38. end
  39.  
  40. local function isTileWalkable(pos)
  41.     local canWalk = true
  42.     for a = 0, 255 do
  43.         pos.stackpos = a
  44.         local tileItem = getTileThingByPos(pos)
  45.         if tileItem.itemid > 0 then
  46.             local itemInfo = getItemInfo(tileItem.itemid)
  47.             if itemInfo.blockSolid then
  48.                 canWalk = false
  49.             end
  50.         else
  51.             if a == 0 then
  52.                 return false
  53.             else
  54.                 return canWalk
  55.             end
  56.         end
  57.     end
  58.     return false
  59. end
  60.  
  61. local function isTileZPath(cid, pos)
  62.     local zPath = false
  63.     local curInfo = getTileInfo({x=pos.x,y=pos.y,z=pos.z,stackpos=0})
  64.     if curInfo then
  65.         local curInfo = curInfo.floorChange
  66.         if curInfo[9] == true then
  67.             local upPos = {x=pos.x,y=pos.y,z=endPos.z,stackpos=0}
  68.             local endInfo = getTileInfo(upPos)
  69.             if endInfo then
  70.                 endInfo = endInfo.floorChange
  71.                 if endInfo[9] == true then
  72.                     if startPos.z < endPos.z then
  73.                         zPath = endInfo
  74.                     else
  75.                         zPath = curInfo
  76.                     end
  77.                 end
  78.             end
  79.         end
  80.     end
  81.     return zPath
  82. end
  83.    
  84.  
  85. local function playDirectionList(cid)
  86.     if #dirListi > 0 then
  87.         for a = 1, #dirListi do
  88.             newPos = getPositionByDirection(startPos, dirListi[#dirListi-a+1])
  89.             addEvent(doMoveCreature, a*10, cid, dirListi[#dirListi-a+1])
  90.             doSendMagicEffect(newPos, 55)
  91.             startPos = newPos
  92.         end
  93.     end
  94.     return true
  95. end
  96.  
  97. local function doDirectionList(cid, lastPos)
  98.     dirListi = {}
  99.     while lastPos.place ~= 1 do
  100.         local oldPos = {x=nodes[lastPos.parent].x,y=nodes[lastPos.parent].y,z=nodes[lastPos.parent].z}
  101.         local newPos = {x=lastPos.x,y=lastPos.y,z=lastPos.z}
  102.         table.insert(dirListi, getDirectionTo(oldPos, newPos, true))
  103.         lastPos = nodes[lastPos.parent]
  104.     end
  105.     --doCreatureSay(cid, table.serialize(dirListi), 1)
  106.     playDirectionList(cid)
  107.     return true
  108. end
  109.  
  110. local function getTotalCost(cid, node, cost)
  111.     while node.place ~= 1 do
  112.         cost = cost + node.cost
  113.         node = nodes[node.parent]
  114.     end
  115.     return cost
  116. end
  117.  
  118. local function opposingDir(node)
  119.     local endDir = getDirectionTo(startPos, endPos)
  120.     local nodeDir = getDirectionTo(startPos, node)
  121.     if endDir == 0 and isInArray({2, 4, 5}, nodeDir) then
  122.         return true
  123.     elseif endDir == 1 and isInArray({3, 4, 6}, nodeDir) then
  124.         return true
  125.     elseif endDir == 2 and isInArray({0, 6, 7}, nodeDir) then
  126.         return true
  127.     elseif endDir == 3 and isInArray({1, 5, 7}, nodeDir) then
  128.         return true
  129.     elseif endDir == 4 and isInArray({7, 0, 1}, nodeDir) then
  130.         return true
  131.     elseif endDir == 5 and isInArray({6, 0, 3}, nodeDir) then
  132.         return true
  133.     elseif endDir == 6 and isInArray({5, 2, 1}, nodeDir) then
  134.         return true
  135.     elseif endDir == 7 and isInArray({4, 2, 3}, nodeDir) then
  136.         return true
  137.     end
  138.     return false
  139. end
  140.  
  141. local function getBestNode()
  142.     local node = false
  143.     local cost = 100000
  144.     for _, tid in ipairs(nodes) do
  145.         if tid.active == 1 then
  146.             local testCost = getTotalCost(0, tid, 0)
  147.             local normDist = getDistanceBetween(startPos, endPos)
  148.             local nodeDist = getDistanceBetween(tid, endPos)
  149.             local diffDist = nodeDist - normDist
  150.             if opposingDir(tid) then diffDist = diffDist + 10 end
  151.             if tid.z ~= endPos.z then diffDist = diffDist + 1000 end
  152.             testCost = testCost+(getDistanceBetween(tid, endPos))+diffDist
  153.             if testCost < cost then
  154.                 node = tid
  155.                 cost = testCost
  156.             end
  157.         end
  158.     end
  159.     return node
  160. end
  161.  
  162. local function pathLength(cid, node, countPath)
  163.     while node.place ~= 1 and countPath < 50 do
  164.         countPath = countPath + 1
  165.         node = nodes[node.parent]
  166.     end
  167.     return countPath
  168. end
  169.  
  170. local function checkNeighbors(cid, currentPos)
  171.     local pos = {}
  172.     while count > 0 and openNodes do
  173.         local currentPos = getBestNode()
  174.         if not currentPos then
  175.             openNodes = false
  176.         end
  177.         if found and currentPos then
  178.             if getTotalCost(cid, found, 0) < (getTotalCost(cid, currentPos, 0)+getDistanceBetween(currentPos, found)) then
  179.                 openNodes = false
  180.                 currentPos.active = 0
  181.                 currentPos = false
  182.                 doCreatureSay(cid, "Script still open for a total of "..os.mtime()-timeToPath.." milliseconds.", 1)
  183.             end
  184.         end
  185.         if currentPos then
  186.             count = count - 1
  187.             for a = 1, 8 do
  188.                 currentPos.active = 0
  189.                 pos.x = currentPos.x - directionsList[a][1]
  190.                 pos.y = currentPos.y - directionsList[a][2]
  191.                 pos.z = currentPos.z
  192.                 pos.cost = getWalkCost(currentPos, pos)
  193.                 inRange = true
  194.                 if getDistanceBetween(pos, startPos) > 50 or getDistanceBetween(pos, endPos) > 50 then
  195.                     inRange = false
  196.                 end
  197.                
  198.                 if inRange and isTileWalkable(pos) then
  199.                     local newcost = getWalkCost(currentPos, pos)
  200.                     local neighbor = false
  201.                     for _, tid in ipairs(nodes) do
  202.                         if tid.x == pos.x and tid.y == pos.y and tid.z == pos.z and tid.parent > 0 then
  203.                             if pos.x == endPos.x and pos.y == endPos.y and pos.z == endPos.z then
  204.                                 neighbor = false
  205.                             else
  206.                                 neighbor = true
  207.                             end
  208.                             local oldPath = getTotalCost(cid, tid, 0)
  209.                             local newPath = getTotalCost(cid, nodes[currentPos.place], newcost)
  210.                             if oldPath > newPath then
  211.                                 tid.parent = currentPos.place
  212.                                 tid.cost = newcost
  213.                             end
  214.                         end
  215.                     end
  216.                     if not neighbor then
  217.                         doSendMagicEffect(pos, 56)
  218.                         pos.cost = newcost
  219.                         local neighbor = newLuaNode()
  220.                         neighbor.x = pos.x
  221.                         neighbor.y = pos.y
  222.                         neighbor.z = pos.z
  223.                         neighbor.cost = pos.cost
  224.                         neighbor.parent = currentPos.place
  225.                         table.insert(nodes[currentPos.place].children, neighbor.place)
  226.                         if endPos.z ~= neighbor.z then
  227.                             local zInfo = isTileZPath(cid, neighbor)
  228.                             if zInfo then
  229.                                 oldNeighbor = neighbor
  230.                                 neighbor = newLuaNode()
  231.                                 neighbor.x = pos.x
  232.                                 neighbor.y = pos.y
  233.                                 neighbor.z = pos.z
  234.                                 neighbor.cost = pos.cost
  235.                                 neighbor.parent = oldNeighbor.place
  236.                                 local zMult = 1
  237.                                 if startPos.z > endPos.z then zMult = -1 end
  238.                                 if zInfo[1] then
  239.                                     neighbor.y = neighbor.y + zMult
  240.                                 elseif zInfo[2] then
  241.                                     neighbor.x = neighbor.x + zMult
  242.                                 elseif zInfo[3] then
  243.                                     neighbor.y = neighbor.y - zMult
  244.                                 elseif zInfo[4] then
  245.                                     neighbor.x = neighbor.x - zmult
  246.                                 end
  247.                                 neighbor.z = endPos.z
  248.                                 table.insert(nodes[oldNeighbor.place].children, neighbor.place)
  249.                             end
  250.                         elseif neighbor.x == endPos.x and neighbor.y == endPos.y and neighbor.z == endPos.z then
  251.                             if found == false then
  252.                                 doCreatureSay(cid, "Found Path after checking "..#nodes.." tiles taking "..os.mtime()-timeToPath.." milliseconds.", 1)
  253.                                 timeToPath = os.mtime()
  254.                                 found = neighbor
  255.                             end
  256.                         end
  257.                     end
  258.                 end
  259.             end
  260.         end
  261.     end
  262.     if found then
  263.         return doDirectionList(cid, found)
  264.     else
  265.         doCreatureSay(cid, "There is no possible path", 1)
  266.     end
  267.     return true
  268. end
  269.        
  270.  
  271. function onUse(cid, item, fromPosition, itemEx, toPosition)
  272.     timeToPath = os.mtime()
  273.     progress = true
  274.     nodes = {}
  275.     count = 1000
  276.     usedNodes = {}
  277.     currentNode = 0
  278.     startPos = {}
  279.     found = false
  280.     complete = false
  281.     startPos = getCreaturePosition(cid)
  282.     endPos = toPosition
  283.    
  284.     local fast = false
  285.     if (isSightClear(startPos, endPos, false)) then
  286.         fast = true
  287.     end
  288.  
  289.     local startNode = newLuaNode()
  290.     startNode.x = startPos.x
  291.     startNode.y = startPos.y
  292.     startNode.z = startPos.z
  293.     startNode.cost = 0
  294.     startNode.parent = 0
  295.    
  296.     local pos = {}
  297.     pos.x = startNode.x
  298.     pos.y = startNode.y
  299.     pos.z = startNode.z
  300.     pos.cost = startNode.cost
  301.     pos.place = startNode.place
  302.    
  303.     checkNeighbors(cid, {x=pos.x,y=pos.y,z=pos.z,cost=pos.cost,place=pos.place})
  304.     return true
  305. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement