diff --git a/CONTRIBUTING b/CONTRIBUTING index c855b06908..508dc5e2b1 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -25,8 +25,10 @@ All contributions must follow the following rules: * All content in a contribution must be either already legally open-source or done with the full permission of the contribution's original creator(s). + * Contributions must not break existing maps/content or interfere with them in a negative or non-objective way. + * Code contributions are not obliged to follow Mapbase's preprocessor conventions (e.g. #ifdef MAPBASE), - although it is acceptable. + although following them is acceptable. * If you are contributing a file you created yourself specifically for Mapbase, you are required to use the custom "Mapbase - Source 2013" header used in other Mapbase files as of Mapbase v5.0. diff --git a/sp/src/fgdlib/gamedata.cpp b/sp/src/fgdlib/gamedata.cpp index f3689ee998..4138ab4ba3 100644 --- a/sp/src/fgdlib/gamedata.cpp +++ b/sp/src/fgdlib/gamedata.cpp @@ -12,6 +12,9 @@ #include "filesystem_tools.h" #include "tier1/strtools.h" #include "utlmap.h" +#ifdef MAPBASE +#include "fmtstr.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -579,6 +582,34 @@ GDclass *GameData::BeginInstanceRemap( const char *pszClassName, const char *psz return m_InstanceClass; } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: Sets up for additional instance remap fixes from Mapbase +//----------------------------------------------------------------------------- +void GameData::SetupInstanceRemapParams( int iStartNodes, int iStartBrushSide, bool bRemapVecLines ) +{ + // Set the numer of nodes in the level + m_InstanceStartAINodes = iStartNodes; + + // If we have a "nodeid" key, set it to ivNodeDest so it's properly recognized + // during AI node remapping + GDinputvariable *var = m_InstanceClass->VarForName( "nodeid" ); + if ( var ) + { + var->ForceSetType( ivNodeDest ); + } + + //--------------------------------------------- + + // Set the number of brush sides in the level + m_InstanceStartSide = iStartBrushSide; + + //--------------------------------------------- + + m_bRemapVecLines = bRemapVecLines; +} +#endif + enum tRemapOperation { @@ -586,6 +617,13 @@ enum tRemapOperation REMAP_POSITION, REMAP_ANGLE, REMAP_ANGLE_NEGATIVE_PITCH, +#ifdef MAPBASE + // Remaps the node ID for instance/manifest AI node support + REMAP_NODE_ID, + + // Remaps brush sides and sidelists + REMAP_SIDES, +#endif }; @@ -624,6 +662,12 @@ bool GameData::RemapKeyValue( const char *pszKey, const char *pszInValue, char * RemapOperation.Insert( ivOrigin, REMAP_POSITION ); RemapOperation.Insert( ivAxis, REMAP_ANGLE ); RemapOperation.Insert( ivAngleNegativePitch, REMAP_ANGLE_NEGATIVE_PITCH ); +#ifdef MAPBASE + RemapOperation.Insert( ivNodeDest, REMAP_NODE_ID ); + RemapOperation.Insert( ivSide, REMAP_SIDES ); + RemapOperation.Insert( ivSideList, REMAP_SIDES ); + RemapOperation.Insert( ivVecLine, REMAP_POSITION ); +#endif } if ( !m_InstanceClass ) @@ -657,6 +701,12 @@ bool GameData::RemapKeyValue( const char *pszKey, const char *pszInValue, char * case REMAP_POSITION: { +#ifdef MAPBASE + // Only remap ivVecLine if the keyvalue is enabled + if (KVType == ivVecLine && !m_bRemapVecLines) + break; +#endif + Vector inPoint( 0.0f, 0.0f, 0.0f ), outPoint; sscanf ( pszInValue, "%f %f %f", &inPoint.x, &inPoint.y, &inPoint.z ); @@ -697,6 +747,54 @@ bool GameData::RemapKeyValue( const char *pszKey, const char *pszInValue, char * sprintf( pszOutValue, "%g", -outAngles.x ); // just the pitch } break; + +#ifdef MAPBASE + case REMAP_NODE_ID: + { + int value = atoi( pszInValue ); + if (value == -1) + break; + + //Warning( " %s %s: Remapped %i to %i", m_InstanceClass->GetName(), KVVar->GetName(), value, value + m_InstanceStartAINodes ); + + value += m_InstanceStartAINodes; + + sprintf( pszOutValue, "%i", value ); + } + break; + + case REMAP_SIDES: + { + CUtlStringList sideList; + V_SplitString( pszInValue, " ", sideList ); + + // Convert sides + CUtlStringList newSideList; + for (int i = 0; i < sideList.Count(); i++) + { + int iSide = atoi( sideList[i] ); + + //Warning( " %s %s: Remapped %i to %i", m_InstanceClass->GetName(), KVVar->GetName(), iSide, iSide + m_InstanceStartSide ); + + iSide += m_InstanceStartSide; + + newSideList.AddToTail( const_cast( CNumStr( iSide ).String() ) ); + } + + // Initial side + strcpy( pszOutValue, newSideList[0] ); + + // Start at 1 for subsequent sides + for (int i = 1; i < newSideList.Count(); i++) + { + // Any subsequent sides are spaced + sprintf( pszOutValue, "%s %s", pszOutValue, newSideList[i] ); + } + + //Warning("Old side list: \"%s\", new side list: \"%s\"\n", pszInValue, pszOutValue); + } + break; +#endif } return ( strcmpi( pszInValue, pszOutValue ) != 0 ); diff --git a/sp/src/game/client/c_baselesson.cpp b/sp/src/game/client/c_baselesson.cpp index a968ea83a9..8a2d961722 100644 --- a/sp/src/game/client/c_baselesson.cpp +++ b/sp/src/game/client/c_baselesson.cpp @@ -16,6 +16,9 @@ #include "vprof.h" #include "view.h" #include "vstdlib/ikeyvaluessystem.h" +#ifdef MAPBASE +#include "usermessages.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -442,6 +445,9 @@ void CIconLesson::Init() m_iFlags = LOCATOR_ICON_FX_NONE; #ifdef MAPBASE m_szCaptionColor = gameinstructor_default_captioncolor.GetString(); + + m_iIconTargetPos = ICON_TARGET_EYE_POSITION; + m_szHudHint = ""; #else m_szCaptionColor = "255,255,255";// Default to white #endif @@ -653,6 +659,17 @@ void CIconLesson::UpdateInactive() m_fCurrentDistance = pLocalPlayer->EyePosition().DistTo( pIconTarget->WorldSpaceCenter() ); } +#ifdef MAPBASE + if (m_szHudHint.String()[0] != '\0' && GetRoot()->IsLearned()) + { + DevMsg("Showing hint\n"); + CUtlBuffer msg_data; + msg_data.PutChar( 1 ); + msg_data.PutString( m_szHudHint.String() ); + usermessages->DispatchUserMessage( usermessages->LookupUserMessage( "KeyHintText" ), bf_read( msg_data.Base(), msg_data.TellPut() ) ); + } +#endif + m_fUpdateDistanceTime = gpGlobals->curtime + LESSON_DISTANCE_UPDATE_RATE; } } @@ -1014,6 +1031,7 @@ Vector CIconLesson::GetIconTargetPosition( C_BaseEntity *pIconTarget ) LESSON_VARIABLE_MACRO_STRING( START_SOUND, m_szStartSound, CGameInstructorSymbol ) \ \ LESSON_VARIABLE_MACRO( ICON_TARGET_POS, m_iIconTargetPos, int ) \ + LESSON_VARIABLE_MACRO_STRING( HUD_HINT_AFTER_LEARNED, m_szHudHint, CGameInstructorSymbol ) \ // Create keyvalues name symbol diff --git a/sp/src/game/client/c_baselesson.h b/sp/src/game/client/c_baselesson.h index d23ee2b7cd..2cad41ca88 100644 --- a/sp/src/game/client/c_baselesson.h +++ b/sp/src/game/client/c_baselesson.h @@ -275,6 +275,8 @@ class CIconLesson : public CTextLesson ICON_TARGET_ORIGIN, ICON_TARGET_CENTER, }; + + CGameInstructorSymbol m_szHudHint; #endif }; diff --git a/sp/src/game/client/c_world.cpp b/sp/src/game/client/c_world.cpp index dcec1f09ac..cf48d47cc6 100644 --- a/sp/src/game/client/c_world.cpp +++ b/sp/src/game/client/c_world.cpp @@ -63,7 +63,7 @@ BEGIN_RECV_TABLE( C_World, DT_World ) RecvPropString(RECVINFO(m_iszChapterTitle)), #endif #ifdef MAPBASE_VSCRIPT - RecvPropInt(RECVINFO(m_iScriptLanguage)), + RecvPropInt(RECVINFO(m_iScriptLanguageClient)), #endif END_RECV_TABLE() diff --git a/sp/src/game/client/c_world.h b/sp/src/game/client/c_world.h index aa1ce2269c..a0cc315c34 100644 --- a/sp/src/game/client/c_world.h +++ b/sp/src/game/client/c_world.h @@ -42,7 +42,7 @@ class C_World : public C_BaseEntity const char *GetDetailSpriteMaterial() const; #ifdef MAPBASE_VSCRIPT - ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)m_iScriptLanguage; } + ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)m_iScriptLanguageClient; } #endif public: @@ -64,7 +64,7 @@ class C_World : public C_BaseEntity char m_iszChapterTitle[64]; #endif #ifdef MAPBASE_VSCRIPT - int m_iScriptLanguage; + int m_iScriptLanguageClient; #endif private: diff --git a/sp/src/game/client/detailobjectsystem.cpp b/sp/src/game/client/detailobjectsystem.cpp index 75c860be1f..726e2cd72c 100644 --- a/sp/src/game/client/detailobjectsystem.cpp +++ b/sp/src/game/client/detailobjectsystem.cpp @@ -1624,12 +1624,14 @@ void CDetailObjectSystem::UnserializeModelDict( CUtlBuffer& buf ) DetailModelDict_t dict; dict.m_pModel = (model_t *)engine->LoadModel( lump.m_Name, true ); +#ifndef MAPBASE // Don't allow vertex-lit models if (modelinfo->IsModelVertexLit(dict.m_pModel)) { Warning("Detail prop model %s is using vertex-lit materials!\nIt must use unlit materials!\n", lump.m_Name ); dict.m_pModel = (model_t *)engine->LoadModel( "models/error.mdl" ); } +#endif m_DetailObjectDict.AddToTail( dict ); } diff --git a/sp/src/game/client/viewrender.cpp b/sp/src/game/client/viewrender.cpp index 045da85919..4ad77e8ca4 100644 --- a/sp/src/game/client/viewrender.cpp +++ b/sp/src/game/client/viewrender.cpp @@ -3349,11 +3349,11 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin // // Monitor sky handling // - if ( pCameraEnt->SkyMode() == SKYBOX_3DSKYBOX_VISIBLE ) + SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode(); + if ( nSkyMode == SKYBOX_3DSKYBOX_VISIBLE ) { int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR); bool bDrew3dSkybox = false; - SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode(); Frustum frustum; render->Push3DView( monitorView, nClearFlags, pRenderTarget, (VPlane *)frustum ); @@ -3369,13 +3369,32 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin ViewDrawScene( bDrew3dSkybox, nSkyMode, monitorView, nClearFlags, VIEW_MONITOR ); render->PopView( frustum ); } + else if (nSkyMode == SKYBOX_NOT_VISIBLE) + { + // @MULTICORE (toml 8/11/2006): this should be a renderer.... + Frustum frustum; + render->Push3DView( monitorView, VIEW_CLEAR_DEPTH, pRenderTarget, (VPlane *)frustum ); + + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->PushRenderTargetAndViewport( pRenderTarget ); + pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, 1 ); + if ( pRenderTarget ) + { + pRenderContext->OverrideAlphaWriteEnable( true, true ); + } + + ViewDrawScene( false, nSkyMode, monitorView, 0, VIEW_MONITOR ); + + pRenderContext->PopRenderTargetAndViewport(); + render->PopView( frustum ); + } else { // @MULTICORE (toml 8/11/2006): this should be a renderer.... Frustum frustum; - render->Push3DView( monitorView, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, (VPlane *)frustum ); - ViewDrawScene( false, SKYBOX_2DSKYBOX_VISIBLE, monitorView, 0, VIEW_MONITOR ); - render->PopView( frustum ); + render->Push3DView( monitorView, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, (VPlane *)frustum ); + ViewDrawScene( false, nSkyMode, monitorView, 0, VIEW_MONITOR ); + render->PopView( frustum ); } #else // @MULTICORE (toml 8/11/2006): this should be a renderer.... diff --git a/sp/src/game/client/vscript_client.cpp b/sp/src/game/client/vscript_client.cpp index f340ecd16c..d67491827b 100644 --- a/sp/src/game/client/vscript_client.cpp +++ b/sp/src/game/client/vscript_client.cpp @@ -466,6 +466,12 @@ bool VScriptClientInit() { scriptLanguage = SL_PYTHON; } +#ifdef MAPBASE_VSCRIPT + else if( !Q_stricmp(pszScriptLanguage, "lua") ) + { + scriptLanguage = SL_LUA; + } +#endif else { DevWarning("-scriptlang does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage ); diff --git a/sp/src/game/server/ai_basenpc.cpp b/sp/src/game/server/ai_basenpc.cpp index 88aeba5684..3cdf049112 100644 --- a/sp/src/game/server/ai_basenpc.cpp +++ b/sp/src/game/server/ai_basenpc.cpp @@ -812,6 +812,11 @@ HSCRIPT CAI_BaseNPC::VScriptGetExpresser() return hScript; } + +HSCRIPT CAI_BaseNPC::VScriptGetCine() +{ + return ToHScript(m_hCine.Get()); +} #endif bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info ) @@ -11989,6 +11994,11 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC DEFINE_SCRIPTFUNC_NAMED( VScriptFindEnemyMemory, "FindEnemyMemory", "Get information about the NPC's current enemy." ) + DEFINE_SCRIPTFUNC( GetLastAttackTime, "Get the last time the NPC has used an attack (e.g. fired a bullet from a gun)." ) + DEFINE_SCRIPTFUNC( GetLastDamageTime, "Get the last time the NPC has been damaged." ) + DEFINE_SCRIPTFUNC( GetLastPlayerDamageTime, "Get the last time the NPC has been damaged by a player." ) + DEFINE_SCRIPTFUNC( GetLastEnemyTime, "Get the last time the NPC has seen an enemy." ) + DEFINE_SCRIPTFUNC_NAMED( VScriptGetState, "GetNPCState", "Get the NPC's current state." ) DEFINE_SCRIPTFUNC_NAMED( VScriptGetHintGroup, "GetHintGroup", "Get the name of the NPC's hint group." ) @@ -12027,6 +12037,9 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC DEFINE_SCRIPTFUNC( IsCommandable, "Check if the NPC is commandable." ) DEFINE_SCRIPTFUNC( IsInPlayerSquad, "Check if the NPC is in the player's squad." ) + DEFINE_SCRIPTFUNC_NAMED( VScriptGetCine, "GetCine", "Get the NPC's currently running scripted sequence if it has one." ) + DEFINE_SCRIPTFUNC( GetScriptState, "Get the NPC's current scripted sequence state." ) + END_SCRIPTDESC(); #endif diff --git a/sp/src/game/server/ai_basenpc.h b/sp/src/game/server/ai_basenpc.h index 7604404eeb..0ce63e7c18 100644 --- a/sp/src/game/server/ai_basenpc.h +++ b/sp/src/game/server/ai_basenpc.h @@ -1245,6 +1245,9 @@ class CAI_BaseNPC : public CBaseCombatCharacter, void VScriptClearCondition( const char *szCondition ) { ClearCondition( GetConditionID( szCondition ) ); } HSCRIPT VScriptGetExpresser(); + + HSCRIPT VScriptGetCine(); + int GetScriptState() { return m_scriptState; } #endif //----------------------------------------------------- diff --git a/sp/src/game/server/ai_behavior_rappel.cpp b/sp/src/game/server/ai_behavior_rappel.cpp index afa99a86c9..a9a75e916e 100644 --- a/sp/src/game/server/ai_behavior_rappel.cpp +++ b/sp/src/game/server/ai_behavior_rappel.cpp @@ -303,7 +303,14 @@ void CAI_RappelBehavior::GatherConditions() if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) { // Shoot at the enemy so long as I'm six feet or more above them. +#ifdef MAPBASE + // There seems to be an underlying issue here. COND_CAN_RANGE_ATTACK1 should not be valid without an enemy, + // but crashes have been reported from GetEnemy() returning null in this code. + Assert( GetEnemy() ); + if( GetEnemy() && (GetAbsOrigin().z - GetEnemy()->GetAbsOrigin().z >= 36.0f) && GetOuter()->GetShotRegulator()->ShouldShoot() ) +#else if( (GetAbsOrigin().z - GetEnemy()->GetAbsOrigin().z >= 36.0f) && GetOuter()->GetShotRegulator()->ShouldShoot() ) +#endif { Activity activity = GetOuter()->TranslateActivity( ACT_GESTURE_RANGE_ATTACK1 ); Assert( activity != ACT_INVALID ); diff --git a/sp/src/game/server/baseentity.cpp b/sp/src/game/server/baseentity.cpp index 6a39e23cd4..ca69fbda06 100644 --- a/sp/src/game/server/baseentity.cpp +++ b/sp/src/game/server/baseentity.cpp @@ -2313,6 +2313,10 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" DEFINE_SCRIPTFUNC( SetEffects, "Set effect(s)" ) DEFINE_SCRIPTFUNC( IsEffectActive, "Check if an effect is active" ) + DEFINE_SCRIPTFUNC( GetFlags, "Get flags" ) + DEFINE_SCRIPTFUNC( AddFlag, "Add flag" ) + DEFINE_SCRIPTFUNC( RemoveFlag, "Remove flag" ) + DEFINE_SCRIPTFUNC( GetEFlags, "Get Eflags" ) DEFINE_SCRIPTFUNC( AddEFlags, "Add Eflags" ) DEFINE_SCRIPTFUNC( RemoveEFlags, "Remove Eflags" ) @@ -9675,6 +9679,13 @@ void CBaseEntity::RunVScripts() return; } +#ifdef MAPBASE_VSCRIPT + if (g_pScriptVM == NULL) + { + return; + } +#endif + ValidateScriptScope(); // All functions we want to have call chained instead of overwritten @@ -9750,6 +9761,13 @@ void CBaseEntity::RunPrecacheScripts(void) return; } +#ifdef MAPBASE_VSCRIPT + if (g_pScriptVM == NULL) + { + return; + } +#endif + HSCRIPT hScriptPrecache = m_ScriptScope.LookupFunction("DispatchPrecache"); if (hScriptPrecache) { @@ -9765,6 +9783,13 @@ void CBaseEntity::RunOnPostSpawnScripts(void) return; } +#ifdef MAPBASE_VSCRIPT + if (g_pScriptVM == NULL) + { + return; + } +#endif + HSCRIPT hFuncConnect = g_pScriptVM->LookupFunction("ConnectOutputs"); if (hFuncConnect) { diff --git a/sp/src/game/server/baseentity.h b/sp/src/game/server/baseentity.h index cd40dc64c2..e5aca7e322 100644 --- a/sp/src/game/server/baseentity.h +++ b/sp/src/game/server/baseentity.h @@ -85,6 +85,7 @@ typedef struct KeyValueData_s KeyValueData; class CUserCmd; class CSkyCamera; class CEntityMapData; +class CWorld; class INextBot; @@ -1059,7 +1060,7 @@ class CBaseEntity : public IServerEntity virtual INextBot *MyNextBotPointer( void ) { return NULL; } virtual float GetDelay( void ) { return 0; } virtual bool IsMoving( void ); - bool IsWorld() { return entindex() == 0; } + bool IsWorld() const { extern CWorld *g_WorldEntity; return (void *)this == (void *)g_WorldEntity; } // Ported from the Alien Swarm SDK to fix false IsWorld() positives on server-only entities virtual char const *DamageDecal( int bitsDamageType, int gameMaterial ); virtual void DecalTrace( trace_t *pTrace, char const *decalName ); virtual void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName = NULL ); diff --git a/sp/src/game/server/client.cpp b/sp/src/game/server/client.cpp index 2da256868d..087d023f42 100644 --- a/sp/src/game/server/client.cpp +++ b/sp/src/game/server/client.cpp @@ -338,6 +338,16 @@ void ClientPrecache( void ) CBaseEntity::PrecacheScriptSound( "Bounce.Shell" ); CBaseEntity::PrecacheScriptSound( "Bounce.Concrete" ); +#ifdef MAPBASE + // Game Instructor sounds + CBaseEntity::PrecacheScriptSound( "Instructor.LessonStart" ); + CBaseEntity::PrecacheScriptSound( "Instructor.ImportantLessonStart" ); + + // TODO: Does sv_pure cover this? This is from the ASW SDK to prevent people from making simple scripted wall hacks + //engine->ForceExactFile( "scripts/instructor_lessons.txt" ); + //engine->ForceExactFile( "scripts/mod_lessons.txt" ); +#endif + ClientGamePrecache(); } diff --git a/sp/src/game/server/hl2/npc_antlionguard.cpp b/sp/src/game/server/hl2/npc_antlionguard.cpp index 9c6dfa3099..efc5883df2 100644 --- a/sp/src/game/server/hl2/npc_antlionguard.cpp +++ b/sp/src/game/server/hl2/npc_antlionguard.cpp @@ -3253,6 +3253,9 @@ void CNPC_AntlionGuard::SummonAntlions( void ) // Make the antlion fire my input when he dies pAntlion->KeyValue( "OnDeath", UTIL_VarArgs("%s,SummonedAntlionDied,,0,-1", STRING(GetEntityName())) ); +#ifdef MAPBASE + pAntlion->KeyValue( "OnKilled", UTIL_VarArgs("%s,SummonedAntlionDied,,0,-1", STRING(GetEntityName())) ); +#endif // Start the antlion burrowed, and tell him to come up pAntlion->m_bStartBurrowed = true; diff --git a/sp/src/game/server/logicentities.cpp b/sp/src/game/server/logicentities.cpp index 98c2e4bcc2..2197baffa4 100644 --- a/sp/src/game/server/logicentities.cpp +++ b/sp/src/game/server/logicentities.cpp @@ -5641,6 +5641,8 @@ BEGIN_DATADESC( CMathMod ) DEFINE_KEYFIELD( m_Operator, FIELD_INTEGER, "SetOperator" ), + DEFINE_VARIANT( m_Mod ), + // Inputs DEFINE_INPUTFUNC( FIELD_INPUT, "SetMod", InputSetMod ), DEFINE_INPUTFUNC( FIELD_STRING, "SetOperator", InputSetOperator ), diff --git a/sp/src/game/server/physics_prop_ragdoll.cpp b/sp/src/game/server/physics_prop_ragdoll.cpp index f91a0e899e..0844f7b798 100644 --- a/sp/src/game/server/physics_prop_ragdoll.cpp +++ b/sp/src/game/server/physics_prop_ragdoll.cpp @@ -162,7 +162,7 @@ END_DATADESC() #ifdef MAPBASE_VSCRIPT BEGIN_ENT_SCRIPTDESC( CRagdollProp, CBaseAnimating, "Ragdoll physics prop." ) - DEFINE_SCRIPTFUNC( GetSourceClassName, "Gets the ragdoll's source classname." ) + DEFINE_SCRIPTFUNC_NAMED( GetSourceClassNameAsCStr, "GetSourceClassName", "Gets the ragdoll's source classname." ) DEFINE_SCRIPTFUNC( SetSourceClassName, "Sets the ragdoll's source classname." ) DEFINE_SCRIPTFUNC( HasPhysgunInteraction, "Checks if the ragdoll has the specified interaction." ) diff --git a/sp/src/game/server/physics_prop_ragdoll.h b/sp/src/game/server/physics_prop_ragdoll.h index 0a2a14b053..46e527c320 100644 --- a/sp/src/game/server/physics_prop_ragdoll.h +++ b/sp/src/game/server/physics_prop_ragdoll.h @@ -63,7 +63,7 @@ class CRagdollProp : public CBaseAnimating, public CDefaultPlayerPickupVPhysics virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); void SetSourceClassName( const char *pClassname ); #ifdef MAPBASE - const char *GetSourceClassName() { return STRING( m_strSourceClassName ); } + const char *GetSourceClassNameAsCStr() { return STRING( m_strSourceClassName ); } #endif // Physics attacker diff --git a/sp/src/game/server/vscript_server.cpp b/sp/src/game/server/vscript_server.cpp index 8d01f67879..f5e2805fd1 100644 --- a/sp/src/game/server/vscript_server.cpp +++ b/sp/src/game/server/vscript_server.cpp @@ -1064,6 +1064,12 @@ bool VScriptServerInit() VScriptRunScript( "mapspawn", false ); +#ifdef MAPBASE_VSCRIPT + // Since the world entity spawns before VScript is initted, RunVScripts() is called before the VM has started, so no scripts are run. + // This gets around that by calling the same function right after the VM is initted. + GetWorldEntity()->RunVScripts(); +#endif + VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" ); return true; diff --git a/sp/src/game/server/world.cpp b/sp/src/game/server/world.cpp index 5f68a3d719..628a79bb1c 100644 --- a/sp/src/game/server/world.cpp +++ b/sp/src/game/server/world.cpp @@ -395,6 +395,7 @@ BEGIN_DATADESC( CWorld ) DEFINE_KEYFIELD( m_iszDetailSpriteMaterial, FIELD_STRING, "detailmaterial" ), #ifdef MAPBASE_VSCRIPT DEFINE_KEYFIELD( m_iScriptLanguage, FIELD_INTEGER, "vscriptlanguage" ), + DEFINE_KEYFIELD( m_iScriptLanguageClient, FIELD_INTEGER, "vscriptlanguage_client" ), #endif DEFINE_KEYFIELD( m_bColdWorld, FIELD_BOOLEAN, "coldworld" ), @@ -421,7 +422,7 @@ IMPLEMENT_SERVERCLASS_ST(CWorld, DT_WORLD) SendPropStringT (SENDINFO(m_iszChapterTitle) ), #endif #ifdef MAPBASE_VSCRIPT - SendPropInt (SENDINFO(m_iScriptLanguage), 4 ), // No SPROP_UNSIGNED to allow -1 (disabled) + SendPropInt (SENDINFO(m_iScriptLanguageClient), 4 ), // No SPROP_UNSIGNED to allow -1 (disabled) #endif END_SEND_TABLE() @@ -465,7 +466,7 @@ bool CWorld::KeyValue( const char *szKeyName, const char *szValue ) extern bool g_fGameOver; -static CWorld *g_WorldEntity = NULL; +CWorld *g_WorldEntity = NULL; CWorld* GetWorldEntity() { @@ -484,6 +485,7 @@ CWorld::CWorld( ) #ifdef MAPBASE_VSCRIPT m_iScriptLanguage = SL_NONE; + m_iScriptLanguageClient = -2; #endif m_bColdWorld = false; @@ -550,6 +552,14 @@ void CWorld::Spawn( void ) Precache( ); GlobalEntity_Add( "is_console", STRING(gpGlobals->mapname), ( IsConsole() ) ? GLOBAL_ON : GLOBAL_OFF ); GlobalEntity_Add( "is_pc", STRING(gpGlobals->mapname), ( !IsConsole() ) ? GLOBAL_ON : GLOBAL_OFF ); + +#ifdef MAPBASE_VSCRIPT + if (m_iScriptLanguageClient.Get() == -2) + { + // Clientside language should be regular language by default + m_iScriptLanguageClient.Set( m_iScriptLanguage ); + } +#endif } static const char *g_DefaultLightstyles[] = diff --git a/sp/src/game/server/world.h b/sp/src/game/server/world.h index 4fd82d2e4b..7e94945096 100644 --- a/sp/src/game/server/world.h +++ b/sp/src/game/server/world.h @@ -62,7 +62,7 @@ class CWorld : public CBaseEntity #endif #ifdef MAPBASE_VSCRIPT - ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)(m_iScriptLanguage.Get()); } + ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)(m_iScriptLanguage); } #endif private: @@ -89,7 +89,8 @@ class CWorld : public CBaseEntity CNetworkVar( string_t, m_iszDetailSpriteMaterial ); #ifdef MAPBASE_VSCRIPT - CNetworkVar( int, m_iScriptLanguage ); + int m_iScriptLanguage; + CNetworkVar( int, m_iScriptLanguageClient ); #endif // start flags diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index 583248b1a7..dc7ef81d0a 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -168,6 +168,18 @@ class CMapbaseSystem : public CAutoGameSystem return true; } + void RefreshCustomTalker() + { +#ifdef GAME_DLL + if (g_bMapContainsCustomTalker && mapbase_flush_talker.GetBool()) + { + DevMsg("Mapbase: Reloading response system to flush custom talker\n"); + ReloadResponseSystem(); + g_bMapContainsCustomTalker = false; + } +#endif + } + virtual void LevelInitPreEntity() { #ifdef GAME_DLL @@ -193,26 +205,17 @@ class CMapbaseSystem : public CAutoGameSystem } gameinfo->deleteThis(); - -#ifdef GAME_DLL - if (g_bMapContainsCustomTalker && mapbase_flush_talker.GetBool()) - { - DevMsg("Mapbase: Reloading response system to flush custom talker\n"); - ReloadResponseSystem(); - g_bMapContainsCustomTalker = false; - } - - g_MapName = STRING(gpGlobals->mapname); -#else - //char mapname[128]; - //Q_StripExtension(MapName(), mapname, sizeof(mapname)); - g_MapName = MapName(); -#endif + RefreshMapName(); // Shared Mapbase localization file g_pVGuiLocalize->AddFile( "resource/mapbase_%language%.txt" ); } + virtual void OnRestore() + { + RefreshMapName(); + } + virtual void LevelInitPostEntity() { // Check for a generic "mapname_manifest.txt" file and load it. @@ -242,6 +245,27 @@ class CMapbaseSystem : public CAutoGameSystem virtual void LevelShutdownPostEntity() { g_MapName = NULL; + + RefreshCustomTalker(); + } + + bool RefreshMapName() + { +#ifdef GAME_DLL + const char *pszMapName = STRING(gpGlobals->mapname); +#else + //char mapname[128]; + //Q_StripExtension(MapName(), mapname, sizeof(mapname)); + const char *pszMapName = MapName(); +#endif + + if (g_MapName == NULL || !FStrEq(pszMapName, g_MapName)) + { + g_MapName = pszMapName; + return true; + } + + return false; } #ifdef CLIENT_DLL diff --git a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp index 6e225f3645..a1c99405a3 100644 --- a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp +++ b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp @@ -12,6 +12,7 @@ #include "c_ai_basenpc.h" #else #include "ai_basenpc.h" +#include "globalstate.h" #endif // memdbgon must be the last include file in a .cpp file!!! @@ -244,6 +245,41 @@ void RegisterSharedScriptConstants() ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC_ACTOR, "" ); ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC_SCRIPTED, "" ); + // + // Flags + // + ScriptRegisterConstant( g_pScriptVM, FL_ONGROUND, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_DUCKING, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_WATERJUMP, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_ONTRAIN, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_INRAIN, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_FROZEN, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_ATCONTROLS, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_CLIENT, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_FAKECLIENT, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_INWATER, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_FLY, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_SWIM, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_CONVEYOR, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_NPC, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_GODMODE, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_NOTARGET, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_AIMTARGET, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_PARTIALGROUND, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_STATICPROP, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_GRAPHED, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_GRENADE, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_STEPMOVEMENT, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_DONTTOUCH, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_BASEVELOCITY, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_WORLDBRUSH, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_OBJECT, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_KILLME, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_ONFIRE, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_DISSOLVING, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_TRANSRAGDOLL, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_UNBLOCKABLE_BY_PLAYER, "" ); + // // Entity Flags // @@ -416,5 +452,35 @@ void RegisterSharedScriptConstants() ScriptRegisterConstant( g_pScriptVM, bits_CAP_DOORS_GROUP, "" ); ScriptRegisterConstant( g_pScriptVM, bits_CAP_RANGE_ATTACK_GROUP, "" ); ScriptRegisterConstant( g_pScriptVM, bits_CAP_MELEE_ATTACK_GROUP, "" ); + + // + // Misc. AI + // + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_INVALID, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_NONE, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_IDLE, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_ALERT, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_COMBAT, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_SCRIPT, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_PLAYDEAD, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_PRONE, "When in clutches of barnacle" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_DEAD, "" ); + + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_PLAYING, "SCRIPT_PLAYING", "Playing the action animation." ); + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_WAIT, "SCRIPT_WAIT", "Waiting on everyone in the script to be ready. Plays the pre idle animation if there is one." ); + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_POST_IDLE, "SCRIPT_POST_IDLE", "Playing the post idle animation after playing the action animation." ); + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_CLEANUP, "SCRIPT_CLEANUP", "Cancelling the script / cleaning up." ); + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_WALK_TO_MARK, "SCRIPT_WALK_TO_MARK", "Walking to the scripted sequence position." ); + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_RUN_TO_MARK, "SCRIPT_RUN_TO_MARK", "Running to the scripted sequence position." ); + ScriptRegisterConstantNamed( g_pScriptVM, CAI_BaseNPC::SCRIPT_PLAYING, "SCRIPT_PLAYING", "Moving to the scripted sequence position while playing a custom movement animation." ); +#endif + + // + // Misc. General + // +#ifdef GAME_DLL + ScriptRegisterConstant( g_pScriptVM, GLOBAL_OFF, "" ); + ScriptRegisterConstant( g_pScriptVM, GLOBAL_ON, "" ); + ScriptRegisterConstant( g_pScriptVM, GLOBAL_DEAD, "" ); #endif } diff --git a/sp/src/materialsystem/stdshaders/SDK_windowimposter_ps2x.fxc b/sp/src/materialsystem/stdshaders/SDK_windowimposter_ps2x.fxc new file mode 100644 index 0000000000..fc3ea25a63 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/SDK_windowimposter_ps2x.fxc @@ -0,0 +1,64 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// STATIC: "PARALLAXCORRECT" "0..1" + +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +// SKIP: $PARALLAXCORRECT [ps20] + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler EnvmapSampler : register( s0 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +#if PARALLAXCORRECT +// Parallax cubemaps +const float3 cubemapPos : register(c0); +const float4x4 obbMatrix : register(c1); //through c4 +#endif + +struct PS_INPUT +{ + float3 eyeToVertVector : TEXCOORD0; + float4 vertexColor : COLOR; + +#if PARALLAXCORRECT + float3 worldSpaceNormal : TEXCOORD1; +#endif + + float4 worldPos_projPosZ : TEXCOORD2; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if PARALLAXCORRECT + float3 reflectVect = CalcReflectionVectorUnnormalized( i.worldSpaceNormal, g_EyePos_SpecExponent.xyz - i.worldPos_projPosZ.xyz ); //i.eyeToVertVector; //CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.eyeToVertVector ); + + //Parallax correction (2_0b and beyond) + //Adapted from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ + float3 worldPos = i.worldPos_projPosZ.xyz; + float3 positionLS = mul(float4(worldPos, 1), obbMatrix); + float3 rayLS = mul(reflectVect, (float3x3) obbMatrix); + + float3 firstPlaneIntersect = (float3(1.0f, 1.0f, 1.0f) - positionLS) / rayLS; + float3 secondPlaneIntersect = (-positionLS) / rayLS; + float3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect); + float distance = min(furthestPlane.x, min(furthestPlane.y, furthestPlane.z)); + + // Use distance in WS directly to recover intersection + float3 intersectPositionWS = worldPos + reflectVect * distance; + reflectVect = intersectPositionWS - cubemapPos; +#else + float3 reflectVect = i.eyeToVertVector; +#endif + + HALF4 color; + color.xyz = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + color.a = 1.0f; + color *= i.vertexColor; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, i.worldPos_projPosZ.xyz, i.worldPos_projPosZ.w ); + return FinalOutput( color, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/sp/src/materialsystem/stdshaders/SDK_windowimposter_vs20.fxc b/sp/src/materialsystem/stdshaders/SDK_windowimposter_vs20.fxc new file mode 100644 index 0000000000..f67676ee37 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/SDK_windowimposter_vs20.fxc @@ -0,0 +1,61 @@ +//========== Copyright (c) Valve Corporation, All rights reserved. ==========// +// +// Purpose: +// +//=========================================================================== +// STATIC: "PARALLAXCORRECT" "0..1" + +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float3 vPos : POSITION; +#if PARALLAXCORRECT + float4 vNormal : NORMAL; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + float fog : FOG; +#endif + float3 eyeToVertVector : TEXCOORD0; + float4 vertexColor : COLOR; + +#if PARALLAXCORRECT + float3 worldNormal : TEXCOORD1; +#endif + + float4 worldPos_projPosZ : TEXCOORD2; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + + float3 worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + o.worldPos_projPosZ = float4( worldPos.xyz, o.projPos.z ); + o.eyeToVertVector = worldPos - cEyePos; + +#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) + o.fog = CalcFixedFunctionFog( worldPos, g_FogType ); +#endif + +#if PARALLAXCORRECT + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + o.worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); +#endif + + o.vertexColor = cModulationColor; + return o; +} + diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_ps20.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_ps20.inc new file mode 100644 index 0000000000..7c34f6ee7c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_ps20.inc @@ -0,0 +1,87 @@ +#include "shaderlib/cshader.h" +class sdk_windowimposter_ps20_Static_Index +{ +private: + int m_nPARALLAXCORRECT; +#ifdef _DEBUG + bool m_bPARALLAXCORRECT; +#endif +public: + void SetPARALLAXCORRECT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXCORRECT = i; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } + void SetPARALLAXCORRECT( bool i ) + { + m_nPARALLAXCORRECT = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } +public: + sdk_windowimposter_ps20_Static_Index( ) + { +#ifdef _DEBUG + m_bPARALLAXCORRECT = false; +#endif // _DEBUG + m_nPARALLAXCORRECT = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bPARALLAXCORRECT; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 2 * m_nPARALLAXCORRECT ) + 0; + } +}; +#define shaderStaticTest_sdk_windowimposter_ps20 psh_forgot_to_set_static_PARALLAXCORRECT + 0 +class sdk_windowimposter_ps20_Dynamic_Index +{ +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +public: + sdk_windowimposter_ps20_Dynamic_Index() + { +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bPIXELFOGTYPE; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nPIXELFOGTYPE ) + 0; + } +}; +#define shaderDynamicTest_sdk_windowimposter_ps20 psh_forgot_to_set_dynamic_PIXELFOGTYPE + 0 diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_ps20b.inc new file mode 100644 index 0000000000..e94fc94da1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_ps20b.inc @@ -0,0 +1,87 @@ +#include "shaderlib/cshader.h" +class sdk_windowimposter_ps20b_Static_Index +{ +private: + int m_nPARALLAXCORRECT; +#ifdef _DEBUG + bool m_bPARALLAXCORRECT; +#endif +public: + void SetPARALLAXCORRECT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXCORRECT = i; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } + void SetPARALLAXCORRECT( bool i ) + { + m_nPARALLAXCORRECT = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } +public: + sdk_windowimposter_ps20b_Static_Index( ) + { +#ifdef _DEBUG + m_bPARALLAXCORRECT = false; +#endif // _DEBUG + m_nPARALLAXCORRECT = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bPARALLAXCORRECT; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 2 * m_nPARALLAXCORRECT ) + 0; + } +}; +#define shaderStaticTest_sdk_windowimposter_ps20b psh_forgot_to_set_static_PARALLAXCORRECT + 0 +class sdk_windowimposter_ps20b_Dynamic_Index +{ +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +public: + sdk_windowimposter_ps20b_Dynamic_Index() + { +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bPIXELFOGTYPE; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nPIXELFOGTYPE ) + 0; + } +}; +#define shaderDynamicTest_sdk_windowimposter_ps20b psh_forgot_to_set_dynamic_PIXELFOGTYPE + 0 diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_vs20.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_vs20.inc new file mode 100644 index 0000000000..faa096a23b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_windowimposter_vs20.inc @@ -0,0 +1,87 @@ +#include "shaderlib/cshader.h" +class sdk_windowimposter_vs20_Static_Index +{ +private: + int m_nPARALLAXCORRECT; +#ifdef _DEBUG + bool m_bPARALLAXCORRECT; +#endif +public: + void SetPARALLAXCORRECT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXCORRECT = i; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } + void SetPARALLAXCORRECT( bool i ) + { + m_nPARALLAXCORRECT = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } +public: + sdk_windowimposter_vs20_Static_Index( ) + { +#ifdef _DEBUG + m_bPARALLAXCORRECT = false; +#endif // _DEBUG + m_nPARALLAXCORRECT = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bPARALLAXCORRECT; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 2 * m_nPARALLAXCORRECT ) + 0; + } +}; +#define shaderStaticTest_sdk_windowimposter_vs20 vsh_forgot_to_set_static_PARALLAXCORRECT + 0 +class sdk_windowimposter_vs20_Dynamic_Index +{ +private: + int m_nDOWATERFOG; +#ifdef _DEBUG + bool m_bDOWATERFOG; +#endif +public: + void SetDOWATERFOG( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nDOWATERFOG = i; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } + void SetDOWATERFOG( bool i ) + { + m_nDOWATERFOG = i ? 1 : 0; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } +public: + sdk_windowimposter_vs20_Dynamic_Index() + { +#ifdef _DEBUG + m_bDOWATERFOG = false; +#endif // _DEBUG + m_nDOWATERFOG = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bDOWATERFOG; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nDOWATERFOG ) + 0; + } +}; +#define shaderDynamicTest_sdk_windowimposter_vs20 vsh_forgot_to_set_dynamic_DOWATERFOG + 0 diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_ps20.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_ps20.inc new file mode 100644 index 0000000000..7c34f6ee7c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_ps20.inc @@ -0,0 +1,87 @@ +#include "shaderlib/cshader.h" +class sdk_windowimposter_ps20_Static_Index +{ +private: + int m_nPARALLAXCORRECT; +#ifdef _DEBUG + bool m_bPARALLAXCORRECT; +#endif +public: + void SetPARALLAXCORRECT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXCORRECT = i; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } + void SetPARALLAXCORRECT( bool i ) + { + m_nPARALLAXCORRECT = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } +public: + sdk_windowimposter_ps20_Static_Index( ) + { +#ifdef _DEBUG + m_bPARALLAXCORRECT = false; +#endif // _DEBUG + m_nPARALLAXCORRECT = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bPARALLAXCORRECT; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 2 * m_nPARALLAXCORRECT ) + 0; + } +}; +#define shaderStaticTest_sdk_windowimposter_ps20 psh_forgot_to_set_static_PARALLAXCORRECT + 0 +class sdk_windowimposter_ps20_Dynamic_Index +{ +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +public: + sdk_windowimposter_ps20_Dynamic_Index() + { +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bPIXELFOGTYPE; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nPIXELFOGTYPE ) + 0; + } +}; +#define shaderDynamicTest_sdk_windowimposter_ps20 psh_forgot_to_set_dynamic_PIXELFOGTYPE + 0 diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_ps20b.inc new file mode 100644 index 0000000000..e94fc94da1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_ps20b.inc @@ -0,0 +1,87 @@ +#include "shaderlib/cshader.h" +class sdk_windowimposter_ps20b_Static_Index +{ +private: + int m_nPARALLAXCORRECT; +#ifdef _DEBUG + bool m_bPARALLAXCORRECT; +#endif +public: + void SetPARALLAXCORRECT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXCORRECT = i; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } + void SetPARALLAXCORRECT( bool i ) + { + m_nPARALLAXCORRECT = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } +public: + sdk_windowimposter_ps20b_Static_Index( ) + { +#ifdef _DEBUG + m_bPARALLAXCORRECT = false; +#endif // _DEBUG + m_nPARALLAXCORRECT = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bPARALLAXCORRECT; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 2 * m_nPARALLAXCORRECT ) + 0; + } +}; +#define shaderStaticTest_sdk_windowimposter_ps20b psh_forgot_to_set_static_PARALLAXCORRECT + 0 +class sdk_windowimposter_ps20b_Dynamic_Index +{ +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +public: + sdk_windowimposter_ps20b_Dynamic_Index() + { +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bPIXELFOGTYPE; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nPIXELFOGTYPE ) + 0; + } +}; +#define shaderDynamicTest_sdk_windowimposter_ps20b psh_forgot_to_set_dynamic_PIXELFOGTYPE + 0 diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_vs20.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_vs20.inc new file mode 100644 index 0000000000..faa096a23b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_windowimposter_vs20.inc @@ -0,0 +1,87 @@ +#include "shaderlib/cshader.h" +class sdk_windowimposter_vs20_Static_Index +{ +private: + int m_nPARALLAXCORRECT; +#ifdef _DEBUG + bool m_bPARALLAXCORRECT; +#endif +public: + void SetPARALLAXCORRECT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXCORRECT = i; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } + void SetPARALLAXCORRECT( bool i ) + { + m_nPARALLAXCORRECT = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXCORRECT = true; +#endif + } +public: + sdk_windowimposter_vs20_Static_Index( ) + { +#ifdef _DEBUG + m_bPARALLAXCORRECT = false; +#endif // _DEBUG + m_nPARALLAXCORRECT = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bPARALLAXCORRECT; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 2 * m_nPARALLAXCORRECT ) + 0; + } +}; +#define shaderStaticTest_sdk_windowimposter_vs20 vsh_forgot_to_set_static_PARALLAXCORRECT + 0 +class sdk_windowimposter_vs20_Dynamic_Index +{ +private: + int m_nDOWATERFOG; +#ifdef _DEBUG + bool m_bDOWATERFOG; +#endif +public: + void SetDOWATERFOG( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nDOWATERFOG = i; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } + void SetDOWATERFOG( bool i ) + { + m_nDOWATERFOG = i ? 1 : 0; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } +public: + sdk_windowimposter_vs20_Dynamic_Index() + { +#ifdef _DEBUG + m_bDOWATERFOG = false; +#endif // _DEBUG + m_nDOWATERFOG = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bDOWATERFOG; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nDOWATERFOG ) + 0; + } +}; +#define shaderDynamicTest_sdk_windowimposter_vs20 vsh_forgot_to_set_dynamic_DOWATERFOG + 0 diff --git a/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc b/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc index 364777490f..46193fba3a 100644 --- a/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc +++ b/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc @@ -60,6 +60,7 @@ $Project $File "unlittwotexture_dx9.cpp" $File "MonitorScreen_dx9.cpp" $File "shatteredglass.cpp" + $File "windowimposter_dx90.cpp" } //$Shaders "mapbase_dx9_20b.txt" diff --git a/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt b/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt index c6c4538f7d..1a805f2060 100644 --- a/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt +++ b/sp/src/materialsystem/stdshaders/stdshader_dx9_20b.txt @@ -93,3 +93,5 @@ SDK_unlittwotexture_vs20.fxc SDK_monitorscreen_ps2x.fxc SDK_ShatteredGlass_ps2x.fxc SDK_ShatteredGlass_vs20.fxc +SDK_windowimposter_ps2x.fxc +SDK_windowimposter_vs20.fxc diff --git a/sp/src/materialsystem/stdshaders/windowimposter_dx90.cpp b/sp/src/materialsystem/stdshaders/windowimposter_dx90.cpp new file mode 100644 index 0000000000..99ac791488 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/windowimposter_dx90.cpp @@ -0,0 +1,181 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +#include "sdk_windowimposter_vs20.inc" +#include "sdk_windowimposter_ps20.inc" +#include "sdk_windowimposter_ps20b.inc" + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( sdk_windowimposter, sdk_windowimposter_DX90 ) + +BEGIN_VS_SHADER( sdk_windowimposter_DX90, + "Help for WindowImposter_DX90" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + +#ifdef MAPBASE + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) +#endif + +#ifdef PARALLAX_CORRECTED_CUBEMAPS + // Parallax cubemaps + SHADER_PARAM( ENVMAPPARALLAX, SHADER_PARAM_TYPE_BOOL, "0", "Enables parallax correction code for env_cubemaps" ) + SHADER_PARAM( ENVMAPPARALLAXOBB1, SHADER_PARAM_TYPE_VEC4, "[1 0 0 0]", "The first line of the parallax correction OBB matrix" ) + SHADER_PARAM( ENVMAPPARALLAXOBB2, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "The second line of the parallax correction OBB matrix" ) + SHADER_PARAM( ENVMAPPARALLAXOBB3, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "The third line of the parallax correction OBB matrix" ) + SHADER_PARAM( ENVMAPORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "The world space position of the env_cubemap being corrected" ) +#endif + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { +#ifdef MAPBASE + if( !params[ENVMAPFRAME]->IsDefined() ) + params[ENVMAPFRAME]->SetIntValue( 0 ); +#endif + } + + SHADER_FALLBACK + { + return NULL; + } + + SHADER_INIT + { + LoadCubeMap( ENVMAP ); +#ifdef MAPBASE + if (mat_specular_disable_on_missing.GetBool()) + { + // Revert to defaultcubemap when the envmap texture is missing + // (should be equivalent to toolsblack in Mapbase) + if (params[ENVMAP]->GetTextureValue()->IsError()) + { + params[ENVMAP]->SetStringValue( "engine/defaultcubemap" ); + LoadCubeMap( ENVMAP ); + } + } +#endif + } + + SHADER_DRAW + { +#ifdef PARALLAX_CORRECTED_CUBEMAPS + // Parallax cubemaps + bool hasParallaxCorrection = params[ENVMAPPARALLAX]->GetIntValue() > 0; +#else + bool hasParallaxCorrection = false; +#endif + + SHADOW_STATE + { + if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + DECLARE_STATIC_VERTEX_SHADER( sdk_windowimposter_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( PARALLAXCORRECT, hasParallaxCorrection ); // Parallax cubemaps enabled for 2_0b and onwards + SET_STATIC_VERTEX_SHADER( sdk_windowimposter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sdk_windowimposter_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PARALLAXCORRECT, hasParallaxCorrection ); // Parallax cubemaps enabled for 2_0b and onwards + SET_STATIC_PIXEL_SHADER( sdk_windowimposter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sdk_windowimposter_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PARALLAXCORRECT, 0 ); // No parallax cubemaps with ps_2_0 :( + SET_STATIC_PIXEL_SHADER( sdk_windowimposter_ps20 ); + } + + unsigned int flags = VERTEX_POSITION; + int nTexCoordCount = 2; + + if (hasParallaxCorrection) + { + flags |= VERTEX_NORMAL; + nTexCoordCount++; + } + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, 0, 0 ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableDepthWrites( false ); + FogToFogColor(); + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( sdk_windowimposter_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER( sdk_windowimposter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sdk_windowimposter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sdk_windowimposter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sdk_windowimposter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sdk_windowimposter_ps20 ); + } + + SetModulationVertexShaderDynamicState(); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifdef PARALLAX_CORRECTED_CUBEMAPS + // Parallax cubemaps + if (hasParallaxCorrection) + { + pShaderAPI->SetPixelShaderConstant( 0, params[ENVMAPORIGIN]->GetVecValue() ); + + float* vecs[3]; + vecs[0] = const_cast(params[ENVMAPPARALLAXOBB1]->GetVecValue()); + vecs[1] = const_cast(params[ENVMAPPARALLAXOBB2]->GetVecValue()); + vecs[2] = const_cast(params[ENVMAPPARALLAXOBB3]->GetVecValue()); + float matrix[4][4]; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 4; j++) + { + matrix[i][j] = vecs[i][j]; + } + } + matrix[3][0] = matrix[3][1] = matrix[3][2] = 0; + matrix[3][3] = 1; + pShaderAPI->SetPixelShaderConstant( 1, &matrix[0][0], 4 ); + } +#endif + +#ifdef MAPBASE + BindTexture( SHADER_SAMPLER0, ENVMAP, ENVMAPFRAME ); +#else + BindTexture( SHADER_SAMPLER0, ENVMAP, -1 ); +#endif + } + Draw(); + } + +END_SHADER diff --git a/sp/src/public/fgdlib/gamedata.h b/sp/src/public/fgdlib/gamedata.h index cf8b5be12d..5d55db2f70 100644 --- a/sp/src/public/fgdlib/gamedata.h +++ b/sp/src/public/fgdlib/gamedata.h @@ -88,6 +88,11 @@ class GameData bool RemapNameField( const char *pszInValue, char *pszOutValue, TNameFixup NameFixup ); bool LoadFGDMaterialExclusions( TokenReader &tr ); bool LoadFGDAutoVisGroups( TokenReader &tr ); + +#ifdef MAPBASE + // Sets up for additional instance remap fixes from Mapbase + void SetupInstanceRemapParams( int iStartNodes, int iStartBrushSide, bool bRemapVecLines ); +#endif CUtlVector< FGDMatExlcusions_s > m_FGDMaterialExclusions; @@ -109,6 +114,11 @@ class GameData matrix3x4_t m_InstanceMat; // matrix of the origin and rotation of rendering char m_InstancePrefix[ 128 ]; // the prefix used for the instance name remapping GDclass *m_InstanceClass; // the entity class that is being remapped +#ifdef MAPBASE + int m_InstanceStartAINodes; // the number of AI nodes in the level (for AI node remapping) + int m_InstanceStartSide; // the number of brush sides in the level (for brush side remapping) + bool m_bRemapVecLines; // allows ivVecLine to be remapped +#endif }; diff --git a/sp/src/public/fgdlib/gdvar.h b/sp/src/public/fgdlib/gdvar.h index 197ff30def..e6eb37feb3 100644 --- a/sp/src/public/fgdlib/gdvar.h +++ b/sp/src/public/fgdlib/gdvar.h @@ -92,6 +92,14 @@ class GDinputvariable inline GDIV_TYPE GetType() { return m_eType; } const char *GetTypeText(void); + +#ifdef MAPBASE + // The FGD library normally enforces that variable types should always stay the same. + // The new AI node remapping code needs to change the "nodeid" keyvalue on AI nodes so + // it's properly recognized as a node ID which needs to be remapped. + // That's what this hack is for. + inline void ForceSetType( GDIV_TYPE newType ) { m_eType = newType; } +#endif inline void GetDefault(int *pnStore) { diff --git a/sp/src/utils/vbsp/csg.cpp b/sp/src/utils/vbsp/csg.cpp index 5de1d680ac..a8c39afbeb 100644 --- a/sp/src/utils/vbsp/csg.cpp +++ b/sp/src/utils/vbsp/csg.cpp @@ -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) diff --git a/sp/src/utils/vbsp/manifest.cpp b/sp/src/utils/vbsp/manifest.cpp index 5ac98ca992..4ba2952a7b 100644 --- a/sp/src/utils/vbsp/manifest.cpp +++ b/sp/src/utils/vbsp/manifest.cpp @@ -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 ); diff --git a/sp/src/utils/vbsp/manifest.h b/sp/src/utils/vbsp/manifest.h index e7b801e1b5..3d77211775 100644 --- a/sp/src/utils/vbsp/manifest.h +++ b/sp/src/utils/vbsp/manifest.h @@ -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 @@ class CManifest 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 ); diff --git a/sp/src/utils/vbsp/map.cpp b/sp/src/utils/vbsp/map.cpp index d04bd24437..4e73ebc78a 100644 --- a/sp/src/utils/vbsp/map.cpp +++ b/sp/src/utils/vbsp/map.cpp @@ -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 ; ientities[0].numbrushes ; i++) { diff --git a/sp/src/utils/vbsp/vbsp.cpp b/sp/src/utils/vbsp/vbsp.cpp index d9f8fb9178..7afde5e0a9 100644 --- a/sp/src/utils/vbsp/vbsp.cpp +++ b/sp/src/utils/vbsp/vbsp.cpp @@ -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" ); } diff --git a/sp/src/utils/vbsp/vbsp.h b/sp/src/utils/vbsp/vbsp.h index 12fd9db509..e9a056110c 100644 --- a/sp/src/utils/vbsp/vbsp.h +++ b/sp/src/utils/vbsp/vbsp.h @@ -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]; diff --git a/sp/src/vscript/vscript_squirrel.cpp b/sp/src/vscript/vscript_squirrel.cpp index 1c523c596f..6628a93e73 100644 --- a/sp/src/vscript/vscript_squirrel.cpp +++ b/sp/src/vscript/vscript_squirrel.cpp @@ -2469,7 +2469,7 @@ void* SquirrelVM::GetInstanceValue(HSCRIPT hInstance, ScriptClassDesc_t* pExpect sq_pushobject(vm_, *obj); - if (!sq_instanceof(vm_)) + if (sq_instanceof(vm_) != SQTrue) { sq_pop(vm_, 3); return nullptr; diff --git a/thirdpartylegalnotices.txt b/thirdpartylegalnotices.txt index 126ea8cec0..2c75083f05 100644 --- a/thirdpartylegalnotices.txt +++ b/thirdpartylegalnotices.txt @@ -868,3 +868,34 @@ Google Snappy // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +************************************************************************************ +************************************************************************************ + +Mapbase integrates a few additional third-party libraries, all of which are from free and/or +open-source projects operating under MIT or GNU licenses. They can be used in any mod or +commercial product as long as the given notices are present here or elsewhere. + +************************************************************************************ +Squirrel programming language (used in VScript) +************************************************************************************ + +Copyright (c) 2003-2017 Alberto Demichelis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.