aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Blackmon <bob.blackmon@ymail.com>2017-04-02 22:50:30 -0400
committerBob Blackmon <bob.blackmon@ymail.com>2017-04-02 22:50:30 -0400
commit6647a360d40d556171af76bff451638c0cdac53b (patch)
tree16a380b56df1dc30f79b6eaf8081b652a2f72eb6
parentd1bd1d49f0e63fc6a4e8f60613a7cc2205897928 (diff)
downloadzones-6647a360d40d556171af76bff451638c0cdac53b.tar.gz
zones-6647a360d40d556171af76bff451638c0cdac53b.tar.bz2
zones-6647a360d40d556171af76bff451638c0cdac53b.zip
Add BBox testing
Now tests BBox of each area before doing a polygon test, which improves computation speed.
-rw-r--r--zones/lua/weapons/weapon_zone_designator.lua11
-rw-r--r--zones/lua/zones.lua57
2 files changed, 62 insertions, 6 deletions
diff --git a/zones/lua/weapons/weapon_zone_designator.lua b/zones/lua/weapons/weapon_zone_designator.lua
index 90f96f5..fd2c0c5 100644
--- a/zones/lua/weapons/weapon_zone_designator.lua
+++ b/zones/lua/weapons/weapon_zone_designator.lua
@@ -159,6 +159,7 @@ function SWEP:PrimaryAttack()
until ( next == curr )
zones.List[curr:GetZoneID()].height[curr:GetAreaNumber()] = curr:GetTall()
+ zones.CalcBounds(zones.List[id])
self:SetCurrentPoint(NULL)
@@ -210,7 +211,11 @@ function SWEP:PrimaryAttack()
n = n:GetNext()
until (n == new)
+
zones.List[id].points[areanum] = pts
+
+ zones.CalcBounds(zones.List[id])
+
zones.Sync()
end
@@ -295,6 +300,9 @@ function SWEP:SecondaryAttack()
until ( next == curr )
zones.List[curr:GetZoneID()].height[curr:GetAreaNumber()] = curr:GetTall()
+ zones.CalcBounds(zones.List[curr:GetZoneID()])
+
+ zones.Sync()
self:SetCurrentPoint(NULL)
@@ -340,6 +348,9 @@ function SWEP:SecondaryAttack()
until (n == next)
zones.List[id].points[areanum] = pts
+
+ zones.CalcBounds(zones.List[id])
+
zones.Sync()
self:SetCurrentPoint(last)
diff --git a/zones/lua/zones.lua b/zones/lua/zones.lua
index c005c07..00cf4b8 100644
--- a/zones/lua/zones.lua
+++ b/zones/lua/zones.lua
@@ -1,5 +1,5 @@
-local version = 1.0 -- Older versions will not run if a newer version is used in another script.
+local version = 1.1 -- Older versions will not run if a newer version is used in another script.
--[[
ZONES - by Bobbleheadbob
WARNING: If you edit any of these files, make them use a different namespace. Multiple scripts may depend on this library so modifying it can break other scripts.
@@ -53,7 +53,7 @@ zones.List = zones.List or {}
--[[ --Example of a zone.
zones.List[1] = { -- 1 is the zone ID. Automatically assigned.
- -- points, height, and class are reserved.
+ -- points, height, bounds, and class are reserved.
points = { --List of areas in 3D space which define the zone.
{ --each area is a list of points. Areas should intersect with one another but they don't have to.
Vector(),
@@ -67,6 +67,16 @@ zones.List = zones.List or {}
},
},
height = {200,100}, -- How tall each area of the zone is. Each entry corresponds to an area listed above.
+ bounds = { --List of the min/max points in each area. Used to speed up point-in-zone testing. These are calculated when the zone is created/changed.
+ {
+ mins=Vector(),
+ maxs=Vector(),
+ },
+ {
+ mins=Vector(),
+ maxs=Vector(),
+ },
+ },
class = "GMaps Area", -- Zones with different classes are created and treated separately. Use zones.RegisterClass to create a new one.
-- Zones can have any other values saved to them. If you save a player, make sure to save it as a steamid.
@@ -98,7 +108,9 @@ end
function zones.GetZoneAt(pos,class) --works like above, except uses any point.
for k,zone in pairs(zones.List) do
if class and class != zone.class then continue end
+
for k1, points in pairs(zone.points) do
+ if not pos:WithinAABox(zone.bounds[k1].mins,zone.bounds[k1].maxs) then continue end
if zones.PointInPoly(pos,points) then
local z = points[1].z
if pos.z >= z and pos.z < z + zone.height[k1] then
@@ -114,6 +126,7 @@ function zones.GetZonesAt(pos,class) --works like above, except uses any point.
for k,zone in pairs(zones.List) do
if class and class != zone.class then continue end
for k1, points in pairs(zone.points) do
+ if not pos:WithinAABox(zone.bounds[k1].mins,zone.bounds[k1].maxs) then continue end
if zones.PointInPoly(pos,points) then
local z = points[1].z
if pos.z >= z and pos.z < z + zone.height[k1] then
@@ -138,6 +151,11 @@ function zones.FindByClass(class)
return tbl
end
+--Returns the numerical ID of a zone.
+function zones.GetID(zone)
+ return table.KeyFromValue(zones.List,zone)
+end
+
if SERVER then
util.AddNetworkString("zones_sync")
@@ -157,6 +175,13 @@ if SERVER then
function zones.LoadZones()
local tbl = file.Read("zones/"..game.GetMap():gsub("_","-"):lower()..".txt", "DATA")
zones.List = tbl and util.JSONToTable(tbl) or {}
+
+ //Update legacy files:
+ for k,v in pairs(zones.List)do
+ if not v.bounds then
+ zones.CalcBounds(v)
+ end
+ end
end
local sync = false
@@ -181,20 +206,23 @@ if SERVER then
local zone = {
points = {{}}, --only 1 area when creating a new zone.
height = {ent:GetTall()},
- class = ent:GetZoneClass()
+ class = ent:GetZoneClass(),
+ bounds = {}
}
local id = table.maxn(zones.List) + 1
local cur = ent
repeat
-
- zone.points[1][#zone.points[1]+1] = cur:GetPos() - Vector(0,0,2)
+ local pos = cur:GetPos() - Vector(0,0,2)
+ zone.points[1][#zone.points[1]+1] = pos
cur:SetZoneID(id)
cur = cur:GetNext()
until (cur == ent)
+ zones.CalcBounds(zone)
+
zones.List[id] = zone
zones.Sync()
@@ -204,6 +232,20 @@ if SERVER then
end
+ function zones.CalcBounds(zone)
+ zone.bounds = {}
+ for areanum,area in pairs(zone.points)do
+ local mins,maxs = Vector(10000000,10000000,area[1].z), Vector(-10000000,-10000000,area[1].z + zone.height[areanum])
+ for k,pos in pairs(area) do
+ maxs.x = math.max(pos.x, maxs.x)
+ maxs.y = math.max(pos.y, maxs.y)
+ mins.x = math.min(pos.x, mins.x)
+ mins.y = math.min(pos.y, mins.y)
+ end
+ zone.bounds[areanum] = {mins=mins,maxs=maxs}
+ end
+ end
+
function zones.Remove(id)
zones.List[id] = nil
zones.Sync()
@@ -259,6 +301,7 @@ if SERVER then
table.Add(zto.points, zfrom.points)
table.Add(zto.height, zfrom.height)
+ table.Add(zto.bounds, zfrom.bounds)
zones.Remove(from)
@@ -268,10 +311,11 @@ if SERVER then
function zones.Split(id,areanum)
local zone = zones.List[id]
- local pts, h = zone.points[areanum], zone.height[areanum]
+ local pts, h, bound = zone.points[areanum], zone.height[areanum], zone.bounds[areanum]
table.remove(zone.points,areanum)
table.remove(zone.height,areanum)
+ table.remove(zone.bounds,areanum)
if #zone.points == 0 then
zones.Remove(id)
@@ -280,6 +324,7 @@ if SERVER then
local new = table.Copy(zone)
new.points = {pts}
new.height = {h}
+ new.bounds = {bound}
local id = table.maxn(zones.List)+1
zones.List[id] = new