Mapbase v5.1

- Fixed a major oversight in Source 2013 which was causing some code to think all logic entities were worldspawn
- Added WIP background nodraw for point_cameras set to not draw skybox at all
- Fixed map-specific talker not flushing on restore
- Added optional HUD hint to code-based game instructor hints
- Added workaround for suspicious crashes in HL2 NPC rappelling code (reported by 1upD)
- Made antlions summoned by npc_antlionguard report as dead when removed with the "Kill" input
- Fixed math_mod not saving mod value (reported by Klems)
- Added SDK_WindowImposter, which uses the SteamPipe cubemap bug workaround and includes support for parallax corrected cubemaps
- Updated thirdpartylegalnotices.txt to mention the Squirrel API
- Fixed incorrect type checking for script instances in VScript
- Added a bunch of new misc. VScript constants
- Added a few new base VScript functions
- Added a separate "Clientside Script Language" keyvalue to worldspawn for VScript, allowing client scripts to use a different language from server scripts
- Fixed worldspawn crashing the game when running entity scripts (reported by krassell)
- Fixed manifests creating a second worldspawn, allowing them to function properly in HL2
- Added tons of remapping-related fixes for instances and manifests, including node IDs and overlay remapping
- Added a keyvalue to func_instance which allows vector axis lines to be remapped properly
- Added support for manifest root path instances in VBSP
- Added missing PrintBrushContents() contents to VBSP
- Added -nohiddenmaps parameter
- Made manifest cordon somewhat functional
This commit is contained in:
Blixibon
2020-09-23 05:03:47 +00:00
parent 5c2051864a
commit add157197f
45 changed files with 1477 additions and 71 deletions

View File

@@ -594,6 +594,13 @@ void PrintBrushContentsToString( int contents, char *pOut, int nMaxChars )
ADD_CONTENTS(CONTENTS_BLOCKLOS)
ADD_CONTENTS(CONTENTS_OPAQUE)
ADD_CONTENTS(CONTENTS_TESTFOGVOLUME)
#ifdef MAPBASE
ADD_CONTENTS(CONTENTS_UNUSED)
ADD_CONTENTS(CONTENTS_UNUSED6)
ADD_CONTENTS(CONTENTS_TEAM1)
ADD_CONTENTS(CONTENTS_TEAM2)
ADD_CONTENTS(CONTENTS_IGNORE_NODRAW_OPAQUE)
#endif
ADD_CONTENTS(CONTENTS_MOVEABLE)
ADD_CONTENTS(CONTENTS_AREAPORTAL)
ADD_CONTENTS(CONTENTS_PLAYERCLIP)

View File

@@ -5,13 +5,31 @@
#include "manifest.h"
#include "windows.h"
#ifdef MAPBASE
entity_t *g_ManifestWorldSpawn = NULL;
extern char g_MainMapPath[ MAX_PATH ];
#endif
//-----------------------------------------------------------------------------
// Purpose: default constructor
//-----------------------------------------------------------------------------
CManifestMapPrefs::CManifestMapPrefs( void )
{
m_nInternalId = 0;
m_bIsVisible = true;
//m_bIsPrimary = false;
}
//-----------------------------------------------------------------------------
// Purpose: default constructor
//-----------------------------------------------------------------------------
CManifestMap::CManifestMap( void )
{
m_nInternalId = 0;
m_RelativeMapFileName[ 0 ] = 0;
m_bTopLevelMap = false;
m_bIsVisible = true;
}
@@ -35,7 +53,11 @@ CManifest::CManifest( void )
//-----------------------------------------------------------------------------
ChunkFileResult_t CManifest::LoadManifestMapKeyCallback( const char *szKey, const char *szValue, CManifestMap *pManifestMap )
{
if ( !stricmp( szKey, "Name" ) )
if ( !stricmp( szKey, "InternalID" ) )
{
pManifestMap->m_nInternalId = atoi( szValue );
}
else if ( !stricmp( szKey, "Name" ) )
{
// pManifestMap->m_FriendlyName = szValue;
}
@@ -260,6 +282,82 @@ ChunkFileResult_t CManifest::LoadManifestCordoningPrefsCallback( CChunkFile *pFi
return( eResult );
}
//-----------------------------------------------------------------------------
// Parses the preferences chunk that pertains to specific submaps in the map:
//
// Maps
// {
// VMF
// {
// "InternalID" "1"
// "IsPrimary" "1"
// }
// VMF
// {
// "InternalID" "2"
// }
// VMF
// {
// "InternalID" "3"
// "IsVisible" "0"
// }
// }
//
//-----------------------------------------------------------------------------
ChunkFileResult_t CManifest::LoadPrefsVmfKeyCallback( const char *szKey, const char *szValue, CManifestMapPrefs *pManifestMapPrefs )
{
if ( !stricmp( szKey, "InternalID" ) )
{
pManifestMapPrefs->m_nInternalId = atoi( szValue );
}
else if ( !stricmp( szKey, "IsVisible" ) )
{
pManifestMapPrefs->m_bIsVisible = ( atoi( szValue ) == 1 );
}
//else if ( !stricmp( szKey, "IsPrimary" ) )
//{
// pManifestMapPrefs->m_bIsPrimary = ( atoi( szValue ) == 1 );
//}
return ChunkFile_Ok;
}
//-----------------------------------------------------------------------------
// Parses preferences and applies them to their corresponding submaps
//-----------------------------------------------------------------------------
ChunkFileResult_t CManifest::LoadPrefsVmfCallback( CChunkFile *pFile, CManifest *pManifest )
{
CManifestMapPrefs prefs;
ChunkFileResult_t eResult = pFile->ReadChunk( (KeyHandler_t)LoadPrefsVmfKeyCallback, &prefs );
if (eResult == ChunkFile_Ok && prefs.m_nInternalId != 0)
{
for( int i = 0; i < pManifest->m_Maps.Count(); i++ )
{
if ( pManifest->m_Maps[ i ]->m_nInternalId == prefs.m_nInternalId )
{
pManifest->m_Maps[ i ]->m_bIsVisible = prefs.m_bIsVisible;
break;
}
}
}
return(eResult);
}
ChunkFileResult_t CManifest::LoadPrefsMapsCallback( CChunkFile *pFile, CManifest *pManifest )
{
CChunkHandlerMap Handlers;
Handlers.AddHandler( "VMF", ( ChunkHandler_t )CManifest::LoadPrefsVmfCallback, pManifest );
pFile->PushHandlers(&Handlers);
ChunkFileResult_t eResult = pFile->ReadChunk();
pFile->PopHandlers();
return( eResult );
}
//-----------------------------------------------------------------------------
// Purpose: this function will create a new entity pair
@@ -298,12 +396,20 @@ bool CManifest::LoadSubMaps( CMapFile *pMapFile, const char *pszFileName )
memset( InstanceEntity, 0, sizeof( *InstanceEntity ) );
InstanceEntity->origin.Init( 0.0f, 0.0f, 0.0f );
#ifdef MAPBASE
g_ManifestWorldSpawn = InstanceEntity;
#else
pEPair = CreateEPair( "classname", "worldspawn" );
pEPair->next = InstanceEntity->epairs;
InstanceEntity->epairs = pEPair;
#endif
for( int i = 0; i < m_Maps.Count(); i++ )
{
if ( g_bNoHiddenManifestMaps && !m_Maps[ i ]->m_bIsVisible )
continue;
// if ( m_Maps[ i ]->m_bTopLevelMap == false )
{
char FileName[ MAX_PATH ];
@@ -389,6 +495,9 @@ bool CManifest::LoadVMFManifestUserPrefs( const char *pszFileName )
CChunkHandlerMap Handlers;
Handlers.AddHandler( "cordoning", ( ChunkHandler_t )CManifest::LoadManifestCordoningPrefsCallback, this );
if (g_bNoHiddenManifestMaps)
Handlers.AddHandler( "Maps", ( ChunkHandler_t )CManifest::LoadPrefsMapsCallback, this );
// Handlers.SetErrorHandler( ( ChunkErrorHandler_t )CMapDoc::HandleLoadError, this);
File.PushHandlers(&Handlers);
@@ -460,11 +569,14 @@ bool CManifest::LoadVMFManifest( const char *pszFileName )
if ( g_MainMap == NULL )
{
g_MainMap = g_LoadingMap;
#ifdef MAPBASE
V_ExtractFilePath( pszFileName, g_MainMapPath, sizeof( g_MainMapPath ) );
#endif
}
LoadSubMaps( g_LoadingMap, pszFileName );
LoadVMFManifestUserPrefs( pszFileName );
LoadSubMaps( g_LoadingMap, pszFileName );
}
return ( eResult == ChunkFile_Ok );

View File

@@ -32,8 +32,19 @@ class CManifestMap
{
public:
CManifestMap( void );
int m_nInternalId;
char m_RelativeMapFileName[ MAX_PATH ];
bool m_bTopLevelMap;
bool m_bIsVisible;
};
class CManifestMapPrefs
{
public:
CManifestMapPrefs( void );
int m_nInternalId;
bool m_bIsVisible;
//int m_bIsPrimary;
};
class CManifest
@@ -51,6 +62,9 @@ public:
static ChunkFileResult_t LoadCordonsKeyCallback( const char *pszKey, const char *pszValue, CManifest *pManifest );
static ChunkFileResult_t LoadCordonsCallback( CChunkFile *pFile, CManifest *pManifest );
static ChunkFileResult_t LoadManifestCordoningPrefsCallback( CChunkFile *pFile, CManifest *pManifest );
static ChunkFileResult_t LoadPrefsVmfKeyCallback( const char *szKey, const char *szValue, CManifestMapPrefs *pManifestMapPrefs );
static ChunkFileResult_t LoadPrefsVmfCallback( CChunkFile *pFile, CManifest *pManifest );
static ChunkFileResult_t LoadPrefsMapsCallback( CChunkFile *pFile, CManifest *pManifest );
bool LoadSubMaps( CMapFile *pMapFile, const char *pszFileName );
epair_t *CreateEPair( char *pKey, char *pValue );

View File

@@ -49,6 +49,12 @@ struct LoadSide_t
extern qboolean onlyents;
#ifdef MAPBASE
extern entity_t *g_ManifestWorldSpawn;
char g_MainMapPath[ MAX_PATH ];
#endif
CUtlVector< CMapFile * > g_Maps;
CMapFile *g_MainMap = NULL;
@@ -2116,7 +2122,11 @@ void CMapFile::CheckForInstances( const char *pszFileName )
char InstancePath[ MAX_PATH ];
bool bLoaded = false;
#ifdef MAPBASE
if ( DeterminePath( pszFileName, pInstanceFile, InstancePath ) || DeterminePath( g_MainMapPath, pInstanceFile, InstancePath ) )
#else
if ( DeterminePath( pszFileName, pInstanceFile, InstancePath ) )
#endif
{
if ( LoadMapFile( InstancePath ) )
{
@@ -2425,6 +2435,11 @@ void CMapFile::MergeEntities( entity_t *pInstanceEntity, CMapFile *Instance, Vec
entity_t *WorldspawnEnt = NULL;
GameData::TNameFixup FixupStyle;
#ifdef MAPBASE
// For fixing AI node problems with manifests and instances
int max_ai_node_id = 0;
#endif
char *pTargetName = ValueForKey( pInstanceEntity, "targetname" );
char *pName = ValueForKey( pInstanceEntity, "name" );
if ( pTargetName[ 0 ] )
@@ -2451,6 +2466,20 @@ void CMapFile::MergeEntities( entity_t *pInstanceEntity, CMapFile *Instance, Vec
max_entity_id = value;
}
}
#ifdef MAPBASE
// If this is a classname starting with "info_node", look for a node ID keyvalue and
// add it to the counter.
if ( strnicmp( ValueForKey( &entities[ i ], "classname" ), "info_node", 9 ) == 0 )
{
int value = atoi( ValueForKey( &entities[i], "nodeid" ) );
if ( value > max_ai_node_id )
{
max_ai_node_id = value;
//Warning( "Max AI nodes is now %i", max_ai_node_id );
}
}
#endif
}
FixupStyle = ( GameData::TNameFixup )( IntForKey( pInstanceEntity, "fixup_style" ) );
@@ -2495,6 +2524,11 @@ void CMapFile::MergeEntities( entity_t *pInstanceEntity, CMapFile *Instance, Vec
GDclass *EntClass = GD.BeginInstanceRemap( pEntity, NameFixup, InstanceOrigin, InstanceAngle );
if ( EntClass )
{
#ifdef MAPBASE
// Sets up for additional instance remap fixes from Mapbase
GD.SetupInstanceRemapParams( max_ai_node_id, nummapbrushsides - Instance->nummapbrushsides, IntForKey( pInstanceEntity, "remap_vecline" ) > 0 );
#endif
for( int i = 0; i < EntClass->GetVariableCount(); i++ )
{
GDinputvariable *EntVar = EntClass->GetVariableAt( i );
@@ -2590,8 +2624,11 @@ void CMapFile::MergeEntities( entity_t *pInstanceEntity, CMapFile *Instance, Vec
WorldspawnEnt->numbrushes = 0;
#ifdef MAPBASE
char *pIsTopLevel = ValueForKey( pInstanceEntity, "toplevel" );
if ( strcmp( pIsTopLevel, "1" ) )
WorldspawnEnt->epairs = NULL;
if ( strcmp( pIsTopLevel, "1" ) == 0 )
{
g_ManifestWorldSpawn->epairs = WorldspawnEnt->epairs;
}
WorldspawnEnt->epairs = NULL;
#else
WorldspawnEnt->epairs = NULL;
#endif
@@ -2613,10 +2650,27 @@ void CMapFile::MergeOverlays( entity_t *pInstanceEntity, CMapFile *Instance, Vec
for( int i = Instance->m_StartMapOverlays; i < g_aMapOverlays.Count(); i++ )
{
Overlay_Translate( &g_aMapOverlays[ i ], InstanceOrigin, InstanceAngle, InstanceMatrix );
#ifdef MAPBASE
int iSides = (nummapbrushsides - Instance->nummapbrushsides);
for (int i2 = 0; i2 < g_aMapOverlays[i].aSideList.Count(); i2++)
{
//Warning( "Remapping overlay side %i to %i\n", g_aMapOverlays[i].aSideList[i2], g_aMapOverlays[i].aSideList[i2] + iSides );
g_aMapOverlays[i].aSideList[i2] += iSides;
}
#endif
}
for( int i = Instance->m_StartMapWaterOverlays; i < g_aMapWaterOverlays.Count(); i++ )
{
Overlay_Translate( &g_aMapWaterOverlays[ i ], InstanceOrigin, InstanceAngle, InstanceMatrix );
#ifdef MAPBASE
int iSides = (nummapbrushsides - Instance->nummapbrushsides);
for (int i2 = 0; i2 < g_aMapWaterOverlays[i].aSideList.Count(); i2++)
{
g_aMapWaterOverlays[i].aSideList[i2] += iSides;
}
#endif
}
}
@@ -2671,6 +2725,9 @@ bool LoadMapFile( const char *pszFileName )
if ( g_MainMap == NULL )
{
g_MainMap = g_LoadingMap;
#ifdef MAPBASE
V_ExtractFilePath( pszFileName, g_MainMapPath, sizeof( g_MainMapPath ) );
#endif
}
if ( g_MainMap == g_LoadingMap || verbose )
@@ -2707,40 +2764,6 @@ bool LoadMapFile( const char *pszFileName )
}
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
// Fill out parallax obb matrix array
// "i" is static so this code could account for
// multiple LoadMapFile() calls from instances, etc.
for (static int i = 0; i < g_nCubemapSamples; i++)
{
if (g_pParallaxObbStrs[i][0] != '\0')
{
entity_t* obbEnt = EntityByName(g_pParallaxObbStrs[i]);
if (obbEnt)
{
g_pParallaxObbStrs[i] = ValueForKey(obbEnt, "transformationmatrix");
}
else
{
Warning( "Cannot find parallax obb \"%s\"\n", g_pParallaxObbStrs[i] );
g_pParallaxObbStrs[i][0] = '\0';
}
}
}
// Remove parallax_obb entities (in a nice slow linear search)
for (int i = 0; i < g_MainMap->num_entities; i++)
{
entity_t* mapent = &g_MainMap->entities[i];
const char *pClassName = ValueForKey( mapent, "classname" );
if ( !strcmp( "parallax_obb", pClassName ) )
{
mapent->numbrushes = 0;
mapent->epairs = NULL;
}
}
#endif
if ((eResult == ChunkFile_Ok) || (eResult == ChunkFile_EOF))
{
// Update the overlay/side list(s).
@@ -2754,6 +2777,51 @@ bool LoadMapFile( const char *pszFileName )
pMainManifest->CordonWorld();
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
// Fill out parallax obb matrix array
// "i" is static so this code could account for
// multiple LoadMapFile() calls from instances, etc.
for (static int i = 0; i < g_nCubemapSamples; i++)
{
if (g_pParallaxObbStrs[i][0] != '\0')
{
Warning( "Testing OBB string %s\n", g_pParallaxObbStrs[i] );
for (int i2 = 0; i2 < g_LoadingMap->num_entities; i2++)
{
entity_t* obbEnt = &g_LoadingMap->entities[i2];
if (stricmp( ValueForKey( obbEnt, "targetname" ), g_pParallaxObbStrs[i] ) != 0)
continue;
if (obbEnt)
{
g_pParallaxObbStrs[i] = ValueForKey(obbEnt, "transformationmatrix");
Warning( "Using OBB transformation matrix \"%s\"\n", g_pParallaxObbStrs[i] );
}
else
{
Warning( "Cannot find parallax obb \"%s\"\n", g_pParallaxObbStrs[i] );
g_pParallaxObbStrs[i][0] = '\0';
}
break;
}
}
}
// Remove parallax_obb entities (in a nice slow linear search)
for (int i = 0; i < g_LoadingMap->num_entities; i++)
{
entity_t* mapent = &g_LoadingMap->entities[i];
const char *pClassName = ValueForKey( mapent, "classname" );
if ( !strcmp( "parallax_obb", pClassName ) )
{
mapent->numbrushes = 0;
mapent->epairs = NULL;
}
}
#endif
ClearBounds (g_LoadingMap->map_mins, g_LoadingMap->map_maxs);
for (int i=0 ; i<g_MainMap->entities[0].numbrushes ; i++)
{

View File

@@ -60,6 +60,7 @@ bool g_NodrawTriggers = false;
bool g_DisableWaterLighting = false;
bool g_bAllowDetailCracks = false;
bool g_bNoVirtualMesh = false;
bool g_bNoHiddenManifestMaps = false;
#ifdef MAPBASE
bool g_bNoDefaultCubemaps = true;
bool g_bSkyboxCubemaps = false;
@@ -1157,6 +1158,10 @@ int RunVBSP( int argc, char **argv )
{
EnableFullMinidumps( true );
}
else if ( !Q_stricmp( argv[i], "-nohiddenmaps" ) )
{
g_bNoHiddenManifestMaps = true;
}
#ifdef MAPBASE
// Thanks to Mapbase's shader changes, default all-black cubemaps are no longer needed.
// The command has been switched from "-nodefaultcubemap" to "-defaultcubemap",
@@ -1264,6 +1269,7 @@ int RunVBSP( int argc, char **argv )
" -nox360 : Disable generation Xbox360 version of vsp (default)\n"
" -replacematerials : Substitute materials according to materialsub.txt in content\\maps\n"
" -FullMinidumps : Write large minidumps on crash.\n"
" -nohiddenmaps : Exclude manifest maps if they are currently hidden.\n"
);
}

View File

@@ -371,6 +371,7 @@ extern bool g_NodrawTriggers;
extern bool g_DisableWaterLighting;
extern bool g_bAllowDetailCracks;
extern bool g_bNoVirtualMesh;
extern bool g_bNoHiddenManifestMaps;
extern char outbase[32];
extern char source[1024];