mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
371 lines
11 KiB
Lua
371 lines
11 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/
|
|
--]]
|
|
|
|
|
|
--[[
|
|
Terrain control. Changes the ground
|
|
|
|
Terrain.Create( sName ) Creates a new terrain type and stores it
|
|
Terrain.Get( sName ) Returns the terrain.
|
|
Terrain.Set( sName ) Sets the terrain. (This should only be done serverside)
|
|
Terrain.GetCurrent() Returns the terrain obj or nil.
|
|
StormFox2.Terrain.Reset() Resets the terrain to default.
|
|
StormFox2.Terrain.HasMaterialChanged( iMaterial ) Returns true if the terrain has changed the material.
|
|
|
|
Terrain Meta:
|
|
:LockUntil( fFunc ) Makes the terrian
|
|
:MakeFootprints( sndList, sndName ) Makes footprints. Allows to overwrite footstep sounds.
|
|
:AddTextureSwap( material, basetexture, basetextire2 ) Changes a materials textures.
|
|
:RenderWindow( width, height ) A function that renders a window-texure. (Weather will trump this)
|
|
:RenderWindowRefract( width, height ) A function that renders a window-texure. (Weather will trump this)
|
|
:RenderWindow64x64( width, height ) A function that renders a window-texure. (Weather will trump this)
|
|
:RenderWindowRefract64x64( width, height ) A function that renders a window-texure. (Weather will trump this)
|
|
:Apply Applies the terrain (This won't reset old terrain)
|
|
|
|
Hooks:
|
|
StormFox2.terrain.footstep Entity foot[0 = left,1 = right] sTexture bTerrainTexture
|
|
]]
|
|
|
|
---@class SF2Terrain
|
|
local meta = {}
|
|
meta.__index = meta
|
|
meta.__tostring = function(self) return "SF_TerrainType[" .. (self.Name or "Unknwon") .. "]" end
|
|
meta.__eq = function(self, other)
|
|
if type(other) ~= "table" then return false end
|
|
if not other.Name then return false end
|
|
return other.Name == self.Name
|
|
end
|
|
debug.getregistry()["SFTerrain"] = meta
|
|
local terrains = {}
|
|
StormFox2.Terrain = {}
|
|
|
|
--- Creates a new terrain type, stores and returns it.
|
|
---@param sName string
|
|
---@return SF2Terrain
|
|
---@shared
|
|
function StormFox2.Terrain.Create( sName )
|
|
local t = {}
|
|
t.Name = sName
|
|
setmetatable(t, meta)
|
|
terrains[sName] = t
|
|
t.swap = {}
|
|
return t
|
|
end
|
|
|
|
local CURRENT_TERRAIN
|
|
---Returns the current applies terrain.
|
|
---@return SF2Terrain|nil
|
|
---@shared
|
|
function StormFox2.Terrain.GetCurrent()
|
|
return CURRENT_TERRAIN
|
|
end
|
|
|
|
---Returns a terrain by name.
|
|
---@param sName string
|
|
---@return SF2Terrain|nil
|
|
---@shared
|
|
function StormFox2.Terrain.Get( sName )
|
|
if not sName then return end
|
|
return terrains[sName]
|
|
end
|
|
|
|
-- Makes the terrain stay until this function returns true or another terrain overwrites.
|
|
---@param fFunc function
|
|
---@shared
|
|
function meta:LockUntil( fFunc )
|
|
self.lock = fFunc
|
|
end
|
|
|
|
---Sets the ground texture. e.i; snow texture.
|
|
---@param iTexture string
|
|
---@param bOnlyGround boolean
|
|
---@shared
|
|
function meta:SetGroundTexture( iTexture, bOnlyGround )
|
|
self.ground = iTexture
|
|
self.only_ground = bOnlyGround
|
|
end
|
|
|
|
-- Adds a texture swap for when this terrain gets applied.
|
|
---@param mMaterial Material|string
|
|
---@param basetexture string
|
|
---@param basetextire2 string
|
|
---@shared
|
|
function meta:AddTextureSwap( mMaterial, basetexture, basetextire2 )
|
|
if type(mMaterial) ~= "IMaterial" then
|
|
mMaterial = Material(mMaterial)
|
|
end
|
|
if not basetexture and not basetextire2 then return end
|
|
self.swap[mMaterial] = { basetexture, basetextire2 }
|
|
end
|
|
|
|
---Makes footprints and allows to overwrite default footstep sounds.
|
|
---@param bool boolean
|
|
---@param sndList? table
|
|
---@param sndName? string
|
|
---@param OnPrint? function
|
|
---@shared
|
|
function meta:MakeFootprints( bool, sndList, sndName, OnPrint )
|
|
self.footprints = bool
|
|
if sndList or sndName then
|
|
self.footprintSnds = {sndList, sndName}
|
|
end
|
|
self.footstepFunc = OnPrint
|
|
self.footstepLisen = bool or sndList or sndName or OnPrint
|
|
end
|
|
|
|
---A function that renders a window-texure. (Weather will trump this)
|
|
---@param fFunc function
|
|
---@shared
|
|
function meta:RenderWindow( fFunc )
|
|
self.windRender = fFunc
|
|
end
|
|
|
|
---A function that renders a window-texure. (Weather will trump this)
|
|
---@param fFunc function
|
|
---@shared
|
|
function meta:RenderWindowRefract( fFunc )
|
|
self.windRenderRef = fFunc
|
|
end
|
|
|
|
---A function that renders a window-texure. (Weather will trump this)
|
|
---@param fFunc function
|
|
---@shared
|
|
function meta:RenderWindow64x64( fFunc )
|
|
self.windRender64 = fFunc
|
|
end
|
|
|
|
---A function that renders a window-texure. (Weather will trump this)
|
|
---@param fFunc function
|
|
---@shared
|
|
function meta:RenderWindowRefract64x64( fFunc )
|
|
self.windRenderRef64 = fFunc
|
|
end
|
|
|
|
-- Texture handler
|
|
_STORMFOX_TEXCHANGES = _STORMFOX_TEXCHANGES or {} -- List of changed materials.
|
|
_STORMFOX_TEXORIGINAL = _STORMFOX_TEXORIGINAL or {} -- This is global, just in case.
|
|
local footStepLisen = false -- If set to true, will enable footprints.
|
|
|
|
local function StringTex(iTex)
|
|
if not iTex then return end
|
|
if type(iTex) == "string" then return iTex end
|
|
return iTex:GetName()
|
|
end
|
|
|
|
local function HasChanged( self, materialTexture )
|
|
local mat = self:GetName() or "unknown"
|
|
local b = materialTexture == "$basetexture2" and 2 or 1
|
|
return _STORMFOX_TEXCHANGES[mat] and _STORMFOX_TEXCHANGES[mat][b] or false
|
|
end
|
|
|
|
---Returns true if the material has changed.
|
|
---@param iMaterial Material
|
|
---@return boolean
|
|
---@shared
|
|
function StormFox2.Terrain.HasMaterialChanged( iMaterial )
|
|
local mat = iMaterial:GetName() or iMaterial
|
|
return _STORMFOX_TEXCHANGES[mat] and true or false
|
|
end
|
|
|
|
---Returns the original texture for said material.
|
|
---@param iMaterial Material
|
|
---@return stirng
|
|
---@shared
|
|
function StormFox2.Terrain.GetOriginalTexture( iMaterial )
|
|
local mat = iMaterial:GetName() or iMaterial
|
|
return _STORMFOX_TEXORIGINAL[mat] and _STORMFOX_TEXORIGINAL[mat][1]
|
|
end
|
|
|
|
-- We're going to overwrite SetTexture. As some mods might change the default texture.
|
|
local mat_meta = FindMetaTable("IMaterial")
|
|
STORMFOX_TEX_APPLY = STORMFOX_TEX_APPLY or mat_meta.SetTexture
|
|
function mat_meta:SetTexture(materialTexture, texture)
|
|
-- Check if it is basetexutre or basetexture2 we're changing.
|
|
if materialTexture ~= "$basetexture" and materialTexture ~= "$basetexture2" then
|
|
return STORMFOX_TEX_APPLY( self, materialTexture, texture )
|
|
end
|
|
-- Overwrite the original texture list.
|
|
local mat = self:GetName() or "unknown"
|
|
if not _STORMFOX_TEXORIGINAL[mat] then _STORMFOX_TEXORIGINAL[mat] = {} end
|
|
if materialTexture == "$basetexture" then
|
|
_STORMFOX_TEXORIGINAL[mat][1] = StringTex(texture)
|
|
else
|
|
_STORMFOX_TEXORIGINAL[mat][2] = StringTex(texture)
|
|
end
|
|
-- If we havn't changed the texture, allow change.
|
|
if not HasChanged(self, materialTexture) then
|
|
return STORMFOX_TEX_APPLY( self, materialTexture, texture )
|
|
end
|
|
end
|
|
|
|
-- Resets the material. Returns false if unable to reset.
|
|
local function ResetMaterial( self )
|
|
local mat = self:GetName() or "unknown"
|
|
if not _STORMFOX_TEXCHANGES[mat] or not _STORMFOX_TEXORIGINAL[mat] then return false end
|
|
if _STORMFOX_TEXCHANGES[mat][1] and _STORMFOX_TEXORIGINAL[mat][1] then
|
|
STORMFOX_TEX_APPLY( self, "$basetexture", _STORMFOX_TEXORIGINAL[mat][1] )
|
|
end
|
|
if _STORMFOX_TEXCHANGES[mat][2] and _STORMFOX_TEXORIGINAL[mat][2] then
|
|
STORMFOX_TEX_APPLY( self, "$basetexture2", _STORMFOX_TEXORIGINAL[mat][2] )
|
|
end
|
|
_STORMFOX_TEXCHANGES[mat] = nil
|
|
return true
|
|
end
|
|
|
|
-- Set the material
|
|
local function SetMat(self, tex1, tex2)
|
|
if not tex1 and not tex2 then return end
|
|
local mat = self:GetName() or "unknown"
|
|
-- Save the default texture
|
|
if not _STORMFOX_TEXORIGINAL[mat] then _STORMFOX_TEXORIGINAL[mat] = {} end
|
|
if tex1 and not _STORMFOX_TEXORIGINAL[mat][1] then
|
|
_STORMFOX_TEXORIGINAL[mat][1] = StringTex(self:GetTexture("$basetexture"))
|
|
end
|
|
if tex2 and not _STORMFOX_TEXORIGINAL[mat][2] then
|
|
_STORMFOX_TEXORIGINAL[mat][2] = StringTex(self:GetTexture("$basetexture2"))
|
|
end
|
|
-- Set texture
|
|
if tex1 then
|
|
if CLIENT then
|
|
STORMFOX_TEX_APPLY( self, "$basetexture", tex1 )
|
|
end
|
|
if not _STORMFOX_TEXCHANGES[ mat ] then _STORMFOX_TEXCHANGES[ mat ] = {} end
|
|
_STORMFOX_TEXCHANGES[ mat ][ 1 ] = true
|
|
end
|
|
if tex2 then
|
|
if CLIENT then
|
|
STORMFOX_TEX_APPLY( self, "$basetexture2", tex2 )
|
|
end
|
|
if not _STORMFOX_TEXCHANGES[ mat ] then _STORMFOX_TEXCHANGES[ mat ] = {} end
|
|
_STORMFOX_TEXCHANGES[ mat ][ 2 ] = true
|
|
end
|
|
end
|
|
|
|
-- Resets the terrain to default. Setting bNoUpdate to true on the server, will not notify the clients or relays.
|
|
---@param bNoUpdate boolean
|
|
---@shared
|
|
function StormFox2.Terrain.Reset( bNoUpdate )
|
|
--print("Reset")
|
|
if SERVER and not bNoUpdate then
|
|
StormFox2.Map.CallLogicRelay("terrain_clear")
|
|
end
|
|
CURRENT_TERRAIN = nil
|
|
if SERVER and not bNoUpdate then
|
|
net.Start(StormFox2.Net.Terrain)
|
|
net.WriteString( "" )
|
|
net.Broadcast()
|
|
end
|
|
if next(_STORMFOX_TEXCHANGES) == nil then return end
|
|
for tex,_ in pairs( _STORMFOX_TEXCHANGES ) do
|
|
local mat = Material( tex )
|
|
if not ResetMaterial( mat ) then
|
|
StormFox2.Warning( "Can't reset [" .. tostring( mat ) .. "]." )
|
|
end
|
|
end
|
|
_STORMFOX_TEXCHANGES = {}
|
|
end
|
|
|
|
--- Sets the terrain. (This should only be done serverside)
|
|
---@param sName string
|
|
---@return boolean
|
|
---@shared
|
|
function StormFox2.Terrain.Set( sName )
|
|
-- Apply terrain.
|
|
local t = StormFox2.Terrain.Get( sName )
|
|
if not t then
|
|
StormFox2.Terrain.Reset()
|
|
return false
|
|
end
|
|
StormFox2.Terrain.Reset( true )
|
|
t:Apply()
|
|
if SERVER then
|
|
StormFox2.Map.CallLogicRelay( "terrain_" .. string.lower(sName) )
|
|
end
|
|
return true
|
|
end
|
|
|
|
--- Reapplies the current terrain
|
|
---@shared
|
|
function StormFox2.Terrain.Update()
|
|
local terrain = StormFox2.Terrain.GetCurrent()
|
|
if not terrain then return end
|
|
StormFox2.Terrain.Reset( true )
|
|
terrain:Apply()
|
|
end
|
|
|
|
local NO_TYPE = -1
|
|
local DIRTGRASS_TYPE = 0
|
|
local ROOF_TYPE = 1
|
|
local ROAD_TYPE = 2
|
|
local PAVEMENT_TYPE = 3
|
|
|
|
local function checkType(n, bOnlkyG)
|
|
if not n then return false end
|
|
if n == 0 then return true end
|
|
if n == 1 and not bOnlkyG then return true end
|
|
return false
|
|
end
|
|
|
|
-- Applies the terrain (This won't reset old terrain)
|
|
function meta:Apply()
|
|
CURRENT_TERRAIN = self
|
|
if SERVER then
|
|
net.Start(StormFox2.Net.Terrain)
|
|
net.WriteString( CURRENT_TERRAIN.Name )
|
|
net.Broadcast()
|
|
end
|
|
-- Swap materials
|
|
if self.swap then
|
|
for mat,tab in pairs( self.swap ) do
|
|
SetMat( mat, tab[1], tab[2] )
|
|
end
|
|
end
|
|
-- Set ground
|
|
if self.ground then
|
|
for materialName,tab in pairs( StormFox2.Map.GetTextureTree() ) do
|
|
local mat = Material( materialName )
|
|
local a,b = checkType(tab[1], self.only_ground), checkType(tab[2], self.only_ground)
|
|
SetMat( mat, a and self.ground,b and self.ground)
|
|
end
|
|
end
|
|
footStepLisen = self.footprints or self.footprintSnds
|
|
end
|
|
|
|
-- NET
|
|
if SERVER then
|
|
net.Receive(StormFox2.Net.Terrain, function(len, ply) -- OI, what terrain?
|
|
net.Start(StormFox2.Net.Terrain)
|
|
net.WriteString( CURRENT_TERRAIN and CURRENT_TERRAIN.Name or "" )
|
|
net.Send(ply)
|
|
end)
|
|
else
|
|
net.Receive(StormFox2.Net.Terrain, function(len)
|
|
local sName = net.ReadString()
|
|
local b = StormFox2.Terrain.Set( sName )
|
|
--"Terrain Recived: ", sName, b)
|
|
|
|
end)
|
|
-- Ask the server
|
|
hook.Add("StormFox2.InitPostEntity", "StormFox2.terrain.init", function()
|
|
timer.Simple(1, function()
|
|
net.Start(StormFox2.Net.Terrain)
|
|
net.WriteBit(1)
|
|
net.SendToServer()
|
|
end)
|
|
end)
|
|
end
|
|
|
|
-- A bit ballsy, but lets try.
|
|
hook.Add("ShutDown","StormFox2.Terrain.Clear",function()
|
|
StormFox2.Msg("Reloading all changed materials ..")
|
|
for k, _ in pairs( _STORMFOX_TEXORIGINAL ) do
|
|
RunConsoleCommand("mat_reloadmaterial", k)
|
|
end
|
|
end) |