rockbandcheeseman

GEOMain 1.03

Nov 19th, 2012
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 31.40 KB | None | 0 0
  1. -- GEOs (Geometric Environment Objects) 1.03
  2.  
  3. -- Create Metatable
  4. GEO = {}
  5. GEO.__index = GEO
  6.  
  7. -- Set random seed and define infinity
  8. math.randomseed(os.time())
  9. math.inf = 1 / 0
  10.  
  11. function inSphere(m_objId, x, y, z, r)
  12.  
  13.     local ox, oy, oz = getobjectcoords(m_objId)
  14.     if ox then
  15.         -- Pythagorean
  16.         local dist = math.sqrt((x - ox) ^ 2 + (y - oy) ^ 2 + (z - oz) ^ 2)
  17.         if dist <= r then
  18.             return true
  19.         end
  20.     end
  21.    
  22.     return false
  23. end
  24.  
  25. function inCircle(m_objId, x, y, z, r, orientation)
  26.  
  27.     local ox, oy, oz = getobjectcoords(m_objId)
  28.     if ox then
  29.         -- Default orientation to "z"
  30.         orientation = orientation or "z"
  31.         -- Pythagorean based on circle's orientation
  32.         if orientation == "z" then
  33.             local dist = math.sqrt((x - ox) ^ 2 + (y - oy) ^ 2)
  34.             if dist <= r and oz == z then
  35.                 return true
  36.             end
  37.         elseif orientation == "y" then
  38.             local dist = math.sqrt((x - ox) ^ 2 + (z - oz) ^ 2)
  39.             if dist <= r and oy == y then
  40.                 return true
  41.             end
  42.         elseif orientation == "x" then
  43.             local dist = math.sqrt((y - oy) ^ 2 + (z - oz) ^ 2)
  44.             if dist <= r and ox == x then
  45.                 return true
  46.             end
  47.         end
  48.     end
  49.    
  50.     return false
  51. end
  52.  
  53. function inCylinder(m_objId, x, y, zlow, zhigh, r)
  54.  
  55.     local ox, oy, oz = getobjectcoords(m_objId)
  56.     if ox then
  57.         -- Pythagorean to see if object is within radius of circle
  58.         local dist = math.sqrt((x - ox) ^ 2 + (y - oy) ^ 2)
  59.         -- Make sure the object is also within the height of the cylinder
  60.         if dist <= r and z >= zlow and z <= zhigh then
  61.             return true
  62.         end
  63.     end
  64.    
  65.     return false
  66. end
  67.  
  68. function inRectangle(m_objId, xlow, xhigh, ylow, yhigh, zlow, zhigh)
  69.  
  70.     -- These functions are essentially the same
  71.     return inRectPrism(m_objId, xlow, xhigh, ylow, yhigh, zlow, zhigh)
  72. end
  73.  
  74. function inRectPrism(m_objId, xlow, xhigh, ylow, yhigh, zlow, zhigh)
  75.  
  76.     local x, y, z = getobjectcoords(m_objId)
  77.     if x then
  78.         -- Make sure the coordinates are inside of each extreme of the rectangular prism
  79.         if x <= xhigh and x >= xlow and y <= yhigh and y >= ylow and z <= zhigh and z >= zlow then
  80.             return true
  81.         end
  82.     end
  83.    
  84.     return false
  85. end
  86.  
  87. function randomInSphere(x, y, z, r)
  88.  
  89.     -- Increase precision
  90.     x = math.floor(x * 100)
  91.     y = math.floor(y * 100)
  92.     z = math.floor(z * 100)
  93.     r = math.floor(r * 100)
  94.    
  95.     -- Find random values inside of the sphere.
  96.     return math.random(x - r, x + r + 1) / 100, math.random(y - r, y + r + 1) / 100, math.random(z - r, z + r + 1) / 100
  97. end
  98.  
  99. function randomInCircle(x, y, z, r, orientation)
  100.  
  101.     -- Increase precision
  102.     r = math.floor(r * 100)
  103.    
  104.     -- Possible values depend on circle's orientation.
  105.     if orientation == "z" then
  106.         x = math.floor(x * 100)
  107.         y = math.floor(y * 100)
  108.         return math.random(x - r, x + r + 1) / 100, math.random(y - r, y + r + 1) / 100,
  109.     elseif orientation == "x" then
  110.         y = math.floor(y * 100)
  111.         z = math.floor(z * 100)
  112.         return x, math.random(y - r, y + r + 1) / 100, math.random(z - r, z + r + 1) / 100
  113.     elseif orientation == "y" then
  114.         x = math.floor(x * 100)
  115.         z = math.floor(z * 100)
  116.         return math.random(x - r, x + r + 1) / 100, y, math.random(z - r, z + r + 1) / 100
  117.     end
  118. end
  119.  
  120. function randomInCylinder(x, y, zlow, zhigh, r)
  121.  
  122.     -- Increase precision
  123.     x = math.floor(x * 100)
  124.     y = math.floor(y * 100)
  125.     zlow = math.floor(zlow * 100)
  126.     zhigh = math.floor(zhigh * 100)
  127.     r = math.floor(r * 100)
  128.    
  129.     -- Find random values inside of the cylinder.
  130.     return math.random(x - r, x + r + 1) / 100, math.random(y - r, y + r + 1) / 100, math.random(zlow, zhigh + 1) / 100
  131. end
  132.  
  133. function randomInRectPrism(xlow, xhigh, ylow, yhigh, zlow, zhigh)
  134.  
  135.     -- Increase precision
  136.     xlow = math.floor(xlow * 100)
  137.     xhigh = math.floor(xhigh * 100)
  138.     ylow = math.floor(ylow * 100)
  139.     yhigh = math.floor(yhigh * 100)
  140.     zlow = math.floor(zlow * 100)
  141.     zhigh = math.floor(zhigh * 100)
  142.    
  143.     -- Find random values inside of the rectangular prism.
  144.     return math.random(xlow, xhigh + 1) / 100, math.random(ylow, yhigh + 1) / 100, math.random(zlow, zhigh)
  145. end
  146.  
  147. -- Object Creation Comments (refer to this function for questions on how the other ones work)
  148. function GEO.newSphere(name, r, x, y, z)
  149.  
  150.     -- Check to see if there is already a GEO with this name.
  151.     if not GEO[name] then
  152.         -- Create new table
  153.         GEO[name] = {}
  154.         GEO[name].t = "sphere"  -- type
  155.         GEO[name].n = name  -- name
  156.         GEO[name].r = r or 1  -- radius (default value of 1)
  157.         GEO[name].x = x or 0  -- x coordinate of center (default value of 0)
  158.         GEO[name].y = y or 0  -- y coordinate of center (default value of 0)
  159.         GEO[name].z = z or 0  -- z coordinate of center (default value of 0)
  160.        
  161.         -- Notify the console that a sphere has been created.
  162.         hprintf("Sphere \"" .. name .. "\" created.")
  163.         setmetatable(GEO[name], GEO)  -- Add this object to the GEO metatable to allow GEO-editing functions to work on it.
  164.         return GEO[name]  -- Return the object
  165.     end
  166.    
  167.     -- If no object was returned, the name was invalid; notify the console.
  168.     hprintf("Invalid name: \"" .. name .. "\"")
  169. end
  170.  
  171. function GEO.newCircle(name, r, x, y, z, orientation)
  172.  
  173.     if not GEO[name] then
  174.         GEO[name] = {}
  175.         GEO[name].t = "circle"
  176.         GEO[name].n = name
  177.         GEO[name].o = orientation or "z"  -- orientation
  178.         GEO[name].r = r or 0
  179.         GEO[name].x = x or 0
  180.         GEO[name].y = y or 0
  181.         GEO[name].z = z or 0
  182.        
  183.         hprintf("Circle \"" .. name .. "\" created.")
  184.         setmetatable(GEO[name], GEO)
  185.         return GEO[name]
  186.     end
  187.    
  188.     hprintf("Invalid name: \"" .. name .. "\"")
  189. end
  190.  
  191. function GEO.newCylinder(name, r, h, x, y, z)
  192.  
  193.     if not GEO[name] then
  194.         GEO[name] = {}
  195.         GEO[name].t = "cylinder"
  196.         GEO[name].n = name
  197.         x = x or 0
  198.         y = y or 0
  199.         z = z or 0
  200.         r = r or 1
  201.         h = h or 1
  202.         GEO[name].x = x
  203.         GEO[name].y = y
  204.         GEO[name].z = z
  205.         GEO[name].r = r
  206.         GEO[name].h = h  -- height
  207.         GEO[name].zlow = z - h / 2  -- lowest z-coordinate still within the cylinder
  208.         GEO[name].zhigh = z + h / 2  -- highest z-coordinate still within the cylinder
  209.        
  210.         hprintf("Cylinder \"" .. name .. "\" created.")
  211.         setmetatable(GEO[name], GEO)
  212.         return GEO[name]
  213.     end
  214. end
  215.  
  216. function GEO.newRectPrism(name, lx, ly, lz, x, y, z)
  217.  
  218.     if not GEO[name] then
  219.         GEO[name] = {}
  220.         GEO[name].t = "rectprism"
  221.         GEO[name].n = name
  222.         lx = lx or 1
  223.         ly = ly or 1
  224.         lz = lz or 1
  225.         x = x or 0
  226.         y = y or 0
  227.         z = z or 0
  228.         GEO[name].lx = lx  -- x length
  229.         GEO[name].ly = ly  -- y length
  230.         GEO[name].lz = lz  -- z length
  231.         GEO[name].x = x
  232.         GEO[name].y = y
  233.         GEO[name].z = z
  234.         GEO[name].xlow = x - lx / 2  -- lowest x-coordinate still within the rectangular prism
  235.         GEO[name].xhigh = lx / 2 + x  -- highest x-coordinate still within in the rectangular prism
  236.         GEO[name].ylow = y - ly / 2  -- lowest y-coordinate still within the rectangular prism
  237.         GEO[name].yhigh = ly / 2 + y  -- highest y-coordinate still within the rectangular prism
  238.         GEO[name].zlow = z - lz / 2  -- lowest z-coordinate still within the rectangular prism
  239.         GEO[name].zhigh = lz / 2 + z  -- highest z-coordinate still within the rectangular prism
  240.        
  241.         hprintf("Rectangular Prism \"" .. name .. "\" created.")
  242.         setmetatable(GEO[name], GEO)
  243.         return GEO[name]
  244.     end
  245.    
  246.     hprintf("Invalid name: \"" .. name .. "\"")
  247. end
  248.  
  249. function GEO.newRect(name, width, height, x, y, z, orientation)
  250.  
  251.     if not GEO[name] then
  252.         GEO[name] = {}
  253.         GEO[name].t = "rectangle"
  254.         GEO[name].n = name
  255.         width = width or 1
  256.         height = height or 1
  257.         x = x or 0
  258.         y = y or 0
  259.         z = z or 0
  260.         orientation = orientation or "z"
  261.         GEO[name].width = width
  262.         GEO[name].height = height
  263.         GEO[name].x = x
  264.         GEO[name].y = y
  265.         GEO[name].z = z
  266.         GEO[name].o = orientation
  267.        
  268.         -- Coordinates' highs and lows depend on orientation
  269.         if orientation == "z" then
  270.             GEO[name].xlow = x - width / 2
  271.             GEO[name].xhigh = x + width / 2
  272.             GEO[name].ylow = y - height / 2
  273.             GEO[name].yhigh = y + height / 2
  274.             GEO[name].zlow = z
  275.             GEO[name].zhigh = z
  276.         elseif orientation == "x" then
  277.             GEO[name].xlow = x
  278.             GEO[name].xhigh = x
  279.             GEO[name].ylow = y - width / 2
  280.             GEO[name].yhigh = y + width / 2
  281.             GEO[name].zlow = z - height / 2
  282.             GEO[name].zhigh = z + height / 2
  283.         elseif orientation == "y" then
  284.             GEO[name].xlow = x - width / 2
  285.             GEO[name].xhigh = x + width / 2
  286.             GEO[name].ylow = y
  287.             GEO[name].yhigh = y
  288.             GEO[name].zlow = z - height / 2
  289.             GEO[name].zhigh = z + height / 2
  290.         end
  291.        
  292.         hprintf("Rectangle \"" .. name .. "\" created.")
  293.         setmetatable(GEO[name], GEO)
  294.         return GEO[name]
  295.     end
  296.    
  297.     hprintf("Invalid name: \""  .. name .. "\"")
  298. end
  299.  
  300. function GEO.get(name)
  301.  
  302.     return GEO[name]
  303. end
  304.  
  305. function GEO:delete()
  306.  
  307.     self:hide()
  308.     GEO[self.n] = nil
  309.     hprintf("Geo \"" .. self.n .. "\" deleted.")
  310. end
  311.  
  312. function GEO:move(x, y, z)
  313.  
  314.     -- Move the center of the object
  315.     -- Default to GEO's current coordinates
  316.     GEO[self.n].x = x or GEO[self.n].x
  317.     GEO[self.n].y = y or GEO[self.n].y
  318.     GEO[self.n].z = z or GEO[self.n].z
  319.    
  320.     -- If this is a rectangular prism...
  321.     if self.t == "rectprism" then
  322.         -- Change the x, y, and z lows and highs accordingly to adjust to the new center
  323.         GEO[self.n].xlow = x - GEO[self.n].lx / 2  
  324.         GEO[self.n].xhigh = GEO[self.n].lx / 2 + x
  325.         GEO[self.n].ylow = y - GEO[self.n].ly / 2
  326.         GEO[self.n].yhigh = GEO[self.n].ly / 2 + y
  327.         GEO[self.n].zlow = z - GEO[self.n].lz / 2
  328.         GEO[self.n].zhigh = GEO[self.n].lz / 2 + z
  329.    
  330.     -- If this is a rectangle...
  331.     elseif self.t == "rectangle" then
  332.         -- Change the x, y, and z lows and highs accordingly to adjust to the new center (depends on orientation)
  333.         if self.o == "z" then
  334.             GEO[self.n].xlow = self.x - self.width / 2
  335.             GEO[self.n].xhigh = self.x + self.width / 2
  336.             GEO[self.n].ylow = self.y - self.height / 2
  337.             GEO[self.n].yhigh = self.y + self.height / 2
  338.             GEO[self.n].zlow = self.z
  339.             GEO[self.n].zhigh = self.z
  340.         elseif self.o == "x" then
  341.             GEO[self.n].xlow = self.x
  342.             GEO[self.n].xhigh = self.x
  343.             GEO[self.n].ylow = self.y - self.width / 2
  344.             GEO[self.n].yhigh = self.y + self.width / 2
  345.             GEO[self.n].zlow = self.z - self.height / 2
  346.             GEO[self.n].zhigh = self.z + self.height / 2
  347.         elseif self.o == "y" then
  348.             GEO[self.n].xlow = self.x - self.width / 2
  349.             GEO[self.n].xhigh = self.x + self.width / 2
  350.             GEO[self.n].ylow = self.y
  351.             GEO[self.n].yhigh = self.y
  352.             GEO[self.n].zlow = self.z - self.height / 2
  353.             GEO[self.n].zhigh = self.z + self.height / 2
  354.         end
  355.    
  356.     -- If this is a cylinder...
  357.     elseif self.t == "cylinder" then
  358.         GEO[self.n].zlow = self.z - self.h / 2
  359.         GEO[self.n].zhigh = self.z + self.h / 2
  360.     end
  361. end
  362.  
  363. function GEO:radius(new)
  364.  
  365.     if self.t == "sphere" or self.t == "circle" or self.t == "cylinder" then
  366.         if new then  -- If "new" is defined...
  367.             GEO[self.n].r = new  -- Change the radius to its value.
  368.         else  -- If not...
  369.             return GEO[self.n].r  -- Return its current radius.
  370.         end
  371.     end
  372. end
  373.  
  374. function GEO:size(x, y, z)
  375.  
  376.     -- If this is a rectangular prism...
  377.     if self.t == "rectprism" then
  378.         if x or y or z then  -- If any of these variables have been defined...
  379.             -- Adjust lengths and x, y, and z highs and lows accordingly.
  380.             GEO[self.n].lx = x or GEO[self.n].lx
  381.             GEO[self.n].ly = y or GEO[self.n].ly
  382.             GEO[self.n].lz = z or GEO[self.n].lz
  383.             GEO[self.n].xlow = GEO[self.n].x - x / 2
  384.             GEO[self.n].xhigh = x / 2 + GEO[self.n].x
  385.             GEO[self.n].ylow = GEO[self.n].y - y / 2
  386.             GEO[self.n].yhigh = y / 2 + GEO[self.n].y
  387.             GEO[self.n].zlow = GEO[self.n].z - z / 2
  388.             GEO[self.n].zhigh = z / 2 + GEO[self.n].z
  389.         else  -- Otherwise...
  390.             return GEO[self.n].lx, GEO[self.n].ly, GEO[self.n].lz  -- Return the x, y, and z lengths.
  391.         end
  392.    
  393.     -- If this is a rectangle...
  394.     elseif self.t == "rectangle" then
  395.         if x or y or z then  -- If any of these variables are defined...
  396.             -- Adjust width, height, and x, y, and z highs and lows accordingly (depends on orientation).
  397.             if self.o == "z" then
  398.                 GEO[self.n].width = x
  399.                 GEO[self.n].height = y
  400.                 GEO[self.n].xlow = self.x - self.width / 2
  401.                 GEO[self.n].xhigh = self.x + self.width / 2
  402.                 GEO[self.n].ylow = self.y - self.height / 2
  403.                 GEO[self.n].yhigh = self.y + self.height / 2
  404.                 GEO[self.n].zlow = self.z
  405.                 GEO[self.n].zhigh = self.z
  406.             elseif self.o == "x" then
  407.                 GEO[self.n].width = y
  408.                 GEO[self.n].height = z
  409.                 GEO[self.n].xlow = self.x
  410.                 GEO[self.n].xhigh = self.x
  411.                 GEO[self.n].ylow = self.y - self.width / 2
  412.                 GEO[self.n].yhigh = self.y + self.width / 2
  413.                 GEO[self.n].zlow = self.z - self.height / 2
  414.                 GEO[self.n].zhigh = self.z + self.height / 2
  415.             elseif self.o == "y" then
  416.                 GEO[self.n].width = x
  417.                 GEO[self.n].height = z
  418.                 GEO[self.n].xlow = self.x - self.width / 2
  419.                 GEO[self.n].xhigh = self.x + self.width / 2
  420.                 GEO[self.n].ylow = self.y
  421.                 GEO[self.n].yhigh = self.y
  422.                 GEO[self.n].zlow = self.z - self.height / 2
  423.                 GEO[self.n].zhigh = self.z + self.height / 2
  424.             end
  425.         else  -- Otherwise...
  426.             return GEO[self.n].width, GEO[self.n].height  -- Return the width and height of the rectangle.
  427.         end
  428.    
  429.     -- If this is a cylinder...
  430.     elseif self.t == "cylinder" then
  431.         local h = x or y or z  -- Whichever variable is defined, it is taken as the height.
  432.         if h then  -- If a height is specified...
  433.             -- Adjust height and z high and low accordingly.
  434.             GEO[self.n].h = h
  435.             GEO[self.n].zlow = self.z - h / 2
  436.             GEO[self.n].zhigh = self.z + h / 2
  437.         else  -- Otherwise...
  438.             return GEO[self.n].h  -- Return the height.
  439.         end
  440.     end
  441. end
  442.  
  443. function GEO:extend(orienation, direction, amount)
  444.  
  445.     -- Change the direction from "+" or "-" to "high" or "low".
  446.     local dir
  447.     dir = string.gsub(direction, "-", "low")
  448.     dir = string.gsub(direction, "+", "high")
  449.    
  450.     -- Get the face we're trying to extend (i.e. "xhigh")
  451.     local face = string.lower(orientation) .. direction
  452.    
  453.     -- If this is a rectangular prism or a rectangle...
  454.     if self.t == "rectprism" or self.t == "rectangle" then
  455.         -- Make sure "face" is actually a valid face (and not something like "cheesederp")
  456.         if self[face] then
  457.             -- Use "GEO[self.n]" when you want to actually permanently change the value of something within the object; use "self" for reading information from the object.
  458.             -- Change the length of the GEO in the orientation specified.
  459.             GEO[self.n]["l" .. string.lower(orientation)] = self["l" .. string.lower(orientation)] + amount
  460.            
  461.             -- Figure out if the positive or negative face is being extended.
  462.             if direction == "+" then
  463.                 GEO[self.n][face] = self[face] + amount
  464.                 GEO[self.n][string.lower(orientation)] = self[string.lower(orientation)] + amount / 2
  465.             else
  466.                 GEO[self.n][face] = self[face] - amount
  467.                 GEO[self.n][string.lower(orientation)] = self[string.lower(orientation)] - amount / 2
  468.             end
  469.         end
  470.    
  471.     -- If this is a cylinder...
  472.     elseif self.t == "cylinder" then
  473.         -- The orientation must be "z"
  474.         if orientation == "z" then
  475.             if self[face] then
  476.                 GEO[self.n].h = self.h + amount
  477.                
  478.                 -- Figure out if the top or bottom face is being extended.
  479.                 if direction == "+" then
  480.                     GEO[self.n][face] = self[face] + amount
  481.                     GEO[self.n].z = self.z + amount / 2
  482.                 else
  483.                     GEO[self.n][face] = self[face] - amount
  484.                     GEO[self.n].z = self.z - amount / 2
  485.                 end
  486.             end
  487.         end
  488.     end
  489. end
  490.  
  491. function GEO:coords()
  492.  
  493.     return self.x, self.y, self.z
  494. end
  495.  
  496. function GEO:high(orientation)
  497.  
  498.     if self.t == "sphere" or self.t == "circle" then
  499.         return self[orientation] + self.r
  500.     elseif self.t == "rectprism" or self.t == "rectangle" then
  501.         return self[orientation .. "high"]
  502.     elseif self.t == "cylinder" then
  503.         if orientation == "z" then
  504.             return self.zhigh
  505.         else
  506.             return self[orientation] + self.r
  507.         end
  508.     end    
  509. end
  510.  
  511. function GEO:low(orientation)
  512.  
  513.     if self.t == "sphere" or self.t == "circle" then
  514.         return self[orientation] - self.r
  515.     elseif self.t == "rectprism" or self.t == "rectangle" then
  516.         return self[orientation .. "low"]
  517.     elseif self.t == "cylinder" then
  518.         if orientation == "z" then
  519.             return self.zlow
  520.         else
  521.             return self[orientation] - self.r
  522.         end
  523.     end    
  524. end
  525.  
  526. function GEO:randcoords()
  527.  
  528.     if self.t == "sphere" then
  529.         return randomInSphere(self.x, self.y, self.z, self.r)
  530.     elseif self.t == "circle" then
  531.         return randomInCircle(self.x, self.y, self.z, self.r, self.o)
  532.     elseif self.t == "cylinder" then
  533.         return randomInCylinder(self.x, self.y, self.zlow, self.zhigh, self.r)
  534.     elseif self.t == "rectprism" or self.t == "rectangle" then
  535.         return randomInRectPrism(self.xlow, self.xhigh, self.ylow, self.yhigh, self.zlow, self.zhigh)
  536.     end
  537. end
  538.  
  539. function GEO:type()
  540.  
  541.     return self.t
  542. end
  543.  
  544. function GEO:orientation()
  545.  
  546.     return self.o
  547. end
  548.  
  549. function GEO:name()
  550.  
  551.     return self.n
  552. end
  553.  
  554. function GEO:perimeter(density, tagType, tagName)
  555.    
  556.     -- Default tagType and tagName to Full-Spectrum Visions
  557.     tagType = tagType or "eqip"
  558.     tagName = tagName or "powerups\\full-spectrum vision"
  559.    
  560.     -- Store all of the perimeter objects in a table
  561.     GEO[self.n].p = GEO[self.n].p or {}
  562.    
  563.     -- Find the change in angle per point from 0 - 2pi (0° - 360°)
  564.     local angle_increment = 2 * math.pi / density
  565.     if self.t == "sphere" or self.t == "cylinder" then
  566.         for i = 1,density do
  567.             -- Use trigonometry to find the outer edge of the circle (for a sphere, this will be at the z-center -- the widest part of the sphere.
  568.             local x = self.r * math.cos(angle_increment * i)
  569.             local y = self.r * math.sin(angle_increment * i)
  570.             local z = self.z
  571.             local m_objId = createobject(tagType, tagName, 0, 0, false, self.x + x, self.y + y, self.z + z)
  572.             GEO[self.n].p[m_objId] = {self.x + x, self.y + y, self.z + z}
  573.         end
  574.     elseif self.t == "circle" then
  575.         if self.o == "z" then
  576.             for i = 1,density do
  577.                 -- Use trigonometry to find the outer edge of the circle (for a sphere, this will be at the z-center -- the widest part of the sphere.
  578.                 local x = self.r * math.cos(angle_increment * i)
  579.                 local y = self.r * math.sin(angle_increment * i)
  580.                 local z = self.z
  581.                 local m_objId = createobject(tagType, tagName, 0, 0, false, self.x + x, self.y + y, self.z + z)
  582.                 GEO[self.n].p[m_objId] = {self.x + x, self.y + y, self.z + z}
  583.             end
  584.         end
  585.     elseif self.t == "rectprism" or self.t == "rectangle" then
  586.         if self.t == "rectangle" then
  587.             if self.o ~= "z" then return end
  588.         end
  589.         -- Create points at four corners of the rectangle
  590.         local o1 = createobject(tagType, tagName, 0, 0, false, self.xhigh, self.yhigh, self.z)
  591.         local o2 = createobject(tagType, tagName, 0, 0, false, self.xhigh, self.ylow, self.z)
  592.         local o3 = createobject(tagType, tagName, 0, 0, false, self.xlow, self.yhigh, self.z)
  593.         local o4 = createobject(tagType, tagName, 0, 0, false, self.xlow, self.ylow, self.z)
  594.         GEO[self.n].p[o1] = {self.xhigh, self.yhigh, self.z}
  595.         GEO[self.n].p[o2] = {self.xhigh, self.yhigh, self.z}
  596.         GEO[self.n].p[o3] = {self.xhigh, self.yhigh, self.z}
  597.         GEO[self.n].p[o4] = {self.xhigh, self.yhigh, self.z}
  598.        
  599.         for i = 1,density do
  600.             local herp = createobject(tagType, tagName, 0, 0, false, self.xhigh - (i * self.lx / density), self.yhigh, self.z)
  601.             local derp = createobject(tagType, tagName, 0, 0, false, self.xhigh, self.yhigh - (i * self.ly / density), self.z)
  602.             local weee = createobject(tagType, tagName, 0, 0, false, self.xhigh - (i * self.lx / density), self.ylow, self.z)
  603.             local cheese = createobject(tagType, tagName, 0, 0, false, self.xlow, self.ylow + (i * self.ly / density), self.z)
  604.             GEO[self.n].p[herp] = {self.xhigh - (i * self.lx / density), self.yhigh, self.z}
  605.             GEO[self.n].p[derp] = {self.xhigh, self.yhigh - (i * self.ly / density), self.z}
  606.             GEO[self.n].p[weee] = {self.xhigh - (i * self.lx / density), self.ylow, self.z}
  607.             GEO[self.n].p[cheese] = {self.xlow, self.ylow + (i * self.ly / density), self.z}
  608.         end
  609.     end
  610. end
  611.  
  612. function GEO:hide()
  613.  
  614.     if self.p then
  615.         for k,v in pairs(GEO[self.n].p) do
  616.             if getobject(k) then
  617.                 destroyobject(k)
  618.                 GEO[self.n].p[k] = nil
  619.             end
  620.         end
  621.     end
  622. end
  623.  
  624. -- Never quite got this to work right, but I'm saving it for the sake of the formula.
  625. --[[function GEO:surface(density)
  626.  
  627.     GEO[self.n].p = GEO[self.n].p or {}
  628.     if self.t == "sphere" then
  629.         local inc = math.pi * (3 - math.sqrt(5))
  630.         local off = 2 / density
  631.         for i = 1,density do
  632.             local y = self.r * i * off - 1 + (off / 2)
  633.             local r = self.r * math.sqrt(1 - y ^ 2)
  634.             local phi = i * inc
  635.             local x = r * math.cos(phi)
  636.             local z = r * math.sin(phi)
  637.             local m_objId = createobject(tagType, tagName, 0, 0, false, x, y, z)
  638.             GEO[self.n].p[m_objId] = {x, y, z}
  639.         end
  640.     end
  641. end--]]
  642.  
  643. function GEO:contains(m_objId)
  644.  
  645.     if self.t == "sphere" then
  646.         return inSphere(m_objId, self.x, self.y, self.z, self.r)
  647.     elseif self.t == "rectprism" or self.t == "rectangle" then
  648.         return inRectPrism(m_objId, self.xlow, self.xhigh, self.ylow, self.yhigh, self.zlow, self.zhigh)
  649.     elseif self.t == "circle" then
  650.         return inCircle(m_objId, self.x, self.y, self.z, self.r, self.o)
  651.     elseif self.t == "cylinder" then
  652.         return inCylinder(m_objId, self.x, self.y, self.zlow, self.zhigh, self.r)
  653.     end
  654. end
  655.  
  656. function GEO:follow(m_objId)
  657.  
  658.     -- If the m_objId exists...
  659.     if getobject(m_objId) then
  660.         GEO[self.n].f = m_objId  -- Save it (the GEOTimer will access it)
  661.         -- Check to see if the object is a player
  662.         if objecttoplayer(m_objId) then
  663.             GEO[self.n].player = true
  664.         end
  665.     end
  666. end
  667.  
  668. function GEO:freeze()
  669.  
  670.     -- Nullify the saved m_objId from GEO:follow()
  671.     GEO[self.n].f = nil
  672. end
  673.  
  674. function GEO.followedBy(m_objId)
  675.  
  676.     -- Initialize table
  677.     local geos = {}
  678.    
  679.     -- Loop through the GEO table
  680.     for k,v in pairs(GEO) do
  681.         if type(v) == "table" and k ~= "__index" then  -- make sure we're actually getting a GEO object
  682.             if v.f == m_objId then
  683.                 -- If this GEO has this m_objId saved, insert it into the geos table.
  684.                 table.insert(geos, v)
  685.             end
  686.         end
  687.     end
  688.    
  689.     -- Return the GEOs following m_objId in a table.
  690.     return geos
  691. end
  692.  
  693. function GEO.cleanup(player)
  694.  
  695.     local m_player = getplayer(player)
  696.     local m_objId = readdword(m_player, 0x34)
  697.     local geos = GEO.followedBy(m_objId)
  698.     for k,v in ipairs(geos) do
  699.         v:delete()
  700.     end
  701. end
  702.  
  703. function GEO:velocity(x, y, z)
  704.  
  705.     GEO[self.n].vx = x or GEO[self.n].vx
  706.     GEO[self.n].vy = y or GEO[self.n].vy
  707.     GEO[self.n].vz = z or GEO[self.n].vz
  708. end
  709.  
  710. function GEO:killzone(bool)
  711.  
  712.     if bool == true then
  713.         GEO[self.n].kz = true
  714.     elseif bool == false then
  715.         GEO[self.n].kz = false
  716.     elseif bool == nil then
  717.         return GEO[self.n].kz or false
  718.     end
  719. end
  720.  
  721. function GEO:damagezone(bool, rate, density)
  722.  
  723.     if bool == true then
  724.         GEO[self.n].dz = rate or 1  -- Default to 1 fire per second
  725.         GEO[self.n].density = density or 1  -- Default to 1 flame projectile per fire
  726.     elseif bool == false then
  727.         GEO[self.n].dz = nil
  728.         GEO[self.n].density = nil
  729.     elseif bool == nil then  -- If nothing is passed, return true if this GEO is a damagezone, false if not.
  730.         if GEO[self.n].dz then
  731.             return true
  732.         else
  733.             return false
  734.         end
  735.     end
  736. end
  737.  
  738. function GEO:face(orientation, direction)
  739.  
  740.     -- If this is a rectangular prism...
  741.     if self.t == "rectprism" then
  742.         orientation = orientation or "z"
  743.         direction = direction or "+"
  744.         if orientation == "z" then
  745.             local width = self.lx
  746.             local height = self.ly
  747.             local highlow
  748.             if direction == "+" then
  749.                 highlow = self.zhigh
  750.             else
  751.                 highlow = self.zlow
  752.             end
  753.            
  754.             -- Create a new rectangle which overlays the specified face and return that rectangle.
  755.             return GEO.newRect(self.n .. "ZFace" .. os.time(), width, height, self.x, self.y, highlow, orientation)
  756.            
  757.         elseif orientation == "x" then
  758.             local width = self.ly
  759.             local height = self.lz
  760.             local highlow
  761.             if direction == "+" then
  762.                 highlow = self.xhigh
  763.             else
  764.                 highlow = self.xlow
  765.             end
  766.            
  767.             return GEO.newRect(self.n .. "XFace" .. os.time(), width, height, highlow, self.y, self.z, orientation)
  768.        
  769.         elseif orientation == "y" then
  770.             local width = self.lx
  771.             local height = self.lz
  772.             local highlow
  773.             if direction == "+" then
  774.                 highlow = self.yhigh
  775.             else
  776.                 highlow = self.ylow
  777.             end
  778.            
  779.             return GEO.newRect(self.n .. "YFace" .. os.time(), width, height, self.x, highlow, self.z, orientation)
  780.         end
  781.    
  782.     -- If this is a cylinder...
  783.     elseif self.t == "cylinder" then
  784.         if orientation == "z" then
  785.             local highlow
  786.             if direction == "+" then
  787.                 highlow = self.zhigh
  788.             else
  789.                 highlow = self.zlow
  790.             end
  791.            
  792.             -- Return a new circle which overlays the specified face and return that circle.
  793.             return GEO.newCircle(self.n .. "ZFace" .. os.time(), self.r, self.x, self.y, highlow, "z")
  794.         else
  795.             hprintf("You may only retrieve the Z face of a cylinder.")
  796.         end
  797.     end
  798. end
  799.  
  800. function GEO:copy(name)
  801.  
  802.     name = name or self.n .. "Copy" .. os.time()
  803.     if not GEO[name] then
  804.         GEO[name] = self
  805.         return GEO[name]
  806.     end
  807. end
  808.  
  809. function GEO:monitor(m_objId)
  810.  
  811.     if getobject(m_objId) then
  812.         GEO[self.n].m = GEO[self.n].m or {}
  813.         GEO[self.n].c = GEO[self.n].c or {}
  814.         GEO[self.n].m[m_objId] = true
  815.     end
  816. end
  817.  
  818. registertimer(10, "GEOTimer")
  819.  
  820. function GEOTimer(id, count)
  821.  
  822.     -- Create a coordinates table for players if it hasn't already been created
  823.     pcoords = pcoords or {}
  824.    
  825.     -- Loop through the GEO table
  826.     for k,v in pairs(GEO) do
  827.         if type(v) == "table" and k ~= "__index" then
  828.             -- If this GEO is following an object...
  829.             if v.f then
  830.                 -- Get the coordinates of the object
  831.                 local x, y, z = getobjectcoords(v.f)
  832.                 if x then  -- If this object exists...
  833.                     if v.player then
  834.                         local player = objecttoplayer(v.f)
  835.                         if player then
  836.                             local m_player = getplayer(player)  -- See if the player is still here
  837.                             if m_player then  -- If they are...
  838.                                 local time_until_respawn = readdword(m_player, 0x2C)  -- Check to see if they're dead
  839.                                 if time_until_respawn == 0 then  -- If they're not...
  840.                                     if v.p then  -- If this GEO has perimeter objects...
  841.                                         for m_objId, coords in pairs(v.p) do
  842.                                             if getobject(m_objId) then
  843.                                                 local ox, oy, oz = unpack(coords)
  844.                                                 local x_diff = x - v.x
  845.                                                 local y_diff = y - v.y
  846.                                                 local z_diff = z - v.z
  847.                                                 local m_object = getobject(m_objId)
  848.                                                 movobjcoords(m_objId, ox + x_diff, oy + y_diff, oz + z_diff)  -- Move them with the GEO.
  849.                                                 GEO[v.n].p[m_objId] = {ox + x_diff, oy + y_diff, oz + z_diff}
  850.                                             end
  851.                                         end
  852.                                     end
  853.                                     v:move(x, y, z)  -- Move the GEO to the player's coordinates
  854.                                 else  -- Otherwise...
  855.                                     v:delete()  -- Delete the GEO.
  856.                                 end
  857.                             else  -- Otherwise...
  858.                                 v:delete()  -- Delete the GEO.
  859.                             end
  860.                         else  -- Otherwise...
  861.                             v:delete()  -- Delete the GEO.
  862.                         end
  863.                     else  -- Otherwise...
  864.                         if v.p then  -- If this GEO has perimeter objects...
  865.                             for m_objId, coords in pairs(v.p) do
  866.                                 if getobject(m_objId) then
  867.                                     local ox, oy, oz = unpack(coords)
  868.                                     local x_diff = x - v.x
  869.                                     local y_diff = y - v.y
  870.                                     local z_diff = z - v.z
  871.                                     local m_object = getobject(m_objId)
  872.                                     movobjcoords(m_objId, ox + x_diff, oy + y_diff, oz + z_diff)  -- Move them with the GEO.
  873.                                     GEO[v.n].p[m_objId] = {ox + x_diff, oy + y_diff, oz + z_diff}
  874.                                 end
  875.                             end
  876.                         end
  877.                         v:move(x, y, z)  -- Don't worry about all of that player nonsense and just move the damn GEO.
  878.                     end
  879.                 else  -- Otherwise...
  880.                     v:delete()  -- Delete the GEO.
  881.                 end
  882.             end
  883.            
  884.             -- If after all of that following nonsense, we still have a GEO...
  885.             if v then
  886.                 -- If this GEO is a killzone...
  887.                 if v.kz then
  888.                     -- Check if anyone is inside of it.
  889.                     for i = 0,15 do
  890.                         if gethash(i) then
  891.                             local m_player = getplayer(i)
  892.                             local m_objId = readdword(m_player, 0x34)
  893.                             if v:contains(m_objId) then
  894.                                 kill(i)  -- Kill that ho.
  895.                             end
  896.                         end
  897.                     end
  898.                 end
  899.                
  900.                 -- If this GEO is a damagezone...
  901.                 if v.dz then
  902.                     if GEO[k] then
  903.                         GEO[k].damagetime = (GEO[k].damagetime or 0) + 0.01
  904.                         if GEO[k].damagetime >= 1 / GEO[k].dz then
  905.                             GEO[k].damagetime = 0
  906.                             -- Create a crapload of flames.
  907.                             for i = 1,v.density do
  908.                                 -- Make the flame projectiles spawn in a random place inside of the GEO.
  909.                                 local x, y, z = v:randcoords()                             
  910.                                 local object = createobject("proj", "weapons\\flamethrower\\flame", 0, 0, false, x, y, z)
  911.                                 local m_object = getobject(object)
  912.                                 -- Randomize the velocity
  913.                                 local obj_x_vel = readfloat(m_object, 0x68) * 100
  914.                                 local obj_y_vel = readfloat(m_object, 0x6C) * 100
  915.                                 local obj_z_vel = readfloat(m_object, 0x70) * 100
  916.                                 local max_vel = math.max(obj_x_vel, obj_y_vel, obj_z_vel)
  917.                                 local vx = math.random(0, max_vel + 1) / 100
  918.                                 local vy = math.random(0, max_vel + 1) / 100
  919.                                 local vz = math.random(0, max_vel + 1) / 100
  920.                                 writefloat(m_object, 0x68, vx)
  921.                                 writefloat(m_object, 0x6C, vy)
  922.                                 writefloat(m_object, 0x70, vz)
  923.                             end
  924.                         end
  925.                     end
  926.                 end
  927.                
  928.                 -- If this GEO is monitoring for objects entering and exiting it...
  929.                 if v.m then
  930.                     -- Loop through the table of objects this GEO is monitoring for.
  931.                     for m_objId,_ in pairs(v.m) do
  932.                         -- If this object still exists...
  933.                         if getobject(m_objId) then
  934.                             -- If this object is inside of the GEO...
  935.                             if v:contains(m_objId) then
  936.                                 -- If the GEO didn't know this object was inside of it 1/100 of a second ago...
  937.                                 if not v.c[m_objId] then
  938.                                     local player = objecttoplayer(m_objId)
  939.                                     -- Call OnGeoEnter.
  940.                                     local allow = OnGeoEnter(v, player, m_objId)
  941.                                     if allow == 0 then
  942.                                         local hash = gethash(player)
  943.                                         if pcoords[hash] then
  944.                                             movobjcoords(m_objId, unpack(pcoords[hash]))
  945.                                         end
  946.                                     else
  947.                                         GEO[k].c[m_objId] = true
  948.                                     end
  949.                                 end
  950.                             else  -- Otherwise...
  951.                                 -- If the GEO thought this object was inside of it 1/100 of a second ago...
  952.                                 if v.c[m_objId] then
  953.                                     local player = objecttoplayer(m_objId)
  954.                                     -- Call OnGeoExit.
  955.                                     local allow = OnGeoExit(v, player, m_objId)
  956.                                     if allow == 0 then
  957.                                         local hash = gethash(player)
  958.                                         if pcoords[hash] then
  959.                                             movobjcoords(m_objId, unpack(pcoords[hash]))
  960.                                         end
  961.                                     else
  962.                                         GEO[k].c[m_objId] = nil
  963.                                     end
  964.                                 end
  965.                             end
  966.                         else  -- Otherwise...
  967.                             GEO[k].m[m_objId] = nil  -- Stop monitoring for this object.
  968.                         end
  969.                     end
  970.                 end
  971.                
  972.                 -- If this GEO has a velocity...
  973.                 if v.vx or v.vy or v.vz then
  974.                     if v.p then  -- If this GEO has perimeter objects...
  975.                         for m_objId, coords in pairs(v.p) do
  976.                             if getobject(m_objId) then
  977.                                 local ox, oy, oz = unpack(coords)
  978.                                 local m_object = getobject(m_objId)
  979.                                 movobjcoords(m_objId, ox + (v.vx or 0), oy + (v.vy or 0), oz + (v.vz or 0))  -- Move them with the GEO.
  980.                                 GEO[v.n].p[m_objId] = {ox + (v.vx or 0), oy + (v.vy or 0), oz + (v.vz or 0)}
  981.                             end
  982.                         end
  983.                     end
  984.                     -- Move that ho.
  985.                     v:move(v.x + (v.vx or 0) / 100, v.y + (v.vy or 0) / 100, v.z + (v.vz or 0) / 100)
  986.                 end
  987.             end
  988.         end
  989.     end
  990.    
  991.     -- Update coordinates at a slight delay for blocking GEO entry/exit (if there is no delay, players in mid-air could end up dying since they'll just be teleported in mid-air perpetually)
  992.     if count % 25 == 0 then
  993.         for i = 0,15 do
  994.             local hash = gethash(i)
  995.             if hash then
  996.                 local m_player = getplayer(i)
  997.                 local time_until_respawn = readdword(m_player, 0x2C)  -- Check to see if they're dead
  998.                 if time_until_respawn == 0 then  -- If they're not...
  999.                     local m_objId = readdword(m_player, 0x34)
  1000.                     pcoords[hash] = {getobjectcoords(m_objId)}
  1001.                 else
  1002.                     pcoords[hash] = nil
  1003.                 end
  1004.             end
  1005.         end
  1006.     end
  1007.    
  1008.     return 1
  1009. end
  1010.  
  1011. function OnGeoEnter(geo, player, m_objId)
  1012.  
  1013.     return 1
  1014. end
  1015.  
  1016. function OnGeoExit(geo, player, m_objId)
  1017.  
  1018.     return 1
  1019. end
Advertisement
Add Comment
Please, Sign In to add comment