--[[ | 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