[URL="https://github.com/Luabee/Zones"]Zones[/URL] are persistent areas in the map made of multiple concave polygons.
[U]Video:[/U]
[video=youtube;Cht0jQBcVL8]http://www.youtube.com/watch?v=Cht0jQBcVL8[/video]
[U]Github:[/U]
[url]https://github.com/Luabee/Zones[/url]
[U]The SWEP:[/U]
The zone designation SWEP is a universal interface into the API. Any admin can spawn the SWEP on any gamemode and use its 4 modes to create and edit zones of any kind. When you pull the SWEP out, all zones are rendered visibly. Each zone is color-coordinated to its class. A zone's class determines its behavior and config settubgs through the API.
Holding R allows you to change the SWEP settings. You can create, delete, merge, split, edit, and resize zones. Points can also be added and removed from existing zones. When you create a new zone, a small menu appears which allows you to configure the zone's properties.
Putting the SWEP away removes all zone entities and you're left with just the Lua table of zones and the save file. None of the zones are visible by default to anyone who isn't holding the admin-only SWEP. Please note that any changes to zones using the SWEP must be saved manually in the SWEP's reload menu.
[U]The API:[/U]
The Zones API is designed to work with any number of different scripts, all using the same SWEP.
Once the zones are designated, the rest is up to the developer. A simple example is included which scales all damage to players in the zones by a per-zone amount. To create a new zone class you can use zones.RegisterClass().
[lua]
zones.RegisterClass("Class Name", Color(255,0,0)) -- Color is only used in the editor
[/lua]
The new class is added to the list and available in the SWEP config menu. Existing zones can be changed to the new class in their zone edit menu. From there, you can use the GetCurrentZone player method to find which zone the player is standing in.
[lua]
local zone = ply:GetCurrentZone( optional_classname_filter )
[/lua]
Once you've detected whether a player (or point) is in a zone, you can check to see if that zone fits your class before applying the zone behavior. An example of all this can be found [URL="https://github.com/Luabee/Zones/blob/master/zones/lua/autorun/zone_example.lua"]here[/URL].
You can also write a config vgui for your zone's Edit menu. Since any property you save to the zone is saved to the persistent JSON data file, the possibilities are up to the developer.
All zones and their properties are synchronized between the server and all clients, so you can design behaviors for either realm. The zone-detection algorithm is a [URL="https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm"]ray casting algorithm[/URL] which is quite fast. Having many zones on the map at once can begin to have an impact if you check every frame, so you should cache your results every second or so for best results, though it is by no means required.
Zones is meant to be a medium-weight API. You should include a copy of it [I]within[/I] your addon/gamemode. Multiple scripts running different versions will only execute the newest version.
Well there's my ambitious developer-oriented project for the year. Hopefully someone besides me uses it for something. If it finds its way into your script I'd love to know. :)
See, now I don't think today was a good day to release it. Assuming this ain't no bamboozle
[QUOTE=VeXan;52045136]See, now I don't think today was a good day to release it. Assuming this ain't no bamboozle[/QUOTE]
You caught me. The video is 100% CGI. Took me all year.
Can we get the ability to define zone points with 3 planes (for higher precision)?
[QUOTE=maksimiljan;52045209]Can we get the ability to define zone points with 3 planes (for higher precision)?[/QUOTE]
How will that give you higher precision?
[QUOTE=maksimiljan;52045209]Can we get the ability to define zone points with 3 planes (for higher precision)?[/QUOTE]
You can merge zones of different heights to create [I]basically[/I] any shape found in normal Source engine maps. You can't make things like spheres though.
The reason it uses an x/y polygon with a z height as opposed to a x/y/z mesh is to make the zone detection algorithm as fast as possible. Merging zones together removes most of the shape limitations that would exist.
This is quite cool. I have a few suggestions, why not use a bbox test before doing the poly intersection queries? Just compute the max bounds once the zone changed.
Also as for the networking I noticed you send the entire table to every client if one of the zones changed or a new client joins, wouldn't it be wise to only send whatever changed instead of the entire table and only to the player that actually needs the information. And why is the network code inside a Tick hook when you only need to do it at the given time when required.
Edit: Also it would be decent gesture to allow the user to specify the save file.
Edit 2: Now you got me worked up, this is pretty cool. I'm gonna try to add some sort of room fill where u simply specify the bounds and it tries to generate them automatically.
[QUOTE=Zeh Matt;52049830]This is quite cool. I have a few suggestions, why not use a bbox test before doing the poly intersection queries? Just compute the max bounds once the zone changed.
Also as for the networking I noticed you send the entire table to every client if one of the zones changed or a new client joins, wouldn't it be wise to only send whatever changed instead of the entire table and only to the player that actually needs the information. And why is the network code inside a Tick hook when you only need to do it at the given time when required.
Edit: Also it would be decent gesture to allow the user to specify the save file.
Edit 2: Now you got me worked up, this is pretty cool. I'm gonna try to add some sort of room fill where u simply specify the bounds and it tries to generate them automatically.[/QUOTE]
I like that bbox caching idea. Might integrate it if I can prove it works faster.
And it only networks once per tick at max because sometimes it calls zones.Sync() twice in a frame which could cause sync errors. So zone.Sync() just tells the system to sync next tick.
And I send the whole table because it's simpler to code it that way. It's only done every once and a while when admins are editing the zones so it shouldn't be a problem.
EDIT:
I updated the github to use that bbox method. It improved computation time by a small number. Thanks for the suggestion! :)
It also only syncs to the new player when they join, not to everyone. This was intended but a bug broke it.
I've also updated the documentation and moved it to the example file.
This is pretty slick!
I'm curious if you have some intend on allowing users to specify some sort of event table, I'm thinking of something simple like this:
[lua]local ZONE = {}
ZONE.Color = Color(255, 255, 255, 128)
ZONE.Name = "My friendly zone name"
function ZONE:PlayerEnter(ply)
end
function ZONE:PlayerLeave(ply)
end
function ZONE:PlayerThink(ply)
end
function ZONE:OnPlayerDeath(ply)
end
etc..
zones.RegisterClass("zonename", ZONE)[/lua]
It would probably simplify a lot of things especially the enter/leave situation.
[QUOTE=Zeh Matt;52051535]I'm curious if you have some intend on allowing users to specify some sort of event table, I'm thinking of something simple like this:
[lua]local ZONE = {}
ZONE.Color = Color(255, 255, 255, 128)
ZONE.Name = "My friendly zone name"
function ZONE:PlayerEnter(ply)
end
function ZONE:PlayerLeave(ply)
end
function ZONE:PlayerThink(ply)
end
function ZONE:OnPlayerDeath(ply)
end
etc..
zones.RegisterClass("zonename", ZONE)[/lua]
It would probably simplify a lot of things especially the enter/leave situation.[/QUOTE]
That looks sexy as fuck, though I don't know how I would test for enter/leave without forcing a current-zone think hook, which I don't want to force since it could be costly.
In response to your first comment about the save file specification, it needs to be named after the map so it loads persistently. Maybe I could save each class as a file and each file would go in a folder for the map, but that sounds pretty extra. Do you think it would be very useful to do it that way?
The github is open source if you want to contribute. :)
[QUOTE=bobbleheadbob;52051557]That looks sexy as fuck, though I don't know how I would test for enter/leave without forcing a current-zone think hook, which I don't want to force since it could be costly.
In response to your first comment about the save file specification, it needs to be named after the map so it loads persistently. Maybe I could save each class as a file and each file would go in a folder for the map, but that sounds pretty extra. Do you think it would be very useful to do it that way?
The github is open source if you want to contribute. :)[/QUOTE]
Well for the save path specification, some servers may use different map versions which are essentially the same maps with a few corrections, so it would be somewhat neat for some manual save/load mechanism.
As for the enter/leave I have a few things in mind. One would be to initialize the physics and set it to trigger that would even remove all the custom tests, the other thing is some recent update introduced PVS testing so that might be a thing to use.
It would also speed up getting the zones the player is currently in I suppose.
[QUOTE=bobbleheadbob;52051557]That looks sexy as fuck, though I don't know how I would test for enter/leave without forcing a current-zone think hook, which I don't want to force since it could be costly.
In response to your first comment about the save file specification, it needs to be named after the map so it loads persistently. Maybe I could save each class as a file and each file would go in a folder for the map, but that sounds pretty extra. Do you think it would be very useful to do it that way?
The github is open source if you want to contribute. :)[/QUOTE]
Metastruct zone system is based on physics, could be some ent collision, not sure to remember exactly how it works
[QUOTE=pierre0158;52051944]Metastruct zone system is based on physics, could be some ent collision, not sure to remember exactly how it works[/QUOTE]
They are just primitive boxes.
[QUOTE=Zeh Matt;52052213]They are just primitive boxes.[/QUOTE]
But as far as i remember, you can create collision shapes with poly, right ?
Broken.
Putted in addons.
[IMG]http://i.imgur.com/UnSXAwi.png[/IMG]
[QUOTE='Hat [RU];52054337']Broken.
Putted in addons.[/QUOTE]
Look at the installation instructions in the readme; you cannot just drop it in addons.
[editline]3rd April 2017[/editline]
[QUOTE=bobbleheadbob;52045425]You can merge zones of different heights to create [I]basically[/I] any shape found in normal Source engine maps. You can't make things like spheres though.
The reason it uses an x/y polygon with a z height as opposed to a x/y/z mesh is to make the zone detection algorithm as fast as possible. Merging zones together removes most of the shape limitations that would exist.[/QUOTE]
Could you make a sphere approximation with a Riemann sum? What's the recommended max amount of polys per zone?
[QUOTE=code_gs;52054598]
[editline]3rd April 2017[/editline]
What's the recommended max amount of polys per zone?
[/quote]
There isn't really a max polygons per zone, since the algorithm is just basically a worst-case of O(2n) where n is the count of all points in all polygons. My recommendation is to just simplify where possible, but don't literally cut corners.
EDIT:
Just pushed an update to make it O(n)
[QUOTE=code_gs;52054598]
Could you make a sphere approximation with a Riemann sum?[/QUOTE]
It can be done manually right now I suppose.
If you make a little algorithm for me which returns a table of layers, each being a table of vertices, as well as a table of heights corresponding to those layers, I can see about working it in. You'd only need to do the bottom half of the sphere, with the top half reflected due to the height property.
EDIT 2:
You can snap to walls now by holding E while placing the zone.
[video=youtube;-Hbp4QHOx3g]http://www.youtube.com/watch?v=-Hbp4QHOx3g[/video]
[QUOTE=bobbleheadbob;52054914]O(2n)
EDIT:
Just pushed an update to make it O(n)[/QUOTE]
Just FYI, normally we don't count constant factors like 2, or even lower factors of n like the +n in n²+n. In other words, O(n) and O(2n) are the same thing.
I don't mean to say you didn't improve your algorithm. If you made it twice as fast, that's [i]awesome[/i], but it doesn't change the big O notation if it. O(whatever) measures the [i]growth rate[/i] of the time it takes to run an algorithm compared to the input size; not the actual time.
[QUOTE=NeatNit;52056378]Just FYI, normally we don't count constant factors like 2, or even lower factors of n like the +n in n²+n. In other words, O(n) and O(2n) are the same thing.
I don't mean to say you didn't improve your algorithm. If you made it twice as fast, that's [i]awesome[/i], but it doesn't change the big O notation if it. O(whatever) measures the [i]growth rate[/i] of the time it takes to run an algorithm compared to the input size; not the actual time.[/QUOTE]
Thanks I'll try to remember that. I take the class on it next semester.
Thanks to Zeh Matt I've also cut down on the expense of finding the current zone of a player using mapping and cached results. The guy's a genius, everyone.
Sorry, you need to Log In to post a reply to this thread.