Files
wnsrc/lua/niknaks/modules/sh_bsp_brushes.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

158 lines
4.0 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
-- Copyright © 2022-2072, Nak, https://steamcommunity.com/id/Nak2/
-- All Rights Reserved. Not allowed to be reuploaded.
-- License: https://github.com/Nak2/NikNaks/blob/main/LICENSE
local obj_tostring = "BSP %s [ %s ]"
local format = string.format
--- @class BSPObject
local meta = NikNaks.__metatables["BSP"]
--- @class BrushObject
local meta_brush = {}
meta_brush.__index = meta_brush
meta_brush.__tostring = function( self ) return format( obj_tostring, "BSP Brush", self.__id ) end
meta_brush.MetaName = "BSP Brush"
NikNaks.__metatables["BSP Brush"] = meta_brush
local DIST_EPSILON = 0.03125
local MAX_MAP_BRUSHES = 8192
local MAX_MAP_BRUSHSIDES = 65536
--- Returns an array of the brush-data with brush-sides.
--- @return BrushObject[]
function meta:GetBrushes()
if self._brushes then return self._brushes end
self._brushes = {}
local data = self:GetLump( 18 )
for id = 1, math.min( data:Size() / 96, MAX_MAP_BRUSHES ) do
--- @class BrushObject
local t = {}
local first = data:ReadLong()
local num = data:ReadLong()
t.contents = data:ReadLong()
t.numsides = num
--- @type BrushSideObject[]
t.sides = {}
t.__id = id
t.__map = self
local n = 1
for i = first, first + num - 1 do
t.sides[n] = self:GetBrushSides()[i]
n = n + 1
end
self._brushes[id] = setmetatable( t, meta_brush )
end
self:ClearLump( 18 )
return self._brushes
end
--- Returns an array of brushside-data.
--- @return BrushSideObject[]
function meta:GetBrushSides()
if self._brushside then return self._brushside end
self._brushside = {}
local data = self:GetLump( 19 )
local planes = self:GetPlanes()
for i = 1, math.min( data:Size() / 64, MAX_MAP_BRUSHSIDES ) do
--- @class BrushSideObject
local t = {}
t.plane = planes[ data:ReadUShort() ]
t.texinfo = data:ReadShort()
t.dispinfo = data:ReadShort()
local q = data:ReadShort()
t.bevel = bit.band( q, 0x1 ) == 1 -- Seems to be 1 if used for collision detection
t.thin = bit.rshift( q, 8 ) == 1 -- For Portal 2 / Alien Swarm
self._brushside[i - 1] = t
end
self:ClearLump( 19 )
return self._brushside
end
function meta_brush:GetIndex()
return self.__id or -1
end
--- Returns the content flag the brush has.
--- @return number
function meta_brush:GetContents()
return self.contents
end
--- Returns true if the brush has said content
--- @param CONTENTS number
--- @return boolean
function meta_brush:HasContents( CONTENTS )
if CONTENTS == 0 then return self.contents == CONTENTS end
return bit.band( self.contents, CONTENTS ) ~= 0
end
-- Texture Stuff
--- Returns the TexInfo for the brush-side.
--- @param side number
--- @return table
function meta_brush:GetTexInfo( side )
return self.__map:GetTexInfo()[self.sides[side].texinfo]
end
--- Returns the TexData for the brush-side.
--- @param side number
--- @return table
function meta_brush:GetTexData( side )
return self.__map:GetTexData()[ self:GetTexInfo( side ).texdata]
end
--- Returns the texture for the brush-side.
--- @param side number
--- @return string
function meta_brush:GetTexture( side )
local t = self:GetTexData( side ) or {}
return t.nameStringTableID
end
--- Returns the Material for the brush-side.
--- @param side number
--- @return IMaterial
function meta_brush:GetMaterial( side )
if self._material and self._material[side] then return self._material[side] end
if not self._material then self._material = {} end
self._material[side] = Material( self:GetTexture( side ) or "__error" )
return self._material[side]
end
--- Returns true if the point is inside the brush
--- @param position Vector
--- @return boolean
function meta_brush:IsPointInside( position )
for i = 1, self.numsides do
local side = self.sides[i]
local plane = side.plane
if plane.normal:Dot( position ) - plane.dist > DIST_EPSILON then
return false
end
end
return true
end