Advertisement
rockbandcheeseman

GEOMain 1.021

Nov 17th, 2012
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 30.16 KB | None | 0 0
  1. -- GEOs (Geometric Environment Objects) 1.01
  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.     GEO[self.n] = nil
  308.     hprintf("Geo \"" .. self.n .. "\" deleted.")
  309. end
  310.  
  311. function GEO:move(x, y, z)
  312.  
  313.     -- Move the center of the object
  314.     -- Default to GEO's current coordinates
  315.     GEO[self.n].x = x or GEO[self.n].x
  316.     GEO[self.n].y = y or GEO[self.n].y
  317.     GEO[self.n].z = z or GEO[self.n].z
  318.    
  319.     -- If this is a rectangular prism...
  320.     if self.t == "rectprism" then
  321.         -- Change the x, y, and z lows and highs accordingly to adjust to the new center
  322.         GEO[self.n].xlow = x - GEO[self.n].lx / 2  
  323.         GEO[self.n].xhigh = GEO[self.n].lx / 2 + x
  324.         GEO[self.n].ylow = y - GEO[self.n].ly / 2
  325.         GEO[self.n].yhigh = GEO[self.n].ly / 2 + y
  326.         GEO[self.n].zlow = z - GEO[self.n].lz / 2
  327.         GEO[self.n].zhigh = GEO[self.n].lz / 2 + z
  328.    
  329.     -- If this is a rectangle...
  330.     elseif self.t == "rectangle" then
  331.         -- Change the x, y, and z lows and highs accordingly to adjust to the new center (depends on orientation)
  332.         if self.o == "z" then
  333.             GEO[self.n].xlow = self.x - self.width / 2
  334.             GEO[self.n].xhigh = self.x + self.width / 2
  335.             GEO[self.n].ylow = self.y - self.height / 2
  336.             GEO[self.n].yhigh = self.y + self.height / 2
  337.             GEO[self.n].zlow = self.z
  338.             GEO[self.n].zhigh = self.z
  339.         elseif self.o == "x" then
  340.             GEO[self.n].xlow = self.x
  341.             GEO[self.n].xhigh = self.x
  342.             GEO[self.n].ylow = self.y - self.width / 2
  343.             GEO[self.n].yhigh = self.y + self.width / 2
  344.             GEO[self.n].zlow = self.z - self.height / 2
  345.             GEO[self.n].zhigh = self.z + self.height / 2
  346.         elseif self.o == "y" then
  347.             GEO[self.n].xlow = self.x - self.width / 2
  348.             GEO[self.n].xhigh = self.x + self.width / 2
  349.             GEO[self.n].ylow = self.y
  350.             GEO[self.n].yhigh = self.y
  351.             GEO[self.n].zlow = self.z - self.height / 2
  352.             GEO[self.n].zhigh = self.z + self.height / 2
  353.         end
  354.    
  355.     -- If this is a cylinder...
  356.     elseif self.t == "cylinder" then
  357.         GEO[self.n].zlow = self.z - self.h / 2
  358.         GEO[self.n].zhigh = self.z + self.h / 2
  359.     end
  360. end
  361.  
  362. function GEO:radius(new)
  363.  
  364.     if self.t == "sphere" or self.t == "circle" or self.t == "cylinder" then
  365.         if new then  -- If "new" is defined...
  366.             GEO[self.n].r = new  -- Change the radius to its value.
  367.         else  -- If not...
  368.             return GEO[self.n].r  -- Return its current radius.
  369.         end
  370.     end
  371. end
  372.  
  373. function GEO:size(x, y, z)
  374.  
  375.     -- If this is a rectangular prism...
  376.     if self.t == "rectprism" then
  377.         if x or y or z then  -- If any of these variables have been defined...
  378.             -- Adjust lengths and x, y, and z highs and lows accordingly.
  379.             GEO[self.n].lx = x or GEO[self.n].lx
  380.             GEO[self.n].ly = y or GEO[self.n].ly
  381.             GEO[self.n].lz = z or GEO[self.n].lz
  382.             GEO[self.n].xlow = GEO[self.n].x - x / 2
  383.             GEO[self.n].xhigh = x / 2 + GEO[self.n].x
  384.             GEO[self.n].ylow = GEO[self.n].y - y / 2
  385.             GEO[self.n].yhigh = y / 2 + GEO[self.n].y
  386.             GEO[self.n].zlow = GEO[self.n].z - z / 2
  387.             GEO[self.n].zhigh = z / 2 + GEO[self.n].z
  388.         else  -- Otherwise...
  389.             return GEO[self.n].lx, GEO[self.n].ly, GEO[self.n].lz  -- Return the x, y, and z lengths.
  390.         end
  391.    
  392.     -- If this is a rectangle...
  393.     elseif self.t == "rectangle" then
  394.         if x or y or z then  -- If any of these variables are defined...
  395.             -- Adjust width, height, and x, y, and z highs and lows accordingly (depends on orientation).
  396.             if self.o == "z" then
  397.                 GEO[self.n].width = x
  398.                 GEO[self.n].height = y
  399.                 GEO[self.n].xlow = self.x - self.width / 2
  400.                 GEO[self.n].xhigh = self.x + self.width / 2
  401.                 GEO[self.n].ylow = self.y - self.height / 2
  402.                 GEO[self.n].yhigh = self.y + self.height / 2
  403.                 GEO[self.n].zlow = self.z
  404.                 GEO[self.n].zhigh = self.z
  405.             elseif self.o == "x" then
  406.                 GEO[self.n].width = y
  407.                 GEO[self.n].height = z
  408.                 GEO[self.n].xlow = self.x
  409.                 GEO[self.n].xhigh = self.x
  410.                 GEO[self.n].ylow = self.y - self.width / 2
  411.                 GEO[self.n].yhigh = self.y + self.width / 2
  412.                 GEO[self.n].zlow = self.z - self.height / 2
  413.                 GEO[self.n].zhigh = self.z + self.height / 2
  414.             elseif self.o == "y" then
  415.                 GEO[self.n].width = x
  416.                 GEO[self.n].height = z
  417.                 GEO[self.n].xlow = self.x - self.width / 2
  418.                 GEO[self.n].xhigh = self.x + self.width / 2
  419.                 GEO[self.n].ylow = self.y
  420.                 GEO[self.n].yhigh = self.y
  421.                 GEO[self.n].zlow = self.z - self.height / 2
  422.                 GEO[self.n].zhigh = self.z + self.height / 2
  423.             end
  424.         else  -- Otherwise...
  425.             return GEO[self.n].width, GEO[self.n].height  -- Return the width and height of the rectangle.
  426.         end
  427.    
  428.     -- If this is a cylinder...
  429.     elseif self.t == "cylinder" then
  430.         local h = x or y or z  -- Whichever variable is defined, it is taken as the height.
  431.         if h then  -- If a height is specified...
  432.             -- Adjust height and z high and low accordingly.
  433.             GEO[self.n].h = h
  434.             GEO[self.n].zlow = self.z - h / 2
  435.             GEO[self.n].zhigh = self.z + h / 2
  436.         else  -- Otherwise...
  437.             return GEO[self.n].h  -- Return the height.
  438.         end
  439.     end
  440. end
  441.  
  442. function GEO:extend(orienation, direction, amount)
  443.  
  444.     -- Change the direction from "+" or "-" to "high" or "low".
  445.     local dir
  446.     dir = string.gsub(direction, "-", "low")
  447.     dir = string.gsub(direction, "+", "high")
  448.    
  449.     -- Get the face we're trying to extend (i.e. "xhigh")
  450.     local face = string.lower(orientation) .. direction
  451.    
  452.     -- If this is a rectangular prism or a rectangle...
  453.     if self.t == "rectprism" or self.t == "rectangle" then
  454.         -- Make sure "face" is actually a valid face (and not something like "cheesederp")
  455.         if self[face] then
  456.             -- 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.
  457.             -- Change the length of the GEO in the orientation specified.
  458.             GEO[self.n]["l" .. string.lower(orientation)] = self["l" .. string.lower(orientation)] + amount
  459.            
  460.             -- Figure out if the positive or negative face is being extended.
  461.             if direction == "+" then
  462.                 GEO[self.n][face] = self[face] + amount
  463.                 GEO[self.n][string.lower(orientation)] = self[string.lower(orientation)] + amount / 2
  464.             else
  465.                 GEO[self.n][face] = self[face] - amount
  466.                 GEO[self.n][string.lower(orientation)] = self[string.lower(orientation)] - amount / 2
  467.             end
  468.         end
  469.    
  470.     -- If this is a cylinder...
  471.     elseif self.t == "cylinder" then
  472.         -- The orientation must be "z"
  473.         if orientation == "z" then
  474.             if self[face] then
  475.                 GEO[self.n].h = self.h + amount
  476.                
  477.                 -- Figure out if the top or bottom face is being extended.
  478.                 if direction == "+" then
  479.                     GEO[self.n][face] = self[face] + amount
  480.                     GEO[self.n].z = self.z + amount / 2
  481.                 else
  482.                     GEO[self.n][face] = self[face] - amount
  483.                     GEO[self.n].z = self.z - amount / 2
  484.                 end
  485.             end
  486.         end
  487.     end
  488. end
  489.  
  490. function GEO:coords()
  491.  
  492.     return self.x, self.y, self.z
  493. end
  494.  
  495. function GEO:high(orientation)
  496.  
  497.     if self.t == "sphere" or self.t == "circle" then
  498.         return self[orientation] + self.r
  499.     elseif self.t == "rectprism" or self.t == "rectangle" then
  500.         return self[orientation .. "high"]
  501.     elseif self.t == "cylinder" then
  502.         if orientation == "z" then
  503.             return self.zhigh
  504.         else
  505.             return self[orientation] + self.r
  506.         end
  507.     end    
  508. end
  509.  
  510. function GEO:low(orientation)
  511.  
  512.     if self.t == "sphere" or self.t == "circle" then
  513.         return self[orientation] - self.r
  514.     elseif self.t == "rectprism" or self.t == "rectangle" then
  515.         return self[orientation .. "low"]
  516.     elseif self.t == "cylinder" then
  517.         if orientation == "z" then
  518.             return self.zlow
  519.         else
  520.             return self[orientation] - self.r
  521.         end
  522.     end    
  523. end
  524.  
  525. function GEO:randcoords()
  526.  
  527.     if self.t == "sphere" then
  528.         return randomInSphere(self.x, self.y, self.z, self.r)
  529.     elseif self.t == "circle" then
  530.         return randomInCircle(self.x, self.y, self.z, self.r, self.o)
  531.     elseif self.t == "cylinder" then
  532.         return randomInCylinder(self.x, self.y, self.zlow, self.zhigh, self.r)
  533.     elseif self.t == "rectprism" or self.t == "rectangle" then
  534.         return randomInRectPrism(self.xlow, self.xhigh, self.ylow, self.yhigh, self.zlow, self.zhigh)
  535.     end
  536. end
  537.  
  538. function GEO:type()
  539.  
  540.     return self.t
  541. end
  542.  
  543. function GEO:orientation()
  544.  
  545.     return self.o
  546. end
  547.  
  548. function GEO:name()
  549.  
  550.     return self.n
  551. end
  552.  
  553. function GEO:perimeter(density, tagType, tagName)
  554.    
  555.     -- Default tagType and tagName to Full-Spectrum Visions
  556.     tagType = tagType or "eqip"
  557.     tagName = tagName or "powerups\\full-spectrum vision"
  558.    
  559.     -- Store all of the perimeter objects in a table
  560.     GEO[self.n].p = GEO[self.n].p or {}
  561.    
  562.     -- Find the change in angle per point from 0 - 2pi (0° - 360°)
  563.     local angle_increment = 2 * math.pi / density
  564.     if self.t == "sphere" or self.t == "cylinder" then
  565.         for i = 1,density do
  566.             -- 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.
  567.             local x = self.r * math.cos(angle_increment * i)
  568.             local y = self.r * math.sin(angle_increment * i)
  569.             local z = self.z
  570.             local m_objId = createobject(tagType, tagName, 0, 0, false, self.x + x, self.y + y, self.z + z)
  571.             GEO[self.n].p[m_objId] = {self.x + x, self.y + y, self.z + z}
  572.         end
  573.     elseif self.t == "circle" then
  574.         if self.o == "z" then
  575.             for i = 1,density do
  576.                 -- 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.
  577.                 local x = self.r * math.cos(angle_increment * i)
  578.                 local y = self.r * math.sin(angle_increment * i)
  579.                 local z = self.z
  580.                 local m_objId = createobject(tagType, tagName, 0, 0, false, self.x + x, self.y + y, self.z + z)
  581.                 GEO[self.n].p[m_objId] = {self.x + x, self.y + y, self.z + z}
  582.             end
  583.         end
  584.     elseif self.t == "rectprism" or self.t == "rectangle" then
  585.         if self.t == "rectangle" then
  586.             if self.o ~= "z" then return end
  587.         end
  588.         -- Create points at four corners of the rectangle
  589.         local o1 = createobject(tagType, tagName, 0, 0, false, self.xhigh, self.yhigh, self.z)
  590.         local o2 = createobject(tagType, tagName, 0, 0, false, self.xhigh, self.ylow, self.z)
  591.         local o3 = createobject(tagType, tagName, 0, 0, false, self.xlow, self.yhigh, self.z)
  592.         local o4 = createobject(tagType, tagName, 0, 0, false, self.xlow, self.ylow, self.z)
  593.         GEO[self.n].p[o1] = {self.xhigh, self.yhigh, self.z}
  594.         GEO[self.n].p[o2] = {self.xhigh, self.yhigh, self.z}
  595.         GEO[self.n].p[o3] = {self.xhigh, self.yhigh, self.z}
  596.         GEO[self.n].p[o4] = {self.xhigh, self.yhigh, self.z}
  597.        
  598.         for i = 1,density do
  599.             local herp = createobject(tagType, tagName, 0, 0, false, self.xhigh - (i * self.lx / density), self.yhigh, self.z)
  600.             local derp = createobject(tagType, tagName, 0, 0, false, self.xhigh, self.yhigh - (i * self.ly / density), self.z)
  601.             local weee = createobject(tagType, tagName, 0, 0, false, self.xhigh - (i * self.lx / density), self.ylow, self.z)
  602.             local cheese = createobject(tagType, tagName, 0, 0, false, self.xlow, self.ylow + (i * self.ly / density), self.z)
  603.             GEO[self.n].p[herp] = {self.xhigh - (i * self.lx / density), self.yhigh, self.z}
  604.             GEO[self.n].p[derp] = {self.xhigh, self.yhigh - (i * self.ly / density), self.z}
  605.             GEO[self.n].p[weee] = {self.xhigh - (i * self.lx / density), self.ylow, self.z}
  606.             GEO[self.n].p[cheese] = {self.xlow, self.ylow + (i * self.ly / density), self.z}
  607.         end
  608.     end
  609. end
  610.  
  611. function GEO:hide()
  612.  
  613.     if self.p then
  614.         for k,v in pairs(GEO[self.n].p) do
  615.             if getobject(k) then
  616.                 destroyobject(k)
  617.                 GEO[self.n].p[k] = nil
  618.             end
  619.         end
  620.     end
  621. end
  622.  
  623. -- Never quite got this to work right, but I'm saving it for the sake of the formula.
  624. --[[function GEO:surface(density)
  625.  
  626.     GEO[self.n].p = GEO[self.n].p or {}
  627.     if self.t == "sphere" then
  628.         local inc = math.pi * (3 - math.sqrt(5))
  629.         local off = 2 / density
  630.         for i = 1,density do
  631.             local y = self.r * i * off - 1 + (off / 2)
  632.             local r = self.r * math.sqrt(1 - y ^ 2)
  633.             local phi = i * inc
  634.             local x = r * math.cos(phi)
  635.             local z = r * math.sin(phi)
  636.             local m_objId = createobject(tagType, tagName, 0, 0, false, x, y, z)
  637.             GEO[self.n].p[m_objId] = {x, y, z}
  638.         end
  639.     end
  640. end--]]
  641.  
  642. function GEO:contains(m_objId)
  643.  
  644.     if self.t == "sphere" then
  645.         return inSphere(m_objId, self.x, self.y, self.z, self.r)
  646.     elseif self.t == "rectprism" or self.t == "rectangle" then
  647.         return inRectPrism(m_objId, self.xlow, self.xhigh, self.ylow, self.yhigh, self.zlow, self.zhigh)
  648.     elseif self.t == "circle" then
  649.         return inCircle(m_objId, self.x, self.y, self.z, self.r, self.o)
  650.     elseif self.t == "cylinder" then
  651.         return inCylinder(m_objId, self.x, self.y, self.zlow, self.zhigh, self.r)
  652.     end
  653. end
  654.  
  655. function GEO:follow(m_objId)
  656.  
  657.     -- If the m_objId exists...
  658.     if getobject(m_objId) then
  659.         GEO[self.n].f = m_objId  -- Save it (the GEOTimer will access it)
  660.         -- Check to see if the object is a player
  661.         if objecttoplayer(m_objId) then
  662.             GEO[self.n].player = true
  663.         end
  664.     end
  665. end
  666.  
  667. function GEO:freeze()
  668.  
  669.     -- Nullify the saved m_objId from GEO:follow()
  670.     GEO[self.n].f = nil
  671. end
  672.  
  673. function GEO.followedBy(m_objId)
  674.  
  675.     -- Initialize table
  676.     local geos = {}
  677.    
  678.     -- Loop through the GEO table
  679.     for k,v in pairs(GEO) do
  680.         if type(v) == "table" and k ~= "__index" then  -- make sure we're actually getting a GEO object
  681.             if v.f == m_objId then
  682.                 -- If this GEO has this m_objId saved, insert it into the geos table.
  683.                 table.insert(geos, v)
  684.             end
  685.         end
  686.     end
  687.    
  688.     -- Return the GEOs following m_objId in a table.
  689.     return geos
  690. end
  691.  
  692. function GEO.cleanup(player)
  693.  
  694.     local m_player = getplayer(player)
  695.     local m_objId = readdword(m_player, 0x34)
  696.     local geos = GEO.followedBy(m_objId)
  697.     for k,v in ipairs(geos) do
  698.         v:delete()
  699.     end
  700. end
  701.  
  702. function GEO:velocity(x, y, z)
  703.  
  704.     GEO[self.n].vx = x or GEO[self.n].vx
  705.     GEO[self.n].vy = y or GEO[self.n].vy
  706.     GEO[self.n].vz = z or GEO[self.n].vz
  707. end
  708.  
  709. function GEO:killzone(bool)
  710.  
  711.     if bool == true then
  712.         GEO[self.n].kz = true
  713.     elseif bool == false then
  714.         GEO[self.n].kz = false
  715.     elseif bool == nil then
  716.         return GEO[self.n].kz or false
  717.     end
  718. end
  719.  
  720. function GEO:damagezone(bool, rate, density)
  721.  
  722.     if bool == true then
  723.         GEO[self.n].dz = rate or 1  -- Default to 1 fire per second
  724.         GEO[self.n].density = density or 1  -- Default to 1 flame projectile per fire
  725.     elseif bool == false then
  726.         GEO[self.n].dz = nil
  727.         GEO[self.n].density = nil
  728.     elseif bool == nil then  -- If nothing is passed, return true if this GEO is a damagezone, false if not.
  729.         if GEO[self.n].dz then
  730.             return true
  731.         else
  732.             return false
  733.         end
  734.     end
  735. end
  736.  
  737. function GEO:face(orientation, direction)
  738.  
  739.     -- If this is a rectangular prism...
  740.     if self.t == "rectprism" then
  741.         orientation = orientation or "z"
  742.         direction = direction or "+"
  743.         if orientation == "z" then
  744.             local width = self.lx
  745.             local height = self.ly
  746.             local highlow
  747.             if direction == "+" then
  748.                 highlow = self.zhigh
  749.             else
  750.                 highlow = self.zlow
  751.             end
  752.            
  753.             -- Create a new rectangle which overlays the specified face and return that rectangle.
  754.             return GEO.newRect(self.n .. "ZFace" .. os.time(), width, height, self.x, self.y, highlow, orientation)
  755.            
  756.         elseif orientation == "x" then
  757.             local width = self.ly
  758.             local height = self.lz
  759.             local highlow
  760.             if direction == "+" then
  761.                 highlow = self.xhigh
  762.             else
  763.                 highlow = self.xlow
  764.             end
  765.            
  766.             return GEO.newRect(self.n .. "XFace" .. os.time(), width, height, highlow, self.y, self.z, orientation)
  767.        
  768.         elseif orientation == "y" then
  769.             local width = self.lx
  770.             local height = self.lz
  771.             local highlow
  772.             if direction == "+" then
  773.                 highlow = self.yhigh
  774.             else
  775.                 highlow = self.ylow
  776.             end
  777.            
  778.             return GEO.newRect(self.n .. "YFace" .. os.time(), width, height, self.x, highlow, self.z, orientation)
  779.         end
  780.    
  781.     -- If this is a cylinder...
  782.     elseif self.t == "cylinder" then
  783.         if orientation == "z" then
  784.             local highlow
  785.             if direction == "+" then
  786.                 highlow = self.zhigh
  787.             else
  788.                 highlow = self.zlow
  789.             end
  790.            
  791.             -- Return a new circle which overlays the specified face and return that circle.
  792.             return GEO.newCircle(self.n .. "ZFace" .. os.time(), self.r, self.x, self.y, highlow, "z")
  793.         else
  794.             hprintf("You may only retrieve the Z face of a cylinder.")
  795.         end
  796.     end
  797. end
  798.  
  799. function GEO:copy(name)
  800.  
  801.     name = name or self.n .. "Copy" .. os.time()
  802.     if not GEO[name] then
  803.         GEO[name] = self
  804.         return GEO[name]
  805.     end
  806. end
  807.  
  808. function GEO:monitor(m_objId)
  809.  
  810.     if getobject(m_objId) then
  811.         GEO[self.n].m = GEO[self.n].m or {}
  812.         GEO[self.n].c = GEO[self.n].c or {}
  813.         GEO[self.n].m[m_objId] = true
  814.     end
  815. end
  816.  
  817. registertimer(10, "GEOTimer")
  818.  
  819. function GEOTimer(id, count)
  820.  
  821.     -- Loop through the GEO table
  822.     for k,v in pairs(GEO) do
  823.         if type(v) == "table" and k ~= "__index" then
  824.             -- If this GEO is following an object...
  825.             if v.f then
  826.                 -- Get the coordinates of the object
  827.                 local x, y, z = getobjectcoords(v.f)
  828.                 if x then  -- If this object exists...
  829.                     if v.player then
  830.                         local player = objecttoplayer(v.f)
  831.                         if player then
  832.                             local m_player = getplayer(player)  -- See if the player is still here
  833.                             if m_player then  -- If they are...
  834.                                 local time_until_respawn = readdword(m_player, 0x2C)  -- Check to see if they're dead
  835.                                 if time_until_respawn == 0 then  -- If they're not...
  836.                                     if v.p then  -- If this GEO has perimeter objects...
  837.                                         for m_objId, coords in pairs(v.p) do
  838.                                             if getobject(m_objId) then
  839.                                                 local ox, oy, oz = unpack(coords)
  840.                                                 local x_diff = x - v.x
  841.                                                 local y_diff = y - v.y
  842.                                                 local z_diff = z - v.z
  843.                                                 local m_object = getobject(m_objId)
  844.                                                 movobjcoords(m_objId, ox + x_diff, oy + y_diff, oz + z_diff)  -- Move them with the GEO.
  845.                                                 GEO[v.n].p[m_objId] = {ox + x_diff, oy + y_diff, oz + z_diff}
  846.                                             end
  847.                                         end
  848.                                     end
  849.                                     v:move(x, y, z)  -- Move the GEO to the player's coordinates
  850.                                 else  -- Otherwise...
  851.                                     v:delete()  -- Delete the GEO.
  852.                                 end
  853.                             else  -- Otherwise...
  854.                                 v:delete()  -- Delete the GEO.
  855.                             end
  856.                         else  -- Otherwise...
  857.                             v:delete()  -- Delete the GEO.
  858.                         end
  859.                     else  -- Otherwise...
  860.                         if v.p then  -- If this GEO has perimeter objects...
  861.                             for m_objId, coords in pairs(v.p) do
  862.                                 if getobject(m_objId) then
  863.                                     local ox, oy, oz = unpack(coords)
  864.                                     local x_diff = x - v.x
  865.                                     local y_diff = y - v.y
  866.                                     local z_diff = z - v.z
  867.                                     local m_object = getobject(m_objId)
  868.                                     movobjcoords(m_objId, ox + x_diff, oy + y_diff, oz + z_diff)  -- Move them with the GEO.
  869.                                     GEO[v.n].p[m_objId] = {ox + x_diff, oy + y_diff, oz + z_diff}
  870.                                 end
  871.                             end
  872.                         end
  873.                         v:move(x, y, z)  -- Don't worry about all of that player nonsense and just move the damn GEO.
  874.                     end
  875.                 else  -- Otherwise...
  876.                     v:delete()  -- Delete the GEO.
  877.                 end
  878.             end
  879.            
  880.             -- If after all of that following nonsense, we still have a GEO...
  881.             if v then
  882.                 -- If this GEO is a killzone...
  883.                 if v.kz then
  884.                     -- Check if anyone is inside of it.
  885.                     for i = 0,15 do
  886.                         if gethash(i) then
  887.                             local m_player = getplayer(i)
  888.                             local m_objId = readdword(m_player, 0x34)
  889.                             if v:contains(m_objId) then
  890.                                 kill(i)  -- Kill that ho.
  891.                             end
  892.                         end
  893.                     end
  894.                 end
  895.                
  896.                 -- If this GEO is a damagezone...
  897.                 if v.dz then
  898.                     if GEO[k] then
  899.                         GEO[k].damagetime = (GEO[k].damagetime or 0) + 0.01
  900.                         if GEO[k].damagetime >= 1 / GEO[k].dz then
  901.                             GEO[k].damagetime = 0
  902.                             -- Create a crapload of flames.
  903.                             for i = 1,v.density do
  904.                                 -- Make the flame projectiles spawn in a random place inside of the GEO.
  905.                                 local x, y, z = v:randcoords()                             
  906.                                 local object = createobject("proj", "weapons\\flamethrower\\flame", 0, 0, false, x, y, z)
  907.                                 local m_object = getobject(object)
  908.                                 -- Randomize the velocity
  909.                                 local obj_x_vel = readfloat(m_object, 0x68) * 100
  910.                                 local obj_y_vel = readfloat(m_object, 0x6C) * 100
  911.                                 local obj_z_vel = readfloat(m_object, 0x70) * 100
  912.                                 local max_vel = math.max(obj_x_vel, obj_y_vel, obj_z_vel)
  913.                                 local vx = math.random(0, max_vel + 1) / 100
  914.                                 local vy = math.random(0, max_vel + 1) / 100
  915.                                 local vz = math.random(0, max_vel + 1) / 100
  916.                                 writefloat(m_object, 0x68, vx)
  917.                                 writefloat(m_object, 0x6C, vy)
  918.                                 writefloat(m_object, 0x70, vz)
  919.                             end
  920.                         end
  921.                     end
  922.                 end
  923.                
  924.                 -- If this GEO is monitoring for objects entering and exiting it...
  925.                 if v.m then
  926.                     -- Loop through the table of objects this GEO is monitoring for.
  927.                     for m_objId,_ in pairs(v.m) do
  928.                         -- If this object still exists...
  929.                         if getobject(m_objId) then
  930.                             -- If this object is inside of the GEO...
  931.                             if v:contains(m_objId) then
  932.                                 -- If the GEO didn't know this object was inside of it 1/100 of a second ago...
  933.                                 if not v.c[m_objId] then
  934.                                     -- Call OnGeoEnter.
  935.                                     OnGeoEnter(v, objecttoplayer(m_objId), m_objId)
  936.                                     GEO[k].c[m_objId] = true
  937.                                 end
  938.                             else  -- Otherwise...
  939.                                 -- If the GEO thought this object was inside of it 1/100 of a second ago...
  940.                                 if v.c[m_objId] then
  941.                                     -- Call OnGeoExit.
  942.                                     OnGeoExit(v, objecttoplayer(m_objId), m_objId)
  943.                                     GEO[k].c[m_objId] = nil
  944.                                 end
  945.                             end
  946.                         else  -- Otherwise...
  947.                             GEO[k].m[m_objId] = nil  -- Stop monitoring for this object.
  948.                         end
  949.                     end
  950.                 end
  951.                
  952.                 -- If this GEO has a velocity...
  953.                 if v.vx or v.vy or v.vz then
  954.                     if v.p then  -- If this GEO has perimeter objects...
  955.                         for m_objId, coords in pairs(v.p) do
  956.                             if getobject(m_objId) then
  957.                                 local ox, oy, oz = unpack(coords)
  958.                                 local m_object = getobject(m_objId)
  959.                                 movobjcoords(m_objId, ox + (v.vx or 0), oy + (v.vy or 0), oz + (v.vz or 0))  -- Move them with the GEO.
  960.                                 GEO[v.n].p[m_objId] = {ox + (v.vx or 0), oy + (v.vy or 0), oz + (v.vz or 0)}
  961.                             end
  962.                         end
  963.                     end
  964.                     -- Move that ho.
  965.                     v:move(v.x + (v.vx or 0) / 100, v.y + (v.vy or 0) / 100, v.z + (v.vz or 0) / 100)
  966.                 end
  967.             end
  968.         end
  969.     end
  970.    
  971.     return 1
  972. end
  973.  
  974. function OnGeoEnter(geo, player, m_objId)
  975.  
  976.  
  977. end
  978.  
  979. function OnGeoExit(geo, player, m_objId)
  980.  
  981.  
  982. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement