This module aims to enrich Garry's Mod's Lua API by offering an intuitive Lua interface for several visibility-related engine functions not currently implemented in the game's native API. While some functions mirror their C++ counterparts, most have been restructured to align seamlessly with Lua scripting paradigms. Most notably, the adaptation of PVS byte buffers into user-friendly Lua userdata objects, complete with methods for easy access and manipulation of relevant data.
With the help of this module, server-side Lua scripts are capable of accessing information regarding Clusters, PVS and Areas.
-- Load the visinfo module
require("visinfo")
-- Store PVS userdata of cluster 123
local pvs = GetPVSForCluster(123)
print("Is cluster 164 visible from cluster 123?", pvs[164])
-- > Is cluster 164 visible from cluster 123? [true/false]
print("Is Vector(123, 456, 789) within the PVS of cluster 123?", pvs:CheckOrigin(Vector(123, 456, 789)))
-- > Is Vector(123, 456, 789) within the PVS of cluster 123? [true/false]
print("How many clusters are visible in cluster 123's PVS?", #pvs)
-- > How many clusters are visible in this PVS? [number of visible clusters]
Finds and returns the ID of the cluster containing the specified location.
Name | Type | Description |
---|---|---|
origin |
Vector |
The position whose cluster we want the ID of. |
Name | Type | Description |
---|---|---|
cluster |
number |
The ID of the cluster if it was found; -1 if it was not. |
Tip
math.ceil(0.125 * GetClusterCount())
returns the appropriate length in bytes for a PVS buffer in the current map. There's really no use for this information in the Lua environment, though, as this module aims to phase out any direct interaction with said byte buffers. Nonetheless, I'm including it here.
Name | Type | Description |
---|---|---|
count |
number |
The total number of visbility clusters within the current map. |
PVS
GetPVSForCluster(number
cluster)
Retrieves the Potentially Visible Set (PVS) data associated with the specified visibility cluster in the current map.
Name | Type | Description |
---|---|---|
cluster |
number |
A number representing the ID of a visibility cluster in the map. |
Name | Type | Description |
---|---|---|
pvs |
PVS |
A userdata object for interacting with the PVS data associated with the provided cluster ID. |
Retrieves the bounding boxes for all visibility clusters in the map. Each bounding box is represented by its minimum and maximum corner coordinates.
Warning
In Lua, tables are indexed beginning at 1
, not 0
. Consequently, the bounding box for cluster ID exampleClusterID
will be located at index exampleClusterID + 1
in the table returned by this function.
Note
Visibility clusters in the Source engine are convex shapes, which means they are not all axis-aligned boxes as the existence of this function may suggest. Consequently, the returned bounding boxes can and will overlap each other when clusters assume more complicated forms.
Tip
If you are attempting to determine which cluster a particular point in the world belongs to, a better alternative would be to use GetClusterForOrigin, which is not only more efficient but also accounts for irregular cluster shapes as aforementioned.
Name | Type | Description |
---|---|---|
boundsList |
table |
A table of bounding boxes. Each bounding box is a table with the following structure:
|
Finds and returns the ID of the area containing the specified location.
Note
Areas are completely separate collections of leaves, either set in stone by brushwork or created dynamically by closed areaportals (the latter of which PVS alone cannot account for).
Name | Type | Description |
---|---|---|
origin |
Vector |
The position whose area we want the ID of. |
Name | Type | Description |
---|---|---|
area |
number |
The ID of the area if it was found; -1 if it was not. |
Determines whether area1
flows into area2
and vice versa. Result depends on areaportal state.
Note
Areaportals will close of their own accord depending on the position of the player. Area testing is therefore not always a good idea!
Name | Type | Description |
---|---|---|
origin |
Vector |
The position whose area we want the ID of. |
Name | Type | Description |
---|---|---|
result |
number |
true if area1 flows into area2 and vice versa (when the function was called). |
A userdata
type representing a Potentially Visible Set (PVS) in the context of map visibility computations. Comes packaged with several methods for working with its associated visibility data.
Metamethod | Description | Syntax |
---|---|---|
__index | When passed number values, acts as an alias of PVS:ContainsCluster , returning a boolean |
pvs[147] |
__len | Returns the number of clusters visible in the PVS in question | #pvs |
__tostring | Returns a string in the format of "[PVS] X/Y clusters visible" |
tostring(pvs) |
PVS
objects come complete with several arithmetic operator overloads for performing a number of basic bitwise operations on the byte buffers of said objects.
Metamethod | Description | Bitwise | Syntax |
---|---|---|---|
__add | Returns a PVS with all the clusters from both of the two PVS objects provided |
A | B |
A + B |
__sub | Returns a copy of A with all clusters shared with B omitted |
A & ~B |
A - B |
__mul | Returns a PVS containing only clusters A and B have in common |
A & B |
A * B |
__div | Returns a PVS containing every cluster in the map except those A and B have in common |
~(A & B) |
A / B |
__unm | Returns an inversion of the PVS provided, containing any clusters the former didn't and not containing any it did |
~A |
-A |
Determines whether a given point exists within the PVS.
Name | Type | Description |
---|---|---|
origin |
Vector |
The position in the map to evaluate. |
Name | Type | Description |
---|---|---|
result |
boolean |
true if the position is within the PVS. |
Determines whether the given box is within the PVS at any point.
Name | Type | Description |
---|---|---|
mins |
Vector |
The minimum corner of the box to evaluate. |
maxs |
Vector |
The maximum corner of the box to evaluate. |
Name | Type | Description |
---|---|---|
result |
boolean |
true if the given box is within the PVS at any point. |
Determines whether a particular cluster exists within the PVS.
Name | Type | Description |
---|---|---|
cluster |
number |
The ID of the cluster to search for. |
Name | Type | Description |
---|---|---|
result |
boolean |
true if the given cluster exists within the PVS. |
Note
In practice, this function should always return the same result as GetClusterCount.
The PVS objects in this module record the total number of clusters in the map when they are created on an individual basis. Realistically, this should never affect anything, but was implemented in this manner "just in case."
Name | Type | Description |
---|---|---|
total |
number |
The total number of clusters accounted for by the PVS object's internal byte buffer (visibility notwithstanding). |
Shows colored boxes for a specified duration indicating the bounding boxes of each cluster visible with the PVS in question.
Important
In order to see anything, you must:
- Set
developer
to2
in the game console - Be the host of a listen server or singleplayer game
Tip
Use transparent colors. A color alpha of 255
will produce completely opaque boxes, which are hardly conducive to an effective visual display. Try starting out with 40
.
Name | Type | Description |
---|---|---|
color |
Color |
The color the boxes should be drawn with. |
duration |
number |
The length of time (in seconds) that the overlay should persist before it disappears. |