diff --git a/README b/README index f9d61ee6..923f02bb 100644 --- a/README +++ b/README @@ -43,9 +43,12 @@ Mapbase is intended to be usable by everyone, including licensed Source projects The Alien Swarm SDK was used to backport features and code from newer branches of Source into a Source 2013/Half-Life 2 environment. Mapbase also implements some of Tony Sergi's code changes from the Source 2007 SDK codebase. Both SDKs are publicly distributed by Valve and are available on Steam. +Some of the features backported from the Alien Swarm SDK (e.g. game instructor, particle rain) require assets from later versions of Source in order to work properly. +The required assets have been backported from Alien Swarm and Left 4 Dead for the release build. They are not available in the code repository. + Here's a list of Mapbase's other known external code sources: -- https://github.com/95Navigator/insolence-2013 (Initial custom shader code and projected texture improvements) +- https://github.com/95Navigator/insolence-2013 (Initial custom shader code and projected texture improvements; also used to implement ASW SDK particle precipitation code) - https://github.com/Biohazard90/g-string_2013 (Custom shadow filters, included indirectly via Insolence repo) - https://github.com/KyleGospo/City-17-Episode-One-Source (Brush phong and projected texture changes, included indirectly via Insolence repo) - https://github.com/DownFall-Team/DownFall (Multiple skybox code and fix for ent_fire delay not using floats; Also used as a guide to port certain Alien Swarm SDK changes to Source 2013, @@ -87,11 +90,15 @@ Direct contributions: - https://github.com/mapbase-source/source-sdk-2013/pull/5 (Custom VScript implementation by ReDucTor; was placed into feature branch before being merged in a subsequent PR) - https://github.com/mapbase-source/source-sdk-2013/pull/3 ("playvideo" command playback fix from Avantate) - https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux fixes from z33ky) +- https://github.com/mapbase-source/source-sdk-2013/pull/47 (VScript utility/consistency changes from samisalreadytaken) +- https://github.com/mapbase-source/source-sdk-2013/pull/59 (New VScript functions and singletons from samisalreadytaken based on API documentation in later Source/Source 2 games) +- https://github.com/mapbase-source/source-sdk-2013/pull/60 (Adjustment by RoyaleNoir to one of Saul's VDC changes) - Demo autorecord code provided by Klems - cc_emit crash fix provided by 1upD - Custom HL2 ammo crate models created by Rara (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code) - Combine lock hardware on door01_left.mdl created by Kralich (This is asset-based and not reflected in the code) - npc_vehicledriver fixes provided by CrAzY +- npc_combine cover behavior patches provided by iohnnyboy //--------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/sp/src/game/client/c_baseentity.cpp b/sp/src/game/client/c_baseentity.cpp index fc5c9f6f..41a32a94 100644 --- a/sp/src/game/client/c_baseentity.cpp +++ b/sp/src/game/client/c_baseentity.cpp @@ -43,6 +43,9 @@ #ifdef MAPBASE #include "viewrender.h" #endif +#ifdef MAPBASE_VSCRIPT +#include "vscript_client.h" +#endif #include "gamestringpool.h" @@ -438,6 +441,9 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities DEFINE_SCRIPTFUNC_NAMED( ScriptGetUp, "GetUpVector", "Get the up vector of the entity" ) #ifdef MAPBASE_VSCRIPT + DEFINE_SCRIPTFUNC( ValidateScriptScope, "Ensure that an entity's script scope has been created" ) + DEFINE_SCRIPTFUNC( GetScriptScope, "Retrieve the script-side data associated with an entity" ) + DEFINE_SCRIPTFUNC( GetHealth, "" ) DEFINE_SCRIPTFUNC( GetMaxHealth, "" ) @@ -465,7 +471,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities DEFINE_SCRIPTFUNC( GetEffects, "Get effects" ) DEFINE_SCRIPTFUNC( IsEffectActive, "Check if an effect is active" ) - DEFINE_SCRIPTFUNC( entindex, "" ) + DEFINE_SCRIPTFUNC_NAMED( GetEntityIndex, "entindex", "" ) #endif END_SCRIPTDESC(); @@ -6519,6 +6525,138 @@ HSCRIPT C_BaseEntity::GetScriptInstance() } #ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// Using my edict, cook up a unique VScript scope that's private to me, and +// persistent. +//----------------------------------------------------------------------------- +bool C_BaseEntity::ValidateScriptScope() +{ + if (!m_ScriptScope.IsInitialized()) + { + if (scriptmanager == NULL) + { + ExecuteOnce(DevMsg("Cannot execute script because scripting is disabled (-scripting)\n")); + return false; + } + + if (g_pScriptVM == NULL) + { + ExecuteOnce(DevMsg(" Cannot execute script because there is no available VM\n")); + return false; + } + + // Force instance creation + GetScriptInstance(); + + EHANDLE hThis; + hThis.Set(this); + + bool bResult = m_ScriptScope.Init(STRING(m_iszScriptId)); + + if (!bResult) + { + DevMsg("%s couldn't create ScriptScope!\n", GetDebugName()); + return false; + } + g_pScriptVM->SetValue(m_ScriptScope, "self", GetScriptInstance()); + } + return true; +} + +//----------------------------------------------------------------------------- +// Returns true if the function was located and called. false otherwise. +// NOTE: Assumes the function takes no parameters at the moment. +//----------------------------------------------------------------------------- +bool C_BaseEntity::CallScriptFunction( const char* pFunctionName, ScriptVariant_t* pFunctionReturn ) +{ + if (!ValidateScriptScope()) + { + DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n"); + return false; + } + + + HSCRIPT hFunc = m_ScriptScope.LookupFunction(pFunctionName); + + if (hFunc) + { + m_ScriptScope.Call(hFunc, pFunctionReturn); + m_ScriptScope.ReleaseFunction(hFunc); + + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Gets a function handle +//----------------------------------------------------------------------------- +HSCRIPT C_BaseEntity::LookupScriptFunction( const char* pFunctionName ) +{ + if (!m_ScriptScope.IsInitialized()) + { + return NULL; + } + + return m_ScriptScope.LookupFunction(pFunctionName); +} + +//----------------------------------------------------------------------------- +// Calls and releases a function handle (ASSUMES SCRIPT SCOPE AND FUNCTION ARE VALID!) +//----------------------------------------------------------------------------- +bool C_BaseEntity::CallScriptFunctionHandle( HSCRIPT hFunc, ScriptVariant_t* pFunctionReturn ) +{ + m_ScriptScope.Call(hFunc, pFunctionReturn); + m_ScriptScope.ReleaseFunction(hFunc); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Load, compile, and run a script file from disk. +// Input : *pScriptFile - The filename of the script file. +// bUseRootScope - If true, runs this script in the root scope, not +// in this entity's private scope. +//----------------------------------------------------------------------------- +bool C_BaseEntity::RunScriptFile( const char* pScriptFile, bool bUseRootScope ) +{ + if (!ValidateScriptScope()) + { + DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n"); + return false; + } + + if (bUseRootScope) + { + return VScriptRunScript(pScriptFile); + } + else + { + return VScriptRunScript(pScriptFile, m_ScriptScope, true); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Compile and execute a discrete string of script source code +// Input : *pScriptText - A string containing script code to compile and run +//----------------------------------------------------------------------------- +bool C_BaseEntity::RunScript( const char* pScriptText, const char* pDebugFilename ) +{ + if (!ValidateScriptScope()) + { + DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n"); + return false; + } + + if (m_ScriptScope.Run(pScriptText, pDebugFilename) == SCRIPT_ERROR) + { + DevWarning(" Entity %s encountered an error in RunScript()\n", GetDebugName()); + } + + return true; +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- HSCRIPT C_BaseEntity::ScriptGetMoveParent( void ) diff --git a/sp/src/game/client/c_baseentity.h b/sp/src/game/client/c_baseentity.h index 8879c6f5..8cd7fec7 100644 --- a/sp/src/game/client/c_baseentity.h +++ b/sp/src/game/client/c_baseentity.h @@ -261,10 +261,27 @@ public: string_t m_iClassname; +#ifdef MAPBASE_VSCRIPT + // VSCRIPT + bool ValidateScriptScope(); + bool CallScriptFunction( const char* pFunctionName, ScriptVariant_t* pFunctionReturn ); + + HSCRIPT GetScriptScope() { return m_ScriptScope; } + + HSCRIPT LookupScriptFunction(const char* pFunctionName); + bool CallScriptFunctionHandle(HSCRIPT hFunc, ScriptVariant_t* pFunctionReturn); + + bool RunScriptFile( const char* pScriptFile, bool bUseRootScope = false ); + bool RunScript( const char* pScriptText, const char* pDebugFilename = "C_BaseEntity::RunScript" ); +#endif + HSCRIPT GetScriptInstance(); HSCRIPT m_hScriptInstance; string_t m_iszScriptId; +#ifdef MAPBASE_VSCRIPT + CScriptScope m_ScriptScope; +#endif // IClientUnknown overrides. public: @@ -366,6 +383,11 @@ public: bool IsMarkedForDeletion( void ); virtual int entindex( void ) const; + +#ifdef MAPBASE_VSCRIPT + // "I don't know why but wrapping entindex() works, while calling it directly crashes." + inline int C_BaseEntity::GetEntityIndex() const { return entindex(); } +#endif // This works for client-only entities and returns the GetEntryIndex() of the entity's handle, // so the sound system can get an IClientEntity from it. diff --git a/sp/src/game/client/c_effects.cpp b/sp/src/game/client/c_effects.cpp index 056c2b78..8035bfc4 100644 --- a/sp/src/game/client/c_effects.cpp +++ b/sp/src/game/client/c_effects.cpp @@ -6,6 +6,7 @@ // //=============================================================================// #include "cbase.h" +#include "c_effects.h" #include "c_tracer.h" #include "view.h" #include "initializer.h" @@ -22,6 +23,7 @@ #include "collisionutils.h" #include "tier0/vprof.h" #include "viewrender.h" +#include "raytrace.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -35,6 +37,12 @@ float g_flSplashLifetime = 0.5f; float g_flSplashAlpha = 0.3f; ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); // N% chance of a rain particle making a splash. +ConVar r_RainParticleDensity( "r_RainParticleDensity", "1", FCVAR_NONE, "Density of Particle Rain 0-1" ); + +#ifdef MAPBASE +ConVar r_RainParticleClampOffset( "r_RainParticleClampOffset", "112", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systemss" ); +ConVar r_RainParticleClampDebug( "r_RainParticleClampDebug", "0", FCVAR_NONE, "Enables debug code for precipitation particle system clamping" ); +#endif float GUST_INTERVAL_MIN = 1; float GUST_INTERVAL_MAX = 2; @@ -60,151 +68,14 @@ CLIENTEFFECT_MATERIAL( "particle/rain" ) CLIENTEFFECT_MATERIAL( "particle/snow" ) CLIENTEFFECT_REGISTER_END() -//----------------------------------------------------------------------------- -// Precipitation particle type -//----------------------------------------------------------------------------- - -class CPrecipitationParticle -{ -public: - Vector m_Pos; - Vector m_Velocity; - float m_SpawnTime; // Note: Tweak with this to change lifetime - float m_Mass; - float m_Ramp; - - float m_flCurLifetime; - float m_flMaxLifetime; -}; - - -class CClient_Precipitation; -static CUtlVector g_Precipitations; - -//=========== -// Snow fall -//=========== -class CSnowFallManager; -static CSnowFallManager *s_pSnowFallMgr = NULL; -bool SnowFallManagerCreate( CClient_Precipitation *pSnowEntity ); -void SnowFallManagerDestroy( void ); - -class AshDebrisEffect : public CSimpleEmitter -{ -public: - AshDebrisEffect( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {} - - static AshDebrisEffect* Create( const char *pDebugName ); - - virtual float UpdateAlpha( const SimpleParticle *pParticle ); - virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta ); - -private: - AshDebrisEffect( const AshDebrisEffect & ); -}; - -//----------------------------------------------------------------------------- -// Precipitation base entity -//----------------------------------------------------------------------------- - -class CClient_Precipitation : public C_BaseEntity -{ -class CPrecipitationEffect; -friend class CClient_Precipitation::CPrecipitationEffect; - -public: - DECLARE_CLASS( CClient_Precipitation, C_BaseEntity ); - DECLARE_CLIENTCLASS(); - - CClient_Precipitation(); - virtual ~CClient_Precipitation(); - - // Inherited from C_BaseEntity - virtual void Precache( ); - - void Render(); - -private: - - // Creates a single particle - CPrecipitationParticle* CreateParticle(); - - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual void ClientThink(); - - void Simulate( float dt ); - - // Renders the particle - void RenderParticle( CPrecipitationParticle* pParticle, CMeshBuilder &mb ); - - void CreateWaterSplashes(); - - // Emits the actual particles - void EmitParticles( float fTimeDelta ); - - // Computes where we're gonna emit - bool ComputeEmissionArea( Vector& origin, Vector2D& size ); - - // Gets the tracer width and speed - float GetWidth() const; - float GetLength() const; - float GetSpeed() const; - - // Gets the remaining lifetime of the particle - float GetRemainingLifetime( CPrecipitationParticle* pParticle ) const; - - // Computes the wind vector - static void ComputeWindVector( ); - - // simulation methods - bool SimulateRain( CPrecipitationParticle* pParticle, float dt ); - bool SimulateSnow( CPrecipitationParticle* pParticle, float dt ); - - void CreateAshParticle( void ); - void CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity ); - - // Information helpful in creating and rendering particles - IMaterial *m_MatHandle; // material used - - float m_Color[4]; // precip color - float m_Lifetime; // Precip lifetime - float m_InitialRamp; // Initial ramp value - float m_Speed; // Precip speed - float m_Width; // Tracer width - float m_Remainder; // particles we should render next time - PrecipitationType_t m_nPrecipType; // Precip type - float m_flHalfScreenWidth; // Precalculated each frame. - - float m_flDensity; - - // Some state used in rendering and simulation - // Used to modify the rain density and wind from the console - static ConVar s_raindensity; - static ConVar s_rainwidth; - static ConVar s_rainlength; - static ConVar s_rainspeed; - - static Vector s_WindVector; // Stores the wind speed vector - - CUtlLinkedList m_Particles; - CUtlVector m_Splashes; - - CSmartPtr m_pAshEmitter; - TimedEvent m_tAshParticleTimer; - TimedEvent m_tAshParticleTraceTimer; - bool m_bActiveAshEmitter; - Vector m_vAshSpawnOrigin; - - int m_iAshCount; - -private: - CClient_Precipitation( const CClient_Precipitation & ); // not defined, not accessible -}; - +CUtlVector< RayTracingEnvironment* > g_RayTraceEnvironments; // Just receive the normal data table stuff IMPLEMENT_CLIENTCLASS_DT(CClient_Precipitation, DT_Precipitation, CPrecipitation) - RecvPropInt( RECVINFO( m_nPrecipType ) ) + RecvPropInt( RECVINFO( m_nPrecipType ) ), +#ifdef MAPBASE + RecvPropInt( RECVINFO( m_spawnflags ) ), +#endif END_RECV_TABLE() static ConVar r_SnowEnable( "r_SnowEnable", "1", FCVAR_CHEAT, "Snow Enable" ); @@ -396,6 +267,12 @@ inline bool CClient_Precipitation::SimulateSnow( CPrecipitationParticle* pPartic void CClient_Precipitation::Simulate( float dt ) { + if ( IsParticleRainType(m_nPrecipType) ) + { + CreateParticlePrecip(); + return; + } + // NOTE: When client-side prechaching works, we need to remove this Precache(); @@ -472,6 +349,9 @@ inline void CClient_Precipitation::RenderParticle( CPrecipitationParticle* pPart float scale; Vector start, delta; + if ( IsParticleRainType(m_nPrecipType) ) + return; + if ( m_nPrecipType == PRECIPITATION_TYPE_ASH ) return; @@ -562,6 +442,9 @@ void CClient_Precipitation::Render() if ( !r_DrawRain.GetInt() ) return; + if ( IsParticleRainType(m_nPrecipType) ) + return; + // Don't render in monitors or in reflections or refractions. if ( CurrentViewID() == VIEW_MONITOR ) return; @@ -632,6 +515,11 @@ CClient_Precipitation::CClient_Precipitation() : m_Remainder(0.0f) m_nPrecipType = PRECIPITATION_TYPE_RAIN; m_MatHandle = INVALID_MATERIAL_HANDLE; m_flHalfScreenWidth = 1; + + m_pParticlePrecipInnerNear = NULL; + m_pParticlePrecipInnerFar = NULL; + m_pParticlePrecipOuter = NULL; + m_bActiveParticlePrecipEmitter = false; g_Precipitations.AddToTail( this ); } @@ -1011,6 +899,363 @@ void CClient_Precipitation::CreateAshParticle( void ) } } +void CClient_Precipitation::PrecacheParticlePrecip( void ) +{ + if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLEASH ) + { + PrecacheParticleSystem( "ash" ); + PrecacheParticleSystem( "ash_outer" ); + } + else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLESNOW ) + { + PrecacheParticleSystem( "snow" ); + PrecacheParticleSystem( "snow_outer" ); + } + else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLERAINSTORM ) + { + PrecacheParticleSystem( "rain_storm" ); + PrecacheParticleSystem( "rain_storm_screen" ); + PrecacheParticleSystem( "rain_storm_outer" ); + } + else //default to rain + { + PrecacheParticleSystem( "rain" ); + PrecacheParticleSystem( "rain_outer" ); + } +} + +void CClient_Precipitation::CreateParticlePrecip( void ) +{ + if ( !m_bParticlePrecipInitialized ) + { + PrecacheParticlePrecip(); + InitializeParticlePrecip(); + } + + + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + if ( pPlayer == NULL ) + return; + + // Make sure the emitter is setup + if ( !m_bActiveParticlePrecipEmitter ) + { + //Update 8 times per second. + m_tParticlePrecipTraceTimer.Init( 8 ); + DestroyInnerParticlePrecip(); + DestroyOuterParticlePrecip(); + m_bActiveParticlePrecipEmitter = true; + } + + UpdateParticlePrecip( pPlayer ); +} + +void CClient_Precipitation::UpdateParticlePrecip( C_BasePlayer *pPlayer ) +{ + if ( !pPlayer ) + return; + + Vector vForward; + Vector vRight; + + pPlayer->GetVectors( &vForward, &vRight, NULL ); + vForward.z = 0.0f; + vForward.NormalizeInPlace(); + Vector vForward45Right = vForward + vRight; + Vector vForward45Left = vForward - vRight; + vForward45Right.NormalizeInPlace(); + vForward45Left.NormalizeInPlace(); + fltx4 TMax = ReplicateX4( 320.0f ); + SubFloat( TMax, 3 ) = FLT_MAX; + float curTime = gpGlobals->frametime; + + while ( m_tParticlePrecipTraceTimer.NextEvent( curTime ) ) + { + Vector vPlayerPos = pPlayer->EyePosition(); + Vector vOffsetPos = vPlayerPos + Vector ( 0, 0, 180 ); + Vector vOffsetPosNear = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * 32 ); + Vector vOffsetPosFar = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * 100 ); + +#ifdef MAPBASE + if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP) + { + Vector mins, maxs; + modelinfo->GetModelBounds( GetModel(), mins, maxs ); + + // Account for precipitation height + maxs.z += 180; + + Vector vecOrigin; //= WorldSpaceCenter(); + VectorLerp( mins, maxs, 0.5f, vecOrigin ); + + maxs -= vecOrigin; + mins -= vecOrigin; + + float flMax = r_RainParticleClampOffset.GetFloat(); + Vector addend( flMax, flMax, 0 ); + mins += addend; + maxs -= addend; + + if (flMax > 0) + { + // Unless this is extruding outwards, make sure the offset isn't inverting the bounds. + // This means precipitation triggers with bounds less than offset*2 will turn into a thin line + // and the involved precipitation will pretty much be spatial at all times, which is okay. + mins.x = clamp( mins.x, -FLT_MAX, -1 ); + mins.y = clamp( mins.y, -FLT_MAX, -1 ); + maxs.x = clamp( maxs.x, 1, FLT_MAX ); + maxs.y = clamp( maxs.y, 1, FLT_MAX ); + } + + if (r_RainParticleClampDebug.GetBool()) + debugoverlay->AddBoxOverlay( vecOrigin, mins, maxs, vec3_angle, 255, 0, 0, 128, 0.15f ); + + maxs += vecOrigin; + mins += vecOrigin; + + CalcClosestPointOnAABB( mins, maxs, vPlayerPos, vPlayerPos ); + CalcClosestPointOnAABB( mins, maxs, vOffsetPos, vOffsetPos ); + CalcClosestPointOnAABB( mins, maxs, vOffsetPosNear, vOffsetPosNear ); + CalcClosestPointOnAABB( mins, maxs, vOffsetPosFar, vOffsetPosFar ); + } +#endif + + Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity; + + // Get the rain volume Ray Tracing Environment. Currently hard coded to 0, should have this lookup + RayTracingEnvironment *RtEnv = g_RayTraceEnvironments.Element( 0 ); + + // Our 4 Rays are forward, off to the left and right, and directly up. + // Use the first three to determine if there's generally visible rain where we're looking. + // The forth, straight up, tells us if we're standing inside a rain volume + // (based on the normal that we hit or if we miss entirely) + FourRays frRays; + FourVectors fvDirection; + fvDirection = FourVectors( vForward, vForward45Left, vForward45Right, Vector( 0, 0, 1 ) ); + frRays.direction = fvDirection; + frRays.origin.DuplicateVector( vPlayerPos ); + RayTracingResult Result; + + RtEnv->Trace4Rays( frRays, Four_Zeros, TMax, &Result ); + + i32x4 in4HitIds = LoadAlignedIntSIMD( Result.HitIds ); + fltx4 fl4HitIds = SignedIntConvertToFltSIMD ( in4HitIds ); + + fltx4 fl4Tolerance = ReplicateX4( 300.0f ); + // ignore upwards test for tolerance, as we may be below an area which is raining, but with it not visible in front of us + //SubFloat( fl4Tolerance, 3 ) = 0.0f; + + bool bInside = ( Result.HitIds[3] != -1 && Result.surface_normal.Vec( 3 ).z < 0.0f ); + bool bNearby = ( IsAnyNegative ( CmpGeSIMD ( fl4HitIds, Four_Zeros ) ) && IsAnyNegative( CmpGeSIMD( fl4Tolerance, Result.HitDistance ) ) ); + + if ( bInside || bNearby ) + { + //We can see a rain volume, but it's farther than 180 units away, only use far effect. + if ( !bInside && SubFloat( FindLowestSIMD3( Result.HitDistance ), 0 ) >= m_flParticleInnerDist ) + { + // Kill the inner rain if it's previously been in use + if ( m_pParticlePrecipInnerNear != NULL ) + { + DestroyInnerParticlePrecip(); + } + // Update if we've already got systems, otherwise, create them. + if ( m_pParticlePrecipOuter != NULL ) + { + m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos ); + m_pParticlePrecipOuter->SetControlPoint( 3, vDensity ); + } + else + { + DispatchOuterParticlePrecip( pPlayer, vForward ); + } + } + else //We're close enough to use the near effect. + { + // Update if we've already got systems, otherwise, create them. +#ifdef MAPBASE + // The outer can now be suppressed without interfering with other functionality + if ( m_pParticlePrecipOuter != NULL ) + { + m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos ); + m_pParticlePrecipOuter->SetControlPoint( 3, vDensity ); + } + if ( m_pParticlePrecipInnerNear != NULL && m_pParticlePrecipInnerFar != NULL ) + { + m_pParticlePrecipInnerNear->SetControlPoint( 1, vOffsetPosNear ); + m_pParticlePrecipInnerFar->SetControlPoint( 1, vOffsetPosFar ); + m_pParticlePrecipInnerNear->SetControlPoint( 3, vDensity ); + m_pParticlePrecipInnerFar->SetControlPoint( 3, vDensity ); + } +#else + if ( m_pParticlePrecipInnerNear != NULL && m_pParticlePrecipInnerFar != NULL && m_pParticlePrecipOuter != NULL ) + { + m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos ); + m_pParticlePrecipInnerNear->SetControlPoint( 1, vOffsetPosNear ); + m_pParticlePrecipInnerFar->SetControlPoint( 1, vOffsetPosFar ); + m_pParticlePrecipInnerNear->SetControlPoint( 3, vDensity ); + m_pParticlePrecipInnerFar->SetControlPoint( 3, vDensity ); + m_pParticlePrecipOuter->SetControlPoint( 3, vDensity ); + } +#endif + else + { + DispatchInnerParticlePrecip( pPlayer, vForward ); + } + } + } + else // No rain in the area, kill any leftover systems. + { + DestroyInnerParticlePrecip(); + DestroyOuterParticlePrecip(); + } + } +} + +void CClient_Precipitation::InitializeParticlePrecip( void ) +{ + //Set up which type of precipitation particle we'll use + if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLEASH ) + { + m_pParticleInnerNearDef = "ash"; + m_pParticleInnerFarDef = "ash"; + m_pParticleOuterDef = "ash_outer"; + m_flParticleInnerDist = 280.0; + } + else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLESNOW ) + { + m_pParticleInnerNearDef = "snow"; + m_pParticleInnerFarDef = "snow"; + m_pParticleOuterDef = "snow_outer"; + m_flParticleInnerDist = 280.0; + } + else if ( m_nPrecipType == PRECIPITATION_TYPE_PARTICLERAINSTORM ) + { + m_pParticleInnerNearDef = "rain_storm"; + m_pParticleInnerFarDef = "rain_storm_screen"; + m_pParticleOuterDef = "rain_storm_outer"; + m_flParticleInnerDist = 0.0; + } + else //default to rain + { + m_pParticleInnerNearDef = "rain"; + m_pParticleInnerFarDef = "rain"; + m_pParticleOuterDef = "rain_outer"; + m_flParticleInnerDist = 180.0; + } + + Assert( m_pParticleInnerFarDef != NULL ); + + //We'll want to change this if/when we add more raytrace environments. + g_RayTraceEnvironments.PurgeAndDeleteElements(); + + // Sets up ray tracing environments for all func_precipitations and func_precipitation_blockers + RayTracingEnvironment *rtEnvRainEmission = new RayTracingEnvironment(); + g_RayTraceEnvironments.AddToTail( rtEnvRainEmission ); + RayTracingEnvironment *rtEnvRainBlocker = new RayTracingEnvironment(); + g_RayTraceEnvironments.AddToTail( rtEnvRainBlocker ); + + rtEnvRainEmission->Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS; // save some ram + rtEnvRainBlocker->Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS; // save some ram + + int nTriCount = 1; + for ( int i=0; iGetVCollide( volume->GetModelIndex() ); + + if ( !pCollide || pCollide->solidCount <= 0 ) + continue; + + Vector *outVerts; + int vertCount = physcollision->CreateDebugMesh( pCollide->solids[0], &outVerts ); + + if ( vertCount ) + { + for ( int j = 0; j < vertCount; j += 3 ) + { + rtEnvRainEmission->AddTriangle( nTriCount++, outVerts[j], outVerts[j + 1], outVerts[j + 2], Vector( 1, 1, 1 ) ); + } + } + physcollision->DestroyDebugMesh( vertCount, outVerts ); + } + rtEnvRainEmission->SetupAccelerationStructure(); + + m_bParticlePrecipInitialized = true; +} + +void CClient_Precipitation::DestroyInnerParticlePrecip( void ) +{ + if ( m_pParticlePrecipInnerFar != NULL ) + { + m_pParticlePrecipInnerFar->StopEmission(); + m_pParticlePrecipInnerFar = NULL; + } + if ( m_pParticlePrecipInnerNear != NULL ) + { + m_pParticlePrecipInnerNear->StopEmission(); + m_pParticlePrecipInnerNear = NULL; + } +} + +void CClient_Precipitation::DestroyOuterParticlePrecip( void ) +{ + if ( m_pParticlePrecipOuter != NULL ) + { + m_pParticlePrecipOuter->StopEmission(); + m_pParticlePrecipOuter = NULL; + } +} + +void CClient_Precipitation::DispatchOuterParticlePrecip( C_BasePlayer *pPlayer, Vector vForward ) +{ + DestroyOuterParticlePrecip(); + +#ifdef MAPBASE + if (m_spawnflags & SF_PRECIP_PARTICLE_NO_OUTER) + return; +#endif + + Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity; + Vector vPlayerPos = pPlayer->EyePosition(); + + m_pParticlePrecipOuter = ParticleProp()->Create( m_pParticleOuterDef, PATTACH_ABSORIGIN_FOLLOW ); + m_pParticlePrecipOuter->SetControlPointEntity( 2, pPlayer ); + m_pParticlePrecipOuter->SetControlPoint( 1, vPlayerPos + Vector (0, 0, 180 ) ); + m_pParticlePrecipOuter->SetControlPoint( 3, vDensity ); +} + +void CClient_Precipitation::DispatchInnerParticlePrecip( C_BasePlayer *pPlayer, Vector vForward ) +{ + DestroyInnerParticlePrecip(); + DestroyOuterParticlePrecip(); + Vector vPlayerPos = pPlayer->EyePosition(); + Vector vOffsetPos = vPlayerPos + Vector ( 0, 0, 180 ); + Vector vOffsetPosNear = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * 32 ); + Vector vOffsetPosFar = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * m_flParticleInnerDist ); // 100.0 + Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity; + +#ifdef MAPBASE + if (!(m_spawnflags & SF_PRECIP_PARTICLE_NO_OUTER)) +#endif + { + m_pParticlePrecipOuter = ParticleProp()->Create( m_pParticleOuterDef, PATTACH_ABSORIGIN_FOLLOW ); + m_pParticlePrecipOuter->SetControlPointEntity( 2, pPlayer ); + m_pParticlePrecipOuter->SetControlPoint( 1, vOffsetPos ); + m_pParticlePrecipOuter->SetControlPoint( 3, vDensity ); + } + + m_pParticlePrecipInnerNear = ParticleProp()->Create( m_pParticleInnerNearDef, PATTACH_ABSORIGIN_FOLLOW ); + m_pParticlePrecipInnerFar = ParticleProp()->Create( m_pParticleInnerFarDef, PATTACH_ABSORIGIN_FOLLOW ); + m_pParticlePrecipInnerNear->SetControlPointEntity( 2, pPlayer ); + m_pParticlePrecipInnerFar->SetControlPointEntity( 2, pPlayer ); + m_pParticlePrecipInnerNear->SetControlPoint( 1, vOffsetPosNear ); + m_pParticlePrecipInnerFar->SetControlPoint( 1, vOffsetPosFar ); + m_pParticlePrecipInnerNear->SetControlPoint( 3, vDensity ); + m_pParticlePrecipInnerFar->SetControlPoint( 3, vDensity ); +} + void CClient_Precipitation::CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity ) { // Create the particle diff --git a/sp/src/game/client/c_effects.h b/sp/src/game/client/c_effects.h index 27bb501e..6012dff7 100644 --- a/sp/src/game/client/c_effects.h +++ b/sp/src/game/client/c_effects.h @@ -10,9 +10,178 @@ #pragma once #endif +#include "cbase.h" +#include "precipitation_shared.h" // Draw rain effects. void DrawPrecipitation(); +//----------------------------------------------------------------------------- +// Precipitation particle type +//----------------------------------------------------------------------------- + +class CPrecipitationParticle +{ +public: + Vector m_Pos; + Vector m_Velocity; + float m_SpawnTime; // Note: Tweak with this to change lifetime + float m_Mass; + float m_Ramp; + + float m_flCurLifetime; + float m_flMaxLifetime; +}; + + +class CClient_Precipitation; +static CUtlVector g_Precipitations; + +//=========== +// Snow fall +//=========== +class CSnowFallManager; +static CSnowFallManager *s_pSnowFallMgr = NULL; +bool SnowFallManagerCreate( CClient_Precipitation *pSnowEntity ); +void SnowFallManagerDestroy( void ); + +class AshDebrisEffect : public CSimpleEmitter +{ +public: + AshDebrisEffect( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {} + + static AshDebrisEffect* Create( const char *pDebugName ); + + virtual float UpdateAlpha( const SimpleParticle *pParticle ); + virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta ); + +private: + AshDebrisEffect( const AshDebrisEffect & ); +}; + +//----------------------------------------------------------------------------- +// Precipitation base entity +//----------------------------------------------------------------------------- + +class CClient_Precipitation : public C_BaseEntity +{ +class CPrecipitationEffect; +friend class CClient_Precipitation::CPrecipitationEffect; + +public: + DECLARE_CLASS( CClient_Precipitation, C_BaseEntity ); + DECLARE_CLIENTCLASS(); + + CClient_Precipitation(); + virtual ~CClient_Precipitation(); + + // Inherited from C_BaseEntity + virtual void Precache( ); + + void Render(); + +private: + + // Creates a single particle + CPrecipitationParticle* CreateParticle(); + + virtual void OnDataChanged( DataUpdateType_t updateType ); + virtual void ClientThink(); + + void Simulate( float dt ); + + // Renders the particle + void RenderParticle( CPrecipitationParticle* pParticle, CMeshBuilder &mb ); + + void CreateWaterSplashes(); + + // Emits the actual particles + void EmitParticles( float fTimeDelta ); + + // Computes where we're gonna emit + bool ComputeEmissionArea( Vector& origin, Vector2D& size ); + + // Gets the tracer width and speed + float GetWidth() const; + float GetLength() const; + float GetSpeed() const; + + // Gets the remaining lifetime of the particle + float GetRemainingLifetime( CPrecipitationParticle* pParticle ) const; + + // Computes the wind vector + static void ComputeWindVector( ); + + // simulation methods + bool SimulateRain( CPrecipitationParticle* pParticle, float dt ); + bool SimulateSnow( CPrecipitationParticle* pParticle, float dt ); + + void PrecacheParticlePrecip( void ); + void CreateParticlePrecip( void ); + void InitializeParticlePrecip( void ); + void DispatchOuterParticlePrecip( C_BasePlayer *pPlayer, Vector vForward ); + void DispatchInnerParticlePrecip( C_BasePlayer *pPlayer, Vector vForward ); + void DestroyOuterParticlePrecip( void ); + void DestroyInnerParticlePrecip( void ); + + void UpdateParticlePrecip( C_BasePlayer *pPlayer ); + +private: + void CreateAshParticle( void ); + void CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity ); + + // Information helpful in creating and rendering particles + IMaterial *m_MatHandle; // material used + + float m_Color[4]; // precip color + float m_Lifetime; // Precip lifetime + float m_InitialRamp; // Initial ramp value + float m_Speed; // Precip speed + float m_Width; // Tracer width + float m_Remainder; // particles we should render next time + PrecipitationType_t m_nPrecipType; // Precip type + float m_flHalfScreenWidth; // Precalculated each frame. + + float m_flDensity; + +#ifdef MAPBASE + int m_spawnflags; +#endif + + // Some state used in rendering and simulation + // Used to modify the rain density and wind from the console + static ConVar s_raindensity; + static ConVar s_rainwidth; + static ConVar s_rainlength; + static ConVar s_rainspeed; + + static Vector s_WindVector; // Stores the wind speed vector + + CUtlLinkedList m_Particles; + CUtlVector m_Splashes; + + CSmartPtr m_pAshEmitter; + TimedEvent m_tAshParticleTimer; + TimedEvent m_tAshParticleTraceTimer; + bool m_bActiveAshEmitter; + Vector m_vAshSpawnOrigin; + + int m_iAshCount; + +protected: + float m_flParticleInnerDist; //The distance at which to start drawing the inner system + char *m_pParticleInnerNearDef; //Name of the first inner system + char *m_pParticleInnerFarDef; //Name of the second inner system + char *m_pParticleOuterDef; //Name of the outer system + HPARTICLEFFECT m_pParticlePrecipInnerNear; + HPARTICLEFFECT m_pParticlePrecipInnerFar; + HPARTICLEFFECT m_pParticlePrecipOuter; + TimedEvent m_tParticlePrecipTraceTimer; + bool m_bActiveParticlePrecipEmitter; + bool m_bParticlePrecipInitialized; + +private: + CClient_Precipitation( const CClient_Precipitation & ); // not defined, not accessible +}; #endif // C_EFFECTS_H diff --git a/sp/src/game/client/cbase.h b/sp/src/game/client/cbase.h index 57e3260b..53322ca4 100644 --- a/sp/src/game/client/cbase.h +++ b/sp/src/game/client/cbase.h @@ -37,6 +37,10 @@ struct studiohdr_t; #include #include +#ifdef MAPBASE +#include "tier1/mapbase_con_groups.h" +#endif + // This is a precompiled header. Include a bunch of common stuff. // This is kind of ugly in that it adds a bunch of dependency where it isn't needed. diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index fa9204eb..4b9b879f 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -40,10 +40,13 @@ $Project $File "$SRCDIR\game\shared\mapbase\matchers.h" $File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT] - $File "$SRCDIR\game\shared\mapbase\vscript_funcs_math.cpp" [$MAPBASE_VSCRIPT] - $File "$SRCDIR\game\shared\mapbase\vscript_funcs_math.h" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\vscript_singletons.h" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\vscript_funcs_hl2.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\vscript_consts_shared.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\vscript_consts_weapons.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT] $File "mapbase\c_func_clientclip.cpp" $File "mapbase\c_func_fake_worldportal.cpp" @@ -71,5 +74,6 @@ $Project $Folder "Link Libraries" { $Lib "vscript" [$MAPBASE_VSCRIPT] + $Lib "raytrace" } } diff --git a/sp/src/game/client/hl2/hud_credits.cpp b/sp/src/game/client/hl2/hud_credits.cpp index da6d070b..280e8a44 100644 --- a/sp/src/game/client/hl2/hud_credits.cpp +++ b/sp/src/game/client/hl2/hud_credits.cpp @@ -139,6 +139,8 @@ private: #ifdef MAPBASE char m_szCreditsFile[MAX_PATH]; + + char m_szLogoFont[64]; #endif }; @@ -263,6 +265,10 @@ void CHudCredits::ReadParams( KeyValues *pKeyValue ) Q_strncpy( m_szLogo, pKeyValue->GetString( "logo", "HALF-LIFE'" ), sizeof( m_szLogo ) ); Q_strncpy( m_szLogo2, pKeyValue->GetString( "logo2", "" ), sizeof( m_szLogo2 ) ); + +#ifdef MAPBASE + Q_strncpy( m_szLogoFont, pKeyValue->GetString( "logofont", "" ), sizeof( m_szLogoFont ) ); +#endif } int CHudCredits::GetStringPixelWidth( wchar_t *pString, vgui::HFont hFont ) @@ -437,6 +443,14 @@ void CHudCredits::DrawLogo( void ) char szLogoFont[64]; +#ifdef MAPBASE + if (m_szLogoFont[0] != '\0') + { + // Custom logo font + Q_strncpy( szLogoFont, m_szLogoFont, sizeof( szLogoFont ) ); + } + else +#endif if ( IsXbox() ) { Q_snprintf( szLogoFont, sizeof( szLogoFont ), "WeaponIcons_Small" ); diff --git a/sp/src/game/client/message.cpp b/sp/src/game/client/message.cpp index fe341e71..1a5c4ae4 100644 --- a/sp/src/game/client/message.cpp +++ b/sp/src/game/client/message.cpp @@ -862,6 +862,82 @@ void CHudMessage::MsgFunc_HudMsg(bf_read &msg) // see tmessage.cpp why 512 msg.ReadString( (char*)pNetMessage->pMessage, 512 ); +#ifdef MAPBASE + // + // Mapbase adds a new data entry for custom fonts on entities like game_text. + // Some existing instances of this user message may not have this, so we have to make sure we have any bits left first. + // + if (msg.GetNumBitsLeft() > 0) + { + // Try to have VGui font names for each channel + static char szVGuiFontNames[MAX_NETMESSAGE][512]; + msg.ReadString( szVGuiFontNames[channel], 512 ); + if (szVGuiFontNames[channel][0] != '\0') + { + pNetMessage->pVGuiSchemeFontName = szVGuiFontNames[channel]; + } + } + + // + // Mapbase adds a new data entry for breaking game_text into newline when it goes past the user's screen. + // Some existing instances of this user message may not have this, so we have to make sure we have any bits left first. + // + if (msg.GetNumBitsLeft() > 0) + { + int len = msg.ReadByte(); + + // This is supposed to work around a bug where certain aspect ratios cut off lengthy texts. + //int lineMax = 64 * ((float)ScreenWidth() / 1440.0f); + int lineMax = 100 / engine->GetScreenAspectRatio(); + + int lineMinBreak = lineMax * 0.9; + + DevMsg( "Line max is %i from an aspect ratio of %.3f (strlen %i)\n", lineMax, engine->GetScreenAspectRatio(), len ); + + char *curMessage = (char*)pNetMessage->pMessage; + char newMessage[512]; + + int cur = 0; // Current time on this line + int i = 0; // curMessage + int i2 = 0; // newMessage + for (i = 0; i < len; i++) + { + cur++; + newMessage[i2] = curMessage[i]; + + // Check if we're past the point in which we should break the line + if (cur >= lineMinBreak) + { + // Line break at the next space + if (curMessage[i] == ' ') + { + newMessage[i2] = '\n'; + cur = 0; + } + else if (curMessage[i] == '\n') + { + // Already a newline here + cur = 0; + } + else if (cur >= lineMax) + { + // We're at the max and there's no space. Force a newline with a hyphen + newMessage[i2] = '-'; + i2++; + newMessage[i2] = '\n'; + i2++; + newMessage[i2] = curMessage[i]; + cur = 0; + } + } + + i2++; + } + + Q_strncpy( (char*)pNetMessage->pMessage, newMessage, 512 ); + } +#endif + MessageAdd( pNetMessage->pName ); } diff --git a/sp/src/game/client/vscript_client.cpp b/sp/src/game/client/vscript_client.cpp index d6749182..3f7e7cea 100644 --- a/sp/src/game/client/vscript_client.cpp +++ b/sp/src/game/client/vscript_client.cpp @@ -141,7 +141,7 @@ public: { if (i > SCRIPT_MAT_PROXY_MAX_VARS || i < 0) { - Warning("VScriptProxy: %i out of range", i); + CGWarning( 0, CON_GROUP_VSCRIPT, "VScriptProxy: %i out of range", i ); return false; } @@ -261,7 +261,7 @@ bool CScriptMaterialProxy::InitScript() if (!bResult) { - DevMsg("VScriptProxy couldn't create ScriptScope!\n"); + CGMsg( 1, CON_GROUP_VSCRIPT, "VScriptProxy couldn't create ScriptScope!\n" ); return false; } @@ -474,7 +474,7 @@ bool VScriptClientInit() #endif else { - DevWarning("-scriptlang does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage ); + CGWarning( 1, CON_GROUP_VSCRIPT, "-scriptlang does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage ); scriptLanguage = SL_NONE; } @@ -487,7 +487,7 @@ bool VScriptClientInit() if( g_pScriptVM ) { #ifdef MAPBASE_VSCRIPT - Log( "VSCRIPT CLIENT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); + CGMsg( 0, CON_GROUP_VSCRIPT, "VSCRIPT CLIENT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); #else Log( "VSCRIPT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); #endif @@ -527,13 +527,13 @@ bool VScriptClientInit() } else { - DevWarning("VM Did not start!\n"); + CGWarning( 1, CON_GROUP_VSCRIPT, "VM Did not start!\n" ); } } } else { - Log( "\nVSCRIPT: Scripting is disabled.\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "\nVSCRIPT: Scripting is disabled.\n" ); } g_pScriptVM = NULL; return false; diff --git a/sp/src/game/client/vscript_client.h b/sp/src/game/client/vscript_client.h index b2aa3aae..9b69563e 100644 --- a/sp/src/game/client/vscript_client.h +++ b/sp/src/game/client/vscript_client.h @@ -4,8 +4,8 @@ // //============================================================================= -#ifndef VSCRIPT_SERVER_H -#define VSCRIPT_SERVER_H +#ifndef VSCRIPT_CLIENT_H +#define VSCRIPT_CLIENT_H #include "vscript/ivscript.h" #include "vscript_shared.h" @@ -19,4 +19,8 @@ extern IScriptVM * g_pScriptVM; // Only allow scripts to create entities during map initialization bool IsEntityCreationAllowedInScripts( void ); -#endif // VSCRIPT_SERVER_H +#ifdef MAPBASE_VSCRIPT +extern IScriptManager * scriptmanager; +#endif + +#endif // VSCRIPT_CLIENT_H diff --git a/sp/src/game/server/AI_ResponseSystem.cpp b/sp/src/game/server/AI_ResponseSystem.cpp index 2023de4b..43fc871b 100644 --- a/sp/src/game/server/AI_ResponseSystem.cpp +++ b/sp/src/game/server/AI_ResponseSystem.cpp @@ -33,6 +33,10 @@ ConVar rr_debugresponses( "rr_debugresponses", "0", FCVAR_NONE, "Show verbose ma ConVar rr_debugrule( "rr_debugrule", "", FCVAR_NONE, "If set to the name of the rule, that rule's score will be shown whenever a concept is passed into the response rules system."); ConVar rr_dumpresponses( "rr_dumpresponses", "0", FCVAR_NONE, "Dump all response_rules.txt and rules (requires restart)" ); +#ifdef MAPBASE +ConVar rr_enhanced_saverestore( "rr_enhanced_saverestore", "0", FCVAR_NONE, "Enables enhanced save/restore capabilities for the Response System." ); +#endif + static CUtlSymbolTable g_RS; inline static char *CopyString( const char *in ) @@ -3176,6 +3180,9 @@ public: Precache(); } +#ifdef MAPBASE + if (!rr_enhanced_saverestore.GetBool() || gpGlobals->eLoadType != MapLoad_Transition) +#endif ResetResponseGroups(); } @@ -3588,6 +3595,34 @@ public: pSave->EndBlock(); } + +#ifdef MAPBASE + // Enhanced Response System save/restore + int count2 = 0; + if (rr_enhanced_saverestore.GetBool()) + { + // Rule state save/load + count2 = rs.m_Rules.Count(); + pSave->WriteInt( &count2 ); + for ( int i = 0; i < count2; ++i ) + { + pSave->StartBlock( "Rule" ); + + pSave->WriteString( rs.m_Rules.GetElementName( i ) ); + const Rule *rule = &rs.m_Rules[ i ]; + + bool bEnabled = rule->m_bEnabled; + pSave->WriteBool( &bEnabled ); + + pSave->EndBlock(); + } + } + else + { + // Indicate this isn't using enhanced save/restore + pSave->WriteInt( &count2 ); + } +#endif } void Restore( IRestore *pRestore, bool createPlayers ) @@ -3651,6 +3686,34 @@ public: pRestore->EndBlock(); } + +#ifdef MAPBASE + // Enhanced Response System save/restore + count = pRestore->ReadInt(); + for ( int i = 0; i < count; ++i ) + { + char szRuleBlockName[SIZE_BLOCK_NAME_BUF]; + pRestore->StartBlock( szRuleBlockName ); + if ( !Q_stricmp( szRuleBlockName, "Rule" ) ) + { + char groupname[ 256 ]; + pRestore->ReadString( groupname, sizeof( groupname ), 0 ); + + // Try and find it + int idx = rs.m_Rules.Find( groupname ); + if ( idx != rs.m_Rules.InvalidIndex() ) + { + Rule *rule = &rs.m_Rules[ idx ]; + + bool bEnabled; + pRestore->ReadBool( &bEnabled ); + rule->m_bEnabled = bEnabled; + } + } + + pRestore->EndBlock(); + } +#endif } private: diff --git a/sp/src/game/server/ai_baseactor.h b/sp/src/game/server/ai_baseactor.h index c51391f3..f0d9f8ae 100644 --- a/sp/src/game/server/ai_baseactor.h +++ b/sp/src/game/server/ai_baseactor.h @@ -194,6 +194,7 @@ public: , SCENE_AI_ADDCONTEXT, SCENE_AI_INPUT, + SCENE_AI_GAMETEXT, // This is handled in CBaseFlex #endif }; diff --git a/sp/src/game/server/ai_basenpc.cpp b/sp/src/game/server/ai_basenpc.cpp index 3cdf0491..e18fbb34 100644 --- a/sp/src/game/server/ai_basenpc.cpp +++ b/sp/src/game/server/ai_basenpc.cpp @@ -301,6 +301,14 @@ int CAI_BaseNPC::gm_nSpawnedThisFrame; CSimpleSimTimer CAI_BaseNPC::m_AnyUpdateEnemyPosTimer; +#ifdef MAPBASE_VSCRIPT +// TODO: Better placement? +ScriptHook_t g_Hook_QueryHearSound; +ScriptHook_t g_Hook_QuerySeeEntity; +ScriptHook_t g_Hook_TranslateActivity; +ScriptHook_t g_Hook_TranslateSchedule; +#endif + // // Deferred Navigation calls go here // @@ -744,7 +752,9 @@ HSCRIPT CAI_BaseNPC::VScriptGetHintNode() const char *CAI_BaseNPC::VScriptGetSchedule() { const char *pName = NULL; - pName = GetCurSchedule()->GetName(); + if (GetCurSchedule()) + pName = GetCurSchedule()->GetName(); + if (!pName) pName = "Unknown"; @@ -755,6 +765,9 @@ const char *CAI_BaseNPC::VScriptGetSchedule() //----------------------------------------------------------------------------- int CAI_BaseNPC::VScriptGetScheduleID() { + if (!GetCurSchedule()) + return -1; + int iSched = GetCurSchedule()->GetId(); // Local IDs are needed to correspond with user-friendly enums @@ -817,6 +830,18 @@ HSCRIPT CAI_BaseNPC::VScriptGetCine() { return ToHScript(m_hCine.Get()); } + +HSCRIPT CAI_BaseNPC::VScriptGetSquad() +{ + HSCRIPT hScript = NULL; + CAI_Squad *pSquad = GetSquad(); + if (pSquad) + { + hScript = g_pScriptVM->RegisterInstance( pSquad ); + } + + return hScript; +} #endif bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info ) @@ -2299,23 +2324,17 @@ bool CAI_BaseNPC::QueryHearSound( CSound *pSound ) return false; #ifdef MAPBASE_VSCRIPT - if (HSCRIPT hFunc = LookupScriptFunction("QueryHearSound")) + if (m_ScriptScope.IsInitialized() && g_Hook_QueryHearSound.CanRunInScope(m_ScriptScope)) { HSCRIPT hSound = g_pScriptVM->RegisterInstance( pSound ); - g_pScriptVM->SetValue( "sound", hSound ); - ScriptVariant_t functionReturn; - bool bValid = true; - if ( CallScriptFunctionHandle( hFunc, &functionReturn ) ) - { - if (functionReturn.m_bool == false) - bValid = false; - } + ScriptVariant_t functionReturn = true; + ScriptVariant_t args[] = { hSound }; + g_Hook_QueryHearSound.Call( m_ScriptScope, &functionReturn, args ); - g_pScriptVM->ClearValue( "sound" ); g_pScriptVM->RemoveInstance( hSound ); - if (bValid == false) + if (functionReturn.m_bool == false) return false; } #endif @@ -2338,18 +2357,15 @@ bool CAI_BaseNPC::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNP #ifdef MAPBASE_VSCRIPT if (bValid) { - if (HSCRIPT hFunc = LookupScriptFunction("QuerySeeEntity")) + if (m_ScriptScope.IsInitialized() && g_Hook_QuerySeeEntity.CanRunInScope(m_ScriptScope)) { - g_pScriptVM->SetValue( "entity", ToHScript(pEntity) ); - ScriptVariant_t functionReturn; - if ( CallScriptFunctionHandle( hFunc, &functionReturn ) ) + ScriptVariant_t args[] = { ToHScript(pEntity) }; + if (g_Hook_QuerySeeEntity.Call( m_ScriptScope, &functionReturn, args )) { if (functionReturn.m_bool == false) bValid = false; } - - g_pScriptVM->ClearValue( "entity" ); } } #endif @@ -6566,6 +6582,9 @@ Activity CAI_BaseNPC::NPC_BackupActivity( Activity eNewActivity ) if (eNewActivity == ACT_BUSY_QUEUE || eNewActivity == ACT_BUSY_STAND) return TranslateActivity(ACT_IDLE); + if (eNewActivity == ACT_WALK_ANGRY) + return TranslateActivity(ACT_WALK); + // GetCoverActivity() should have this covered. // --------------------------------------------- //if (eNewActivity == ACT_COVER) @@ -6604,13 +6623,12 @@ Activity CAI_BaseNPC::NPC_TranslateActivity( Activity eNewActivity ) } #ifdef MAPBASE_VSCRIPT - if (HSCRIPT hFunc = LookupScriptFunction("NPC_TranslateActivity")) + if (m_ScriptScope.IsInitialized() && g_Hook_TranslateActivity.CanRunInScope(m_ScriptScope)) { - g_pScriptVM->SetValue( "activity", GetActivityName(eNewActivity) ); - g_pScriptVM->SetValue( "activity_id", (int)eNewActivity ); - + // activity, activity_id ScriptVariant_t functionReturn; - if ( CallScriptFunctionHandle( hFunc, &functionReturn ) ) + ScriptVariant_t args[] = { GetActivityName(eNewActivity), (int)eNewActivity }; + if (g_Hook_TranslateActivity.Call( m_ScriptScope, &functionReturn, args )) { if (functionReturn.m_type == FIELD_INTEGER) { @@ -6625,9 +6643,6 @@ Activity CAI_BaseNPC::NPC_TranslateActivity( Activity eNewActivity ) eNewActivity = activity; } } - - g_pScriptVM->ClearValue( "activity" ); - g_pScriptVM->ClearValue( "activity_id" ); } #endif #else @@ -12040,6 +12055,28 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC 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." ) + DEFINE_SCRIPTFUNC_NAMED( VScriptGetSquad, "GetSquad", "Get the NPC's squad if it has one." ) + DEFINE_SCRIPTFUNC( IsInSquad, "Returns true if the NPC is in a squad." ) + DEFINE_SCRIPTFUNC( NumWeaponsInSquad, "Get the number of weapons in a squad." ) + + // + // Hooks + // + BEGIN_SCRIPTHOOK( g_Hook_QueryHearSound, "QueryHearSound", FIELD_BOOLEAN, "Called when the NPC is deciding whether to hear a CSound or not." ) + DEFINE_SCRIPTHOOK_PARAM( "sound", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + BEGIN_SCRIPTHOOK( g_Hook_QuerySeeEntity, "QuerySeeEntity", FIELD_BOOLEAN, "Called when the NPC is deciding whether to see an entity or not." ) + DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + BEGIN_SCRIPTHOOK( g_Hook_TranslateActivity, "NPC_TranslateActivity", FIELD_VARIANT, "Called when the NPC is translating their current activity. The activity is provided in both string and ID form. Should return either an activity string or an activity ID. Return -1 to not translate." ) + DEFINE_SCRIPTHOOK_PARAM( "activity", FIELD_CSTRING ) + DEFINE_SCRIPTHOOK_PARAM( "activity_id", FIELD_INTEGER ) + END_SCRIPTHOOK() + BEGIN_SCRIPTHOOK( g_Hook_TranslateSchedule, "NPC_TranslateSchedule", FIELD_VARIANT, "Called when the NPC is translating their current schedule. The schedule is provided in both string and ID form. Should return either a schedule string or a schedule ID. Return -1 to not translate." ) + DEFINE_SCRIPTHOOK_PARAM( "schedule", FIELD_CSTRING ) + DEFINE_SCRIPTHOOK_PARAM( "schedule_id", FIELD_INTEGER ) + END_SCRIPTHOOK() + END_SCRIPTDESC(); #endif @@ -15890,17 +15927,6 @@ bool CAI_BaseNPC::IsCrouchedActivity( Activity activity ) //case ACT_RELOAD_AR2_LOW: case ACT_RELOAD_PISTOL_LOW: case ACT_RELOAD_SHOTGUN_LOW: - - case ACT_RANGE_AIM_LOW: - case ACT_RANGE_AIM_AR2_LOW: - case ACT_RANGE_AIM_SMG1_LOW: - case ACT_RANGE_AIM_PISTOL_LOW: - - case ACT_RANGE_ATTACK1_LOW: - case ACT_RANGE_ATTACK_AR2_LOW: - case ACT_RANGE_ATTACK_SMG1_LOW: - case ACT_RANGE_ATTACK_PISTOL_LOW: - case ACT_RANGE_ATTACK2_LOW: #endif return true; } diff --git a/sp/src/game/server/ai_basenpc.h b/sp/src/game/server/ai_basenpc.h index 0ce63e7c..cd909f33 100644 --- a/sp/src/game/server/ai_basenpc.h +++ b/sp/src/game/server/ai_basenpc.h @@ -1248,6 +1248,8 @@ public: HSCRIPT VScriptGetCine(); int GetScriptState() { return m_scriptState; } + + HSCRIPT VScriptGetSquad(); #endif //----------------------------------------------------- diff --git a/sp/src/game/server/ai_basenpc_schedule.cpp b/sp/src/game/server/ai_basenpc_schedule.cpp index 18719d43..64a51518 100644 --- a/sp/src/game/server/ai_basenpc_schedule.cpp +++ b/sp/src/game/server/ai_basenpc_schedule.cpp @@ -2785,7 +2785,11 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask ) { if ( !m_hCine ) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_NPC_SCRIPTS, "Scripted sequence destroyed while in use\n" ); +#else DevMsg( "Scripted sequence destroyed while in use\n" ); +#endif TaskFail( FAIL_SCHEDULE_NOT_FOUND ); break; } @@ -2796,7 +2800,11 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask ) { if ( !m_hCine ) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_NPC_SCRIPTS, "Scripted sequence destroyed while in use\n" ); +#else DevMsg( "Scripted sequence destroyed while in use\n" ); +#endif TaskFail( FAIL_SCHEDULE_NOT_FOUND ); break; } @@ -3750,8 +3758,6 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) // only slightly above our initial search conditions. if (GetNavigator()->BuildAndGetPathDistToGoal() < 300.0f) { - // NOTE: Remove this DevMsg() when this is tested! - DevMsg("Player Withdrawal Destination Dist: %f\n", GetNavigator()->GetPathDistToGoal()); pHint->NPCHandleStartNav(this, false); pHint->DisableForSeconds( 0.1f ); // Force others to find their own. TaskComplete(); @@ -3999,7 +4005,11 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) } else if (!m_hCine) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_NPC_SCRIPTS, "Cine died!\n" ); +#else DevMsg( "Cine died!\n"); +#endif TaskComplete(); } else if ( IsRunningDynamicInteraction() ) @@ -4055,7 +4065,11 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) { if ( !m_hCine ) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_NPC_SCRIPTS, "Scripted sequence destroyed while in use\n" ); +#else DevMsg( "Scripted sequence destroyed while in use\n" ); +#endif TaskFail( FAIL_SCHEDULE_NOT_FOUND ); break; } @@ -4074,7 +4088,11 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask ) { if ( !m_hCine ) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_NPC_SCRIPTS, "Scripted sequence destroyed while in use\n" ); +#else DevMsg( "Scripted sequence destroyed while in use\n" ); +#endif TaskFail( FAIL_SCHEDULE_NOT_FOUND ); break; } @@ -4403,7 +4421,11 @@ int CAI_BaseNPC::GetScriptCustomMoveSequence( void ) iSequence = LookupSequence( STRING( m_hCine->m_iszCustomMove ) ); if ( iSequence == ACTIVITY_NOT_AVAILABLE ) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_NPC_SCRIPTS, "SCRIPT_CUSTOM_MOVE: %s has no sequence:%s\n", GetClassname(), STRING(m_hCine->m_iszCustomMove) ); +#else DevMsg( "SCRIPT_CUSTOM_MOVE: %s has no sequence:%s\n", GetClassname(), STRING(m_hCine->m_iszCustomMove) ); +#endif } } else if ( m_iszSceneCustomMoveSeq != NULL_STRING ) diff --git a/sp/src/game/server/ai_default.cpp b/sp/src/game/server/ai_default.cpp index 879fdd17..8f660ec3 100644 --- a/sp/src/game/server/ai_default.cpp +++ b/sp/src/game/server/ai_default.cpp @@ -374,6 +374,10 @@ int CAI_BaseNPC::TranslateSchedule( int scheduleType ) return scheduleType; } +#ifdef MAPBASE +extern ScriptHook_t g_Hook_TranslateSchedule; +#endif + //========================================================= // GetScheduleOfType - returns a pointer to one of the // NPC's available schedules of the indicated type. @@ -387,25 +391,19 @@ CAI_Schedule *CAI_BaseNPC::GetScheduleOfType( int scheduleType ) AI_PROFILE_SCOPE_END(); #ifdef MAPBASE_VSCRIPT - if ( m_ScriptScope.IsInitialized() ) + if ( m_ScriptScope.IsInitialized() && g_Hook_TranslateSchedule.CanRunInScope(m_ScriptScope) ) { - // Some of this code should know if there's a function first, so look - // up the function beforehand instead of using CallScriptFunction() - HSCRIPT hFunc = m_ScriptScope.LookupFunction( "NPC_TranslateSchedule" ); - if (hFunc) + int newSchedule = scheduleType; + if ( AI_IdIsLocal( newSchedule ) ) { - int newSchedule = scheduleType; - if ( AI_IdIsLocal( newSchedule ) ) - { - newSchedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(newSchedule); - } - - g_pScriptVM->SetValue( "schedule", GetSchedulingSymbols()->ScheduleIdToSymbol( newSchedule ) ); - g_pScriptVM->SetValue( "schedule_id", scheduleType ); // Use the local ID - - ScriptVariant_t functionReturn; - m_ScriptScope.Call( hFunc, &functionReturn ); + newSchedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(newSchedule); + } + // schedule, schedule_id (local ID) + ScriptVariant_t functionReturn; + ScriptVariant_t args[] = { GetSchedulingSymbols()->ScheduleIdToSymbol( newSchedule ), scheduleType }; + if (g_Hook_TranslateSchedule.Call( m_ScriptScope, &functionReturn, args )) + { if (functionReturn.m_type == FIELD_INTEGER) { newSchedule = functionReturn.m_int; @@ -417,9 +415,6 @@ CAI_Schedule *CAI_BaseNPC::GetScheduleOfType( int scheduleType ) if (newSchedule != scheduleType && newSchedule > -1) scheduleType = newSchedule; - - g_pScriptVM->ClearValue( "schedule" ); - g_pScriptVM->ClearValue( "schedule_id" ); } } #endif diff --git a/sp/src/game/server/ai_squad.cpp b/sp/src/game/server/ai_squad.cpp index 17e0c18f..bdd58d5d 100644 --- a/sp/src/game/server/ai_squad.cpp +++ b/sp/src/game/server/ai_squad.cpp @@ -114,6 +114,48 @@ void CAI_SquadManager::DeleteAllSquads(void) CAI_SquadManager::m_pSquads = NULL; } +#ifdef MAPBASE_VSCRIPT +//------------------------------------- +// Purpose: +//------------------------------------- +HSCRIPT CAI_SquadManager::ScriptGetFirstSquad() +{ + return m_pSquads ? g_pScriptVM->RegisterInstance( m_pSquads ) : NULL; +} + +HSCRIPT CAI_SquadManager::ScriptGetNextSquad( HSCRIPT hStart ) +{ + CAI_Squad *pSquad = HScriptToClass( hStart ); + return (pSquad && pSquad->m_pNextSquad) ? g_pScriptVM->RegisterInstance( pSquad->m_pNextSquad ) : NULL; +} + +//------------------------------------- +// Purpose: +//------------------------------------- +HSCRIPT CAI_SquadManager::ScriptFindSquad( const char *squadName ) +{ + CAI_Squad *pSquad = FindSquad( MAKE_STRING(squadName) ); + return pSquad ? g_pScriptVM->RegisterInstance( pSquad ) : NULL; +} + +HSCRIPT CAI_SquadManager::ScriptFindCreateSquad( const char *squadName ) +{ + CAI_Squad *pSquad = FindCreateSquad( MAKE_STRING( squadName ) ); + return pSquad ? g_pScriptVM->RegisterInstance( pSquad ) : NULL; +} + +BEGIN_SCRIPTDESC_ROOT( CAI_SquadManager, SCRIPT_SINGLETON "Manager for NPC squads." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetFirstSquad, "GetFirstSquad", "Get the first squad in the squad list." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetNextSquad, "GetNextSquad", "Get the next squad in the squad list starting from the specified squad." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptFindSquad, "FindSquad", "Find the specified squad in the squad list. Returns null if none found." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptFindCreateSquad, "FindCreateSquad", "Find the specified squad in the squad list or create it if it doesn't exist." ) + + DEFINE_SCRIPTFUNC( NumSquads, "Get the number of squads in the list." ) + +END_SCRIPTDESC(); +#endif + //----------------------------------------------------------------------------- // CAI_Squad // @@ -151,6 +193,38 @@ BEGIN_SIMPLE_DATADESC( CAI_Squad ) END_DATADESC() +#ifdef MAPBASE_VSCRIPT +BEGIN_SCRIPTDESC_ROOT( CAI_Squad, "NPC squads used for schedule coordination, sharing information about enemies, etc." ) + + DEFINE_SCRIPTFUNC( GetName, "Get the squad's name." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetFirstMember, "GetFirstMember", "Get the squad's first member. The parameter is for whether to ignore silent members (see CAI_Squad::IsSilentMember() for more info)." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetMember, "GetMember", "Get one of the squad's members by their index." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetAnyMember, "GetAnyMember", "Randomly get any one of the squad's members." ) + DEFINE_SCRIPTFUNC( NumMembers, "Get the squad's number of members. The parameter is for whether to ignore silent members (see CAI_Squad::IsSilentMember() for more info)." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetSquadIndex, "GetSquadIndex", "Get the index of the specified NPC in the squad." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptUpdateEnemyMemory, "UpdateEnemyMemory", "Updates the squad's memory of an enemy. The first parameter is the updater, the second parameter is the enemy, and the third parameter is the position." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptSquadMemberInRange, "SquadMemberInRange", "Get the first squad member found around the specified position in the specified range." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptNearestSquadMember, "NearestSquadMember", "Get the squad member nearest to the specified member." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetVisibleSquadMembers, "GetVisibleSquadMembers", "Get the number of squad members visible to the specified member." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetSquadMemberNearestTo, "GetSquadMemberNearestTo", "Get the squad member nearest to a point." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptIsMember, "IsMember", "Returns true if the specified NPC is a member of the squad." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptIsLeader, "IsLeader", "Returns true if the specified NPC is the squad's leader." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetLeader, "GetLeader", "Get the squad's leader." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptAddToSquad, "AddToSquad", "Adds a NPC to the squad." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptRemoveFromSquad, "RemoveFromSquad", "Removes a NPC from the squad." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptIsSilentMember, "IsSilentMember", "Returns true if the specified NPC is a \"silent squad member\", which means it's only in squads for enemy information purposes and does not actually participate in any tactics. For example, this is used for npc_enemyfinder and vital allies (e.g. Alyx) in the player's squad. Please note that this does not check if the NPC is in the squad first." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptSetSquadData, "SetSquadData", "Set the squad data in the specified slot." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetSquadData, "GetSquadData", "Get the squad data in the specified slot." ) + +END_SCRIPTDESC(); +#endif + //------------------------------------- CAI_Squad::CAI_Squad(string_t newName) @@ -783,5 +857,44 @@ bool CAI_Squad::IsSquadInflictor( CBaseEntity *pInflictor ) return (m_hSquadInflictor.Get() == pInflictor); } +#ifdef MAPBASE_VSCRIPT +//------------------------------------------------------------------------------ + +// Functions tailored specifically for VScript. + +HSCRIPT CAI_Squad::ScriptGetFirstMember( bool bIgnoreSilentMembers ) { return ToHScript( GetFirstMember( NULL, bIgnoreSilentMembers ) ); } +HSCRIPT CAI_Squad::ScriptGetMember( int iIndex ) { return iIndex < m_SquadMembers.Count() ? ToHScript( m_SquadMembers[iIndex] ) : NULL; } +HSCRIPT CAI_Squad::ScriptGetAnyMember() { return ToHScript( GetAnyMember() ); } +//int CAI_Squad::ScriptNumMembers( bool bIgnoreSilentMembers ) { return NumMembers( bIgnoreSilentMembers ); } +int CAI_Squad::ScriptGetSquadIndex( HSCRIPT hNPC ) { return GetSquadIndex( HScriptToClass( hNPC ) ); } + +void CAI_Squad::ScriptUpdateEnemyMemory( HSCRIPT hUpdater, HSCRIPT hEnemy, const Vector &position ) { UpdateEnemyMemory( HScriptToClass( hUpdater ), ToEnt( hEnemy ), position ); } + +HSCRIPT CAI_Squad::ScriptSquadMemberInRange( const Vector &vecLocation, float flDist ) { return ToHScript( SquadMemberInRange( vecLocation, flDist ) ); } +HSCRIPT CAI_Squad::ScriptNearestSquadMember( HSCRIPT hMember ) { return ToHScript( NearestSquadMember( HScriptToClass( hMember ) ) ); } +int CAI_Squad::ScriptGetVisibleSquadMembers( HSCRIPT hMember ) { return GetVisibleSquadMembers( HScriptToClass( hMember ) ); } +HSCRIPT CAI_Squad::ScriptGetSquadMemberNearestTo( const Vector &vecLocation ) { return ToHScript( GetSquadMemberNearestTo( vecLocation ) ); } +bool CAI_Squad::ScriptIsMember( HSCRIPT hMember ) { return SquadIsMember( HScriptToClass( hMember ) ); } +bool CAI_Squad::ScriptIsLeader( HSCRIPT hLeader ) { return IsLeader( HScriptToClass( hLeader ) ); } +HSCRIPT CAI_Squad::ScriptGetLeader( void ) { return ToHScript( GetLeader() ); } + +void CAI_Squad::ScriptAddToSquad( HSCRIPT hNPC ) { AddToSquad( HScriptToClass( hNPC ) ); } +void CAI_Squad::ScriptRemoveFromSquad( HSCRIPT hNPC ) { RemoveFromSquad( HScriptToClass( hNPC ), false ); } + +bool CAI_Squad::ScriptIsSilentMember( HSCRIPT hNPC ) { return IsSilentMember( HScriptToClass( hNPC ) ); } + +void CAI_Squad::ScriptSetSquadData( int iSlot, const char *data ) +{ + SetSquadData( iSlot, data ); +} + +const char *CAI_Squad::ScriptGetSquadData( int iSlot ) +{ + const char *data; + GetSquadData( iSlot, &data ); + return data; +} +#endif + //============================================================================= diff --git a/sp/src/game/server/ai_squad.h b/sp/src/game/server/ai_squad.h index 846e9a11..9604d1f0 100644 --- a/sp/src/game/server/ai_squad.h +++ b/sp/src/game/server/ai_squad.h @@ -52,6 +52,14 @@ public: void DeleteSquad( CAI_Squad *pSquad ); void DeleteAllSquads(void); +#ifdef MAPBASE_VSCRIPT + HSCRIPT ScriptGetFirstSquad(); + HSCRIPT ScriptGetNextSquad( HSCRIPT hStart ); + + HSCRIPT ScriptFindSquad( const char *squadName ); + HSCRIPT ScriptFindCreateSquad( const char *squadName ); +#endif + private: CAI_Squad * m_pSquads; // A linked list of all squads @@ -152,6 +160,36 @@ private: void VacateSlot( CBaseEntity *pEnemy, int i ); bool IsSlotOccupied( CBaseEntity *pEnemy, int i ) const; +#ifdef MAPBASE_VSCRIPT + // Functions tailored specifically for VScript. + ALLOW_SCRIPT_ACCESS(); +private: + + HSCRIPT ScriptGetFirstMember( bool bIgnoreSilentMembers ); + HSCRIPT ScriptGetMember( int iIndex ); + HSCRIPT ScriptGetAnyMember(); + //int ScriptNumMembers( bool bIgnoreSilentMembers ); + int ScriptGetSquadIndex( HSCRIPT hNPC ); + + void ScriptUpdateEnemyMemory( HSCRIPT hUpdater, HSCRIPT hEnemy, const Vector &position ); + + HSCRIPT ScriptSquadMemberInRange( const Vector &vecLocation, float flDist ); + HSCRIPT ScriptNearestSquadMember( HSCRIPT hMember ); + int ScriptGetVisibleSquadMembers( HSCRIPT hMember ); + HSCRIPT ScriptGetSquadMemberNearestTo( const Vector &vecLocation ); + bool ScriptIsMember( HSCRIPT hMember ); + bool ScriptIsLeader( HSCRIPT hLeader ); + HSCRIPT ScriptGetLeader( void ); + + void ScriptAddToSquad( HSCRIPT hNPC ); + void ScriptRemoveFromSquad( HSCRIPT hNPC ); + + bool ScriptIsSilentMember( HSCRIPT hNPC ); + + void ScriptSetSquadData( int iSlot, const char *data ); + const char *ScriptGetSquadData( int iSlot ); +#endif + private: friend class CAI_SaveRestoreBlockHandler; friend class CAI_SquadManager; diff --git a/sp/src/game/server/baseanimating.cpp b/sp/src/game/server/baseanimating.cpp index 3daeeb73..0d6055bb 100644 --- a/sp/src/game/server/baseanimating.cpp +++ b/sp/src/game/server/baseanimating.cpp @@ -32,9 +32,6 @@ #include "gib.h" #include "CRagdollMagnet.h" #endif -#ifdef MAPBASE_VSCRIPT -#include "mapbase/vscript_funcs_math.h" -#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -2205,7 +2202,7 @@ HSCRIPT CBaseAnimating::ScriptGetAttachmentMatrix( int iAttachment ) static matrix3x4_t matrix; CBaseAnimating::GetAttachment( iAttachment, matrix ); - return ScriptCreateMatrixInstance( matrix ); + return g_pScriptVM->RegisterInstance( &matrix ); } float CBaseAnimating::ScriptGetPoseParameter( const char* szName ) @@ -2233,7 +2230,7 @@ void CBaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform ) if (hTransform == NULL) return; - GetBoneTransform( iBone, *ToMatrix3x4( hTransform ) ); + GetBoneTransform( iBone, *HScriptToClass( hTransform ) ); } //----------------------------------------------------------------------------- @@ -2250,12 +2247,9 @@ HSCRIPT CBaseAnimating::ScriptGetSequenceKeyValues( int iSequence ) if ( pSeqKeyValues ) { // UNDONE: how does destructor get called on this - m_pScriptModelKeyValues = new CScriptKeyValues( pSeqKeyValues ); + m_pScriptModelKeyValues = hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pSeqKeyValues, true ); // UNDONE: who calls ReleaseInstance on this??? Does name need to be unique??? - - // Allow VScript to delete this when the instance is removed. - hScript = g_pScriptVM->RegisterInstance( m_pScriptModelKeyValues, true ); } return hScript; diff --git a/sp/src/game/server/basecombatcharacter.cpp b/sp/src/game/server/basecombatcharacter.cpp index 6b53d451..1241e738 100644 --- a/sp/src/game/server/basecombatcharacter.cpp +++ b/sp/src/game/server/basecombatcharacter.cpp @@ -158,6 +158,7 @@ BEGIN_ENT_SCRIPTDESC( CBaseCombatCharacter, CBaseFlex, "The base class shared by DEFINE_SCRIPTFUNC_NAMED( GetScriptWeaponIndex, "GetWeapon", "Get a specific weapon in the character's inventory." ) DEFINE_SCRIPTFUNC_NAMED( GetScriptWeaponByType, "FindWeapon", "Find a specific weapon in the character's inventory by its classname." ) DEFINE_SCRIPTFUNC_NAMED( GetScriptAllWeapons, "GetAllWeapons", "Get the character's weapon inventory." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetCurrentWeaponProficiency, "GetCurrentWeaponProficiency", "Get the character's current proficiency (accuracy) with their current weapon." ) DEFINE_SCRIPTFUNC_NAMED( Weapon_ShootPosition, "ShootPosition", "Get the character's shoot position." ) DEFINE_SCRIPTFUNC_NAMED( Weapon_DropAll, "DropAllWeapons", "Make the character drop all of its weapons." ) @@ -166,6 +167,10 @@ BEGIN_ENT_SCRIPTDESC( CBaseCombatCharacter, CBaseFlex, "The base class shared by DEFINE_SCRIPTFUNC_NAMED( ScriptGetAmmoCount, "GetAmmoCount", "Get the ammo count of the specified ammo type." ) DEFINE_SCRIPTFUNC_NAMED( ScriptSetAmmoCount, "SetAmmoCount", "Set the ammo count of the specified ammo type." ) + DEFINE_SCRIPTFUNC( DoMuzzleFlash, "Does a muzzle flash." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttackSpread, "GetAttackSpread", "Get the attack spread." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetSpreadBias, "GetSpreadBias", "Get the spread bias." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptRelationType, "GetRelationship", "Get a character's relationship to a specific entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptRelationPriority, "GetRelationPriority", "Get a character's relationship priority for a specific entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptSetRelationship, "SetRelationship", "Set a character's relationship with a specific entity." ) @@ -1704,6 +1709,25 @@ Killed */ void CBaseCombatCharacter::Event_Killed( const CTakeDamageInfo &info ) { +#ifdef MAPBASE_VSCRIPT + if (m_ScriptScope.IsInitialized() && g_Hook_OnDeath.CanRunInScope( m_ScriptScope )) + { + HSCRIPT hInfo = g_pScriptVM->RegisterInstance( const_cast(&info) ); + + // info + ScriptVariant_t functionReturn; + ScriptVariant_t args[] = { ScriptVariant_t( hInfo ) }; + if ( g_Hook_OnDeath.Call( m_ScriptScope, &functionReturn, args ) && (functionReturn.m_type == FIELD_BOOLEAN && functionReturn.m_bool == false) ) + { + // Make this entity cheat death + g_pScriptVM->RemoveInstance( hInfo ); + return; + } + + g_pScriptVM->RemoveInstance( hInfo ); + } +#endif + extern ConVar npc_vphysics; // Advance life state to dying @@ -4437,6 +4461,37 @@ void CBaseCombatCharacter::ScriptSetAmmoCount( int iType, int iCount ) return SetAmmoCount( iCount, iType ); } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +const Vector& CBaseCombatCharacter::ScriptGetAttackSpread( HSCRIPT hWeapon, HSCRIPT hTarget ) +{ + CBaseEntity *pWeapon = ToEnt( hWeapon ); + if (!pWeapon || !pWeapon->IsBaseCombatWeapon()) + { + Warning( "GetAttackSpread: %s is not a valid weapon\n", pWeapon ? pWeapon->GetDebugName() : "Null entity" ); + return vec3_origin; + } + + // TODO: Make this a simple non-reference Vector? + static Vector vec; + vec = GetAttackSpread( pWeapon->MyCombatWeaponPointer(), ToEnt( hTarget ) ); + return vec; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +float CBaseCombatCharacter::ScriptGetSpreadBias( HSCRIPT hWeapon, HSCRIPT hTarget ) +{ + CBaseEntity *pWeapon = ToEnt( hWeapon ); + if (!pWeapon || !pWeapon->IsBaseCombatWeapon()) + { + Warning( "GetSpreadBias: %s is not a valid weapon\n", pWeapon ? pWeapon->GetDebugName() : "Null entity" ); + return 1.0f; + } + + return GetSpreadBias( pWeapon->MyCombatWeaponPointer(), ToEnt( hTarget ) ); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- int CBaseCombatCharacter::ScriptRelationType( HSCRIPT pTarget ) diff --git a/sp/src/game/server/basecombatcharacter.h b/sp/src/game/server/basecombatcharacter.h index e5d3a3f4..9c4e2fca 100644 --- a/sp/src/game/server/basecombatcharacter.h +++ b/sp/src/game/server/basecombatcharacter.h @@ -414,17 +414,21 @@ public: virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ); virtual void DoMuzzleFlash(); -#ifdef MAPBASE_VSCRIPT // DO NOT COMMIT; WAIT UNTIL FULL MERGE (5/15/2020) +#ifdef MAPBASE_VSCRIPT HSCRIPT GetScriptActiveWeapon(); HSCRIPT GetScriptWeaponIndex( int i ); HSCRIPT GetScriptWeaponByType( const char *pszWeapon, int iSubType = 0 ); void GetScriptAllWeapons( HSCRIPT hTable ); + int ScriptGetCurrentWeaponProficiency() { return GetCurrentWeaponProficiency(); } void ScriptEquipWeapon( HSCRIPT hWeapon ); int ScriptGetAmmoCount( int iType ) const; void ScriptSetAmmoCount( int iType, int iCount ); + const Vector& ScriptGetAttackSpread( HSCRIPT hWeapon, HSCRIPT hTarget ); + float ScriptGetSpreadBias( HSCRIPT hWeapon, HSCRIPT hTarget ); + int ScriptRelationType( HSCRIPT pTarget ); int ScriptRelationPriority( HSCRIPT pTarget ); void ScriptSetRelationship( HSCRIPT pTarget, int disposition, int priority ); diff --git a/sp/src/game/server/baseentity.cpp b/sp/src/game/server/baseentity.cpp index ceeb625f..cd21794c 100644 --- a/sp/src/game/server/baseentity.cpp +++ b/sp/src/game/server/baseentity.cpp @@ -66,9 +66,6 @@ #include "mapbase/matchers.h" #include "mapbase/datadesc_mod.h" #endif -#ifdef MAPBASE_VSCRIPT -#include "mapbase/vscript_funcs_math.h" -#endif #if defined( TF_DLL ) #include "tf_gamerules.h" @@ -626,6 +623,18 @@ CBaseEntity *CBaseEntity::GetFollowedEntity() return GetMoveParent(); } +#ifdef MAPBASE_VSCRIPT +void CBaseEntity::ScriptFollowEntity( HSCRIPT hBaseEntity, bool bBoneMerge ) +{ + FollowEntity( ToEnt( hBaseEntity ), bBoneMerge ); +} + +HSCRIPT CBaseEntity::ScriptGetFollowedEntity() +{ + return ToHScript( GetFollowedEntity() ); +} +#endif + void CBaseEntity::SetClassname( const char *className ) { m_iClassname = AllocPooledString( className ); @@ -1717,6 +1726,25 @@ int CBaseEntity::VPhysicsTakeDamage( const CTakeDamageInfo &info ) // Character killed (only fired once) void CBaseEntity::Event_Killed( const CTakeDamageInfo &info ) { +#ifdef MAPBASE_VSCRIPT + if (m_ScriptScope.IsInitialized() && g_Hook_OnDeath.CanRunInScope( m_ScriptScope )) + { + HSCRIPT hInfo = g_pScriptVM->RegisterInstance( const_cast(&info) ); + + // info + ScriptVariant_t functionReturn; + ScriptVariant_t args[] = { ScriptVariant_t( hInfo ) }; + if ( g_Hook_OnDeath.Call( m_ScriptScope, &functionReturn, args ) && (functionReturn.m_type == FIELD_BOOLEAN && functionReturn.m_bool == false) ) + { + // Make this entity cheat death + g_pScriptVM->RemoveInstance( hInfo ); + return; + } + + g_pScriptVM->RemoveInstance( hInfo ); + } +#endif + if( info.GetAttacker() ) { info.GetAttacker()->Event_KilledOther(this, info); @@ -2181,6 +2209,13 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity ) END_DATADESC() +#ifdef MAPBASE_VSCRIPT +ScriptHook_t CBaseEntity::g_Hook_UpdateOnRemove; +ScriptHook_t CBaseEntity::g_Hook_VPhysicsCollision; +ScriptHook_t CBaseEntity::g_Hook_FireBullets; +ScriptHook_t CBaseEntity::g_Hook_OnDeath; +#endif + BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" ) DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper ) DEFINE_SCRIPTFUNC_NAMED( ConnectOutputToScript, "ConnectOutput", "Adds an I/O connection that will call the named function when the specified output fires" ) @@ -2294,6 +2329,11 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" DEFINE_SCRIPTFUNC_NAMED( ScriptGetContext, "GetContext", "Get a response context value" ) DEFINE_SCRIPTFUNC_NAMED( ScriptAddContext, "AddContext", "Add a response context value" ) + DEFINE_SCRIPTFUNC_NAMED( ScriptFollowEntity, "FollowEntity", "Begin following the specified entity. This makes this entity non-solid, parents it to the target entity, and teleports it to the specified entity's origin. The second parameter is whether or not to use bonemerging while following." ) + DEFINE_SCRIPTFUNC( StopFollowingEntity, "Stops following an entity if we're following one." ) + DEFINE_SCRIPTFUNC( IsFollowingEntity, "Returns true if this entity is following another entity." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetFollowedEntity, "GetFollowedEntity", "Get the entity we're following." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptClassify, "Classify", "Get Class_T class ID" ) DEFINE_SCRIPTFUNC_NAMED( ScriptAcceptInput, "AcceptInput", "" ) @@ -2395,6 +2435,29 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" DEFINE_SCRIPTFUNC_NAMED( ScriptStopThinkFunction, "StopThinkFunction", "" ) DEFINE_SCRIPTFUNC_NAMED( ScriptSetThink, "SetThink", "" ) DEFINE_SCRIPTFUNC_NAMED( ScriptStopThink, "StopThink", "" ) + + // + // Hooks + // + DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." ) + + BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_VPhysicsCollision, "VPhysicsCollision", FIELD_VOID, "Called for every single VPhysics-related collision experienced by this entity." ) + DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "speed", FIELD_FLOAT ) + DEFINE_SCRIPTHOOK_PARAM( "point", FIELD_VECTOR ) + DEFINE_SCRIPTHOOK_PARAM( "normal", FIELD_VECTOR ) + END_SCRIPTHOOK() + + BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_FireBullets, "FireBullets", FIELD_VOID, "Called for every single VPhysics-related collision experienced by this entity." ) + DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "speed", FIELD_FLOAT ) + DEFINE_SCRIPTHOOK_PARAM( "point", FIELD_VECTOR ) + DEFINE_SCRIPTHOOK_PARAM( "normal", FIELD_VECTOR ) + END_SCRIPTHOOK() + + BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnDeath, "OnDeath", FIELD_BOOLEAN, "Called when the entity dies (Event_Killed). Returning false makes the entity cancel death, although this could have unforeseen consequences. For hooking any damage instead of just death, see filter_script and PassesFinalDamageFilter." ) + DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT ) + END_SCRIPTHOOK() #endif END_SCRIPTDESC(); @@ -2502,10 +2565,9 @@ void CBaseEntity::UpdateOnRemove( void ) if ( m_hScriptInstance ) { #ifdef MAPBASE_VSCRIPT - HSCRIPT hFunc = LookupScriptFunction("UpdateOnRemove"); - if ( hFunc ) + if (m_ScriptScope.IsInitialized()) { - CallScriptFunctionHandle( hFunc, NULL ); + g_Hook_UpdateOnRemove.Call( m_ScriptScope, NULL, NULL ); } #endif // MAPBASE_VSCRIPT @@ -3109,26 +3171,17 @@ void CBaseEntity::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; #ifdef MAPBASE_VSCRIPT - if (HSCRIPT hFunc = LookupScriptFunction("VPhysicsCollision")) + if (m_ScriptScope.IsInitialized() && g_Hook_VPhysicsCollision.CanRunInScope(m_ScriptScope)) { - // TODO: Unique class for collision events - g_pScriptVM->SetValue( "entity", ScriptVariant_t( pHitEntity->GetScriptInstance() ) ); - g_pScriptVM->SetValue( "speed", pEvent->collisionSpeed ); - Vector vecContactPoint; pEvent->pInternalData->GetContactPoint( vecContactPoint ); - g_pScriptVM->SetValue( "point", vecContactPoint ); Vector vecSurfaceNormal; pEvent->pInternalData->GetSurfaceNormal( vecSurfaceNormal ); - g_pScriptVM->SetValue( "normal", vecSurfaceNormal ); - CallScriptFunctionHandle( hFunc, NULL ); - - g_pScriptVM->ClearValue( "entity" ); - g_pScriptVM->ClearValue( "speed" ); - g_pScriptVM->ClearValue( "point" ); - g_pScriptVM->ClearValue( "normal" ); + // entity, speed, point, normal + ScriptVariant_t args[] = { ScriptVariant_t( pHitEntity->GetScriptInstance() ), pEvent->collisionSpeed, vecContactPoint, vecSurfaceNormal }; + g_Hook_VPhysicsCollision.Call( m_ScriptScope, NULL, args ); } #endif @@ -4454,7 +4507,7 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, // mapper debug message #ifdef MAPBASE - ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iName.Get()) : "", GetDebugName(), szInputName, Value.String() ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iName.Get()) : "", GetDebugName(), szInputName, Value.String() ); #else DevMsg( 2, "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iName.Get()) : "", GetDebugName(), szInputName, Value.String() ); #endif @@ -4591,7 +4644,7 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, } #ifdef MAPBASE - ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName() ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName() ); #else DevMsg( 2, "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName()/*,", from (%s,%s)" STRING(pCaller->m_iClassname), STRING(pCaller->m_iName.Get())*/ ); #endif @@ -9805,7 +9858,11 @@ void CBaseEntity::RunVScripts() for (int i = 0; i < szScripts.Count(); i++) { +#ifdef MAPBASE + CGMsg( 0, CON_GROUP_VSCRIPT, "%s executing script: %s\n", GetDebugName(), szScripts[i] ); +#else Log( "%s executing script: %s\n", GetDebugName(), szScripts[i]); +#endif RunScriptFile(szScripts[i], IsWorld()); @@ -9916,14 +9973,15 @@ HSCRIPT CBaseEntity::ScriptGetModelKeyValues( void ) if ( pModelKeyValues->LoadFromBuffer( pszModelName, pBuffer ) ) { // UNDONE: how does destructor get called on this +#ifdef MAPBASE_VSCRIPT + m_pScriptModelKeyValues = hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pModelKeyValues, true ); // Allow VScript to delete this when the instance is removed. +#else m_pScriptModelKeyValues = new CScriptKeyValues( pModelKeyValues ); +#endif // UNDONE: who calls ReleaseInstance on this??? Does name need to be unique??? -#ifdef MAPBASE_VSCRIPT - // Allow VScript to delete this when the instance is removed. - hScript = g_pScriptVM->RegisterInstance( m_pScriptModelKeyValues, true ); -#else +#ifndef MAPBASE_VSCRIPT hScript = g_pScriptVM->RegisterInstance( m_pScriptModelKeyValues ); #endif @@ -10073,7 +10131,7 @@ void CBaseEntity::ScriptSetColor( int r, int g, int b ) //----------------------------------------------------------------------------- HSCRIPT CBaseEntity::ScriptEntityToWorldTransform( void ) { - return ScriptCreateMatrixInstance( EntityToWorldTransform() ); + return g_pScriptVM->RegisterInstance( &EntityToWorldTransform() ); } //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/baseentity.h b/sp/src/game/server/baseentity.h index 98fe9fe1..5a0227c7 100644 --- a/sp/src/game/server/baseentity.h +++ b/sp/src/game/server/baseentity.h @@ -554,6 +554,11 @@ public: bool IsFollowingEntity(); CBaseEntity *GetFollowedEntity(); +#ifdef MAPBASE_VSCRIPT + void ScriptFollowEntity( HSCRIPT hBaseEntity, bool bBoneMerge ); + HSCRIPT ScriptGetFollowedEntity(); +#endif + // initialization virtual void Spawn( void ); virtual void Precache( void ) {} @@ -2084,6 +2089,11 @@ public: int ScriptGetMoveType() { return GetMoveType(); } void ScriptSetMoveType( int iMoveType ) { SetMoveType( (MoveType_t)iMoveType ); } + + static ScriptHook_t g_Hook_UpdateOnRemove; + static ScriptHook_t g_Hook_VPhysicsCollision; + static ScriptHook_t g_Hook_FireBullets; + static ScriptHook_t g_Hook_OnDeath; #endif string_t m_iszVScripts; @@ -2091,7 +2101,11 @@ public: CScriptScope m_ScriptScope; HSCRIPT m_hScriptInstance; string_t m_iszScriptId; +#ifdef MAPBASE_VSCRIPT + HSCRIPT m_pScriptModelKeyValues; +#else CScriptKeyValues* m_pScriptModelKeyValues; +#endif }; // Send tables exposed in this module. diff --git a/sp/src/game/server/baseflex.cpp b/sp/src/game/server/baseflex.cpp index 006b85e8..d908b15c 100644 --- a/sp/src/game/server/baseflex.cpp +++ b/sp/src/game/server/baseflex.cpp @@ -782,6 +782,58 @@ bool CBaseFlex::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CCh case CChoreoEvent::EXPRESSION: // These are handled client-side return true; + +#ifdef MAPBASE + case CChoreoEvent::GENERIC: + { + // This is handled in CBaseFlex so that any flex entity--including players--could use this text. + if (stricmp(event->GetParameters(), "AI_GAMETEXT") == 0) + { + // game_text-based lines, for placeholders + if ( event->GetParameters2() ) + { + info->m_nType = 12; // SCENE_AI_GAMETEXT + + hudtextparms_t textParams; + textParams.holdTime = event->GetDuration(); + textParams.fadeinTime = 0.5f; + textParams.fadeoutTime = 0.5f; + + if ( GetGameTextSpeechParams( textParams ) ) + { + CRecipientFilter filter; + filter.AddAllPlayers(); + filter.MakeReliable(); + + UserMessageBegin( filter, "HudMsg" ); + WRITE_BYTE ( textParams.channel & 0xFF ); + WRITE_FLOAT( textParams.x ); + WRITE_FLOAT( textParams.y ); + WRITE_BYTE ( textParams.r1 ); + WRITE_BYTE ( textParams.g1 ); + WRITE_BYTE ( textParams.b1 ); + WRITE_BYTE ( textParams.a1 ); + WRITE_BYTE ( textParams.r2 ); + WRITE_BYTE ( textParams.g2 ); + WRITE_BYTE ( textParams.b2 ); + WRITE_BYTE ( textParams.a2 ); + WRITE_BYTE ( textParams.effect ); + WRITE_FLOAT( textParams.fadeinTime ); + WRITE_FLOAT( textParams.fadeoutTime ); + WRITE_FLOAT( textParams.holdTime ); + WRITE_FLOAT( textParams.fxTime ); + WRITE_STRING( event->GetParameters2() ); + WRITE_STRING( "" ); // No custom font + WRITE_BYTE ( Q_strlen( event->GetParameters2() ) ); + MessageEnd(); + } + return true; + } + } + + return false; + } +#endif } return false; @@ -2033,6 +2085,70 @@ float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname ) } #endif +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: Parameters for scene event AI_GameText +//----------------------------------------------------------------------------- +bool CBaseFlex::GetGameTextSpeechParams( hudtextparms_t ¶ms ) +{ + params.channel = 3; + params.x = -1; + params.y = 0.6; + params.effect = 0; + + params.r1 = 255; + params.g1 = 255; + params.b1 = 255; + + ScriptVariant_t varTable; + if (g_pScriptVM->GetValue(m_ScriptScope, "m_GameTextSpeechParams", &varTable) && varTable.m_type == FIELD_HSCRIPT) + { + int nIterator = -1; + ScriptVariant_t varKey, varValue; + while ((nIterator = g_pScriptVM->GetKeyValue( varTable.m_hScript, nIterator, &varKey, &varValue )) != -1) + { + if (FStrEq( varKey.m_pszString, "color" )) + { + params.r1 = varValue.m_pVector->x; + params.g1 = varValue.m_pVector->y; + params.b1 = varValue.m_pVector->z; + } + else if (FStrEq( varKey.m_pszString, "color2" )) + { + params.r2 = varValue.m_pVector->x; + params.g2 = varValue.m_pVector->y; + params.b2 = varValue.m_pVector->z; + } + else if (FStrEq( varKey.m_pszString, "channel" )) + { + params.channel = varValue.m_int; + } + else if (FStrEq( varKey.m_pszString, "x" )) + { + params.x = varValue.m_float; + } + else if (FStrEq( varKey.m_pszString, "y" )) + { + params.y = varValue.m_float; + } + else if (FStrEq( varKey.m_pszString, "effect" )) + { + params.effect = varValue.m_int; + } + else if (FStrEq( varKey.m_pszString, "fxtime" )) + { + params.fxTime = varValue.m_float; + } + + g_pScriptVM->ReleaseValue( varKey ); + g_pScriptVM->ReleaseValue( varValue ); + } + } + + return true; +} +#endif + //-------------------------------------------------------------------------------------------------- // Returns the script instance of the scene entity associated with our oldest ("top level") scene event diff --git a/sp/src/game/server/baseflex.h b/sp/src/game/server/baseflex.h index 838ba89e..215b13f5 100644 --- a/sp/src/game/server/baseflex.h +++ b/sp/src/game/server/baseflex.h @@ -138,6 +138,10 @@ public: virtual int GetSpecialDSP( void ) { return 0; } +#ifdef MAPBASE + virtual bool GetGameTextSpeechParams( hudtextparms_t ¶ms ); +#endif + protected: // For handling .vfe files // Search list, or add if not in list diff --git a/sp/src/game/server/cbase.cpp b/sp/src/game/server/cbase.cpp index 57e465f8..11365611 100644 --- a/sp/src/game/server/cbase.cpp +++ b/sp/src/game/server/cbase.cpp @@ -303,7 +303,7 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa STRING(ev->m_iParameter) ); #ifdef MAPBASE - ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "%s", szBuffer ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); #else DevMsg( 2, "%s", szBuffer ); #endif @@ -326,7 +326,7 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa STRING(ev->m_iParameter) ); #ifdef MAPBASE - ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "%s", szBuffer ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); #else DevMsg( 2, "%s", szBuffer ); #endif @@ -352,7 +352,7 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa Q_snprintf( szBuffer, sizeof(szBuffer), "Removing from action list: (%s,%s) -> (%s,%s)\n", pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput)); #ifdef MAPBASE - ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "%s", szBuffer ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); #else DevMsg( 2, "%s", szBuffer ); #endif @@ -1104,7 +1104,7 @@ void CEventQueue::ServiceEvents( void ) char szBuffer[256]; Q_snprintf( szBuffer, sizeof(szBuffer), "unhandled input: (%s) -> (%s), from (%s,%s); target entity not found\n", STRING(pe->m_iTargetInput), STRING(pe->m_iTarget), pClass, pName ); #ifdef MAPBASE - ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "%s", szBuffer ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); #else DevMsg( 2, "%s", szBuffer ); #endif diff --git a/sp/src/game/server/cbase.h b/sp/src/game/server/cbase.h index e2a9788d..290e3b25 100644 --- a/sp/src/game/server/cbase.h +++ b/sp/src/game/server/cbase.h @@ -80,6 +80,9 @@ #include "baseentity_shared.h" #include "basetoggle.h" #include "igameevents.h" +#ifdef MAPBASE +#include "tier1/mapbase_con_groups.h" +#endif // saverestore.h declarations class ISave; @@ -151,8 +154,4 @@ class CSound; #include "ndebugoverlay.h" #include "recipientfilter.h" -#ifdef MAPBASE -#define CON_COLOR_DEV_VERBOSE 192,128,192,255 -#endif - #endif // CBASE_H diff --git a/sp/src/game/server/effects.cpp b/sp/src/game/server/effects.cpp index 070d7987..7b07e157 100644 --- a/sp/src/game/server/effects.cpp +++ b/sp/src/game/server/effects.cpp @@ -1512,6 +1512,7 @@ public: DECLARE_SERVERCLASS(); CPrecipitation(); + int UpdateTransmitState(); void Spawn( void ); CNetworkVar( PrecipitationType_t, m_nPrecipType ); @@ -1525,7 +1526,10 @@ END_DATADESC() // Just send the normal entity crap IMPLEMENT_SERVERCLASS_ST( CPrecipitation, DT_Precipitation) - SendPropInt( SENDINFO( m_nPrecipType ), Q_log2( NUM_PRECIPITATION_TYPES ) + 1, SPROP_UNSIGNED ) + SendPropInt( SENDINFO( m_nPrecipType ), Q_log2( NUM_PRECIPITATION_TYPES ) + 1, SPROP_UNSIGNED ), +#ifdef MAPBASE + SendPropInt( SENDINFO( m_spawnflags ), 2, SPROP_UNSIGNED ), +#endif END_SEND_TABLE() @@ -1534,17 +1538,35 @@ CPrecipitation::CPrecipitation() m_nPrecipType = PRECIPITATION_TYPE_RAIN; // default to rain. } +int CPrecipitation::UpdateTransmitState() +{ + return SetTransmitState( FL_EDICT_ALWAYS ); +} + void CPrecipitation::Spawn( void ) { + //SetTransmitState( FL_EDICT_ALWAYS ); + SetTransmitState( FL_EDICT_PVSCHECK ); + PrecacheMaterial( "effects/fleck_ash1" ); PrecacheMaterial( "effects/fleck_ash2" ); PrecacheMaterial( "effects/fleck_ash3" ); PrecacheMaterial( "effects/ember_swirling001" ); Precache(); - SetSolid( SOLID_NONE ); // Remove model & collisions SetMoveType( MOVETYPE_NONE ); SetModel( STRING( GetModelName() ) ); // Set size + if ( IsParticleRainType( m_nPrecipType ) ) + { + SetSolid( SOLID_VPHYSICS ); + AddSolidFlags( FSOLID_NOT_SOLID ); + AddSolidFlags( FSOLID_FORCE_WORLD_ALIGNED ); + VPhysicsInitStatic(); + } + else + { + SetSolid( SOLID_NONE ); // Remove model & collisions + } // Default to rain. if ( m_nPrecipType < 0 || m_nPrecipType > NUM_PRECIPITATION_TYPES ) diff --git a/sp/src/game/server/filters.cpp b/sp/src/game/server/filters.cpp index 2dc49ad3..8b7dcfc9 100644 --- a/sp/src/game/server/filters.cpp +++ b/sp/src/game/server/filters.cpp @@ -47,9 +47,9 @@ END_DATADESC() #ifdef MAPBASE_VSCRIPT BEGIN_ENT_SCRIPTDESC( CBaseFilter, CBaseEntity, "All entities which could be used as filters." ) - DEFINE_SCRIPTFUNC_NAMED( ScriptPassesFilter, "PassesFilter", "Check if the given caller and entity pass the filter." ) - DEFINE_SCRIPTFUNC_NAMED( ScriptPassesDamageFilter, "PassesDamageFilter", "Check if the given caller and damage info pass the damage filter." ) - DEFINE_SCRIPTFUNC_NAMED( ScriptPassesFinalDamageFilter, "PassesFinalDamageFilter", "Used by filter_damage_redirect to distinguish between standalone filter calls and actually damaging an entity. Returns true if there's no unique behavior." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptPassesFilter, "PassesFilter", "Check if the given caller and entity pass the filter. The caller is the one who requests the filter result; For example, the entity being damaged when using this as a damage filter." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptPassesDamageFilter, "PassesDamageFilter", "Check if the given caller and damage info pass the damage filter, with the second parameter being a CTakeDamageInfo instance. The caller is the one who requests the filter result; For example, the entity being damaged when using this as a damage filter." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptPassesFinalDamageFilter, "PassesFinalDamageFilter", "Used by filter_damage_redirect to distinguish between standalone filter calls and actually damaging an entity. Returns true if there's no unique behavior. Parameters are identical to PassesDamageFilter." ) DEFINE_SCRIPTFUNC_NAMED( ScriptBloodAllowed, "BloodAllowed", "Check if the given caller and damage info allow for the production of blood." ) DEFINE_SCRIPTFUNC_NAMED( ScriptDamageMod, "DamageMod", "Mods the damage info with the given caller." ) @@ -2138,6 +2138,12 @@ END_DATADESC() #endif #ifdef MAPBASE_VSCRIPT +ScriptHook_t g_Hook_PassesFilter; +ScriptHook_t g_Hook_PassesDamageFilter; +ScriptHook_t g_Hook_PassesFinalDamageFilter; +ScriptHook_t g_Hook_BloodAllowed; +ScriptHook_t g_Hook_DamageMod; + // ################################################################### // > CFilterScript // ################################################################### @@ -2145,24 +2151,21 @@ class CFilterScript : public CBaseFilter { DECLARE_CLASS( CFilterScript, CBaseFilter ); DECLARE_DATADESC(); + DECLARE_ENT_SCRIPTDESC(); public: bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) { if (m_ScriptScope.IsInitialized()) { - g_pScriptVM->SetValue( "caller", (pCaller) ? ScriptVariant_t( pCaller->GetScriptInstance() ) : SCRIPT_VARIANT_NULL ); - g_pScriptVM->SetValue( "activator", (pEntity) ? ScriptVariant_t( pEntity->GetScriptInstance() ) : SCRIPT_VARIANT_NULL ); - + // caller, activator ScriptVariant_t functionReturn; - if (!CallScriptFunction( "PassesFilter", &functionReturn )) + ScriptVariant_t args[] = { ToHScript( pCaller ), ToHScript( pEntity ) }; + if ( !g_Hook_PassesFilter.Call( m_ScriptScope, &functionReturn, args ) ) { - Warning("%s: No PassesFilter function\n", GetDebugName()); + Warning( "%s: No PassesFilter function\n", GetDebugName() ); } - g_pScriptVM->ClearValue( "caller" ); - g_pScriptVM->ClearValue( "activator" ); - return functionReturn.m_bool; } @@ -2176,21 +2179,18 @@ public: { HSCRIPT pInfo = g_pScriptVM->RegisterInstance( const_cast(&info) ); - g_pScriptVM->SetValue( "info", pInfo ); - g_pScriptVM->SetValue( "caller", (pCaller) ? ScriptVariant_t( pCaller->GetScriptInstance() ) : SCRIPT_VARIANT_NULL ); - + // caller, info ScriptVariant_t functionReturn; - if (!CallScriptFunction( "PassesDamageFilter", &functionReturn )) + ScriptVariant_t args[] = { ToHScript( pCaller ), pInfo }; + if ( !g_Hook_PassesDamageFilter.Call( m_ScriptScope, &functionReturn, args ) ) { // Fall back to main filter function + g_pScriptVM->RemoveInstance( pInfo ); return PassesFilterImpl( pCaller, info.GetAttacker() ); } g_pScriptVM->RemoveInstance( pInfo ); - g_pScriptVM->ClearValue( "info" ); - g_pScriptVM->ClearValue( "caller" ); - return functionReturn.m_bool; } @@ -2204,20 +2204,17 @@ public: { HSCRIPT pInfo = g_pScriptVM->RegisterInstance( const_cast(&info) ); - g_pScriptVM->SetValue( "info", pInfo ); - g_pScriptVM->SetValue( "caller", (pCaller) ? ScriptVariant_t( pCaller->GetScriptInstance() ) : SCRIPT_VARIANT_NULL ); - + // caller, info ScriptVariant_t functionReturn; - if (!CallScriptFunction( "PassesFinalDamageFilter", &functionReturn )) + ScriptVariant_t args[] = { ToHScript( pCaller ), pInfo }; + if ( !g_Hook_PassesFinalDamageFilter.Call( m_ScriptScope, &functionReturn, args ) ) { + g_pScriptVM->RemoveInstance( pInfo ); return BaseClass::PassesFinalDamageFilter( pCaller, info ); } g_pScriptVM->RemoveInstance( pInfo ); - g_pScriptVM->ClearValue( "info" ); - g_pScriptVM->ClearValue( "caller" ); - return functionReturn.m_bool; } @@ -2231,20 +2228,17 @@ public: { HSCRIPT pInfo = g_pScriptVM->RegisterInstance( const_cast(&info) ); - g_pScriptVM->SetValue( "info", pInfo ); - g_pScriptVM->SetValue( "caller", (pCaller) ? ScriptVariant_t( pCaller->GetScriptInstance() ) : SCRIPT_VARIANT_NULL ); - + // caller, info ScriptVariant_t functionReturn; - if (!CallScriptFunction( "BloodAllowed", &functionReturn )) + ScriptVariant_t args[] = { ToHScript( pCaller ), pInfo }; + if ( !g_Hook_BloodAllowed.Call( m_ScriptScope, &functionReturn, args ) ) { + g_pScriptVM->RemoveInstance( pInfo ); return BaseClass::BloodAllowed( pCaller, info ); } g_pScriptVM->RemoveInstance( pInfo ); - g_pScriptVM->ClearValue( "info" ); - g_pScriptVM->ClearValue( "caller" ); - return functionReturn.m_bool; } @@ -2258,20 +2252,17 @@ public: { HSCRIPT pInfo = g_pScriptVM->RegisterInstance( &info ); - g_pScriptVM->SetValue( "info", pInfo ); - g_pScriptVM->SetValue( "caller", (pCaller) ? ScriptVariant_t( pCaller->GetScriptInstance() ) : SCRIPT_VARIANT_NULL ); - + // caller, info ScriptVariant_t functionReturn; - if (!CallScriptFunction( "DamageMod", &functionReturn )) + ScriptVariant_t args[] = { ToHScript( pCaller ), pInfo }; + if ( !g_Hook_DamageMod.Call( m_ScriptScope, &functionReturn, args ) ) { + g_pScriptVM->RemoveInstance( pInfo ); return BaseClass::DamageMod( pCaller, info ); } g_pScriptVM->RemoveInstance( pInfo ); - g_pScriptVM->ClearValue( "info" ); - g_pScriptVM->ClearValue( "caller" ); - return functionReturn.m_bool; } @@ -2284,4 +2275,39 @@ LINK_ENTITY_TO_CLASS( filter_script, CFilterScript ); BEGIN_DATADESC( CFilterScript ) END_DATADESC() + +BEGIN_ENT_SCRIPTDESC( CFilterScript, CBaseFilter, "The filter_script entity which allows VScript functions to hook onto filter methods." ) + + // + // Hooks + // + + // The CFilterScript class is visible in the help string, so "A hook used by filter_script" is redundant, but these names are also + // used for functions in CBaseFilter. In order to reduce confusion, the description emphasizes that these are hooks. + BEGIN_SCRIPTHOOK( g_Hook_PassesFilter, "PassesFilter", FIELD_BOOLEAN, "A hook used by filter_script to determine what entities should pass it. Return true if the entity should pass or false if it should not. This hook is required for regular filtering." ) + DEFINE_SCRIPTHOOK_PARAM( "caller", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "activator", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + + BEGIN_SCRIPTHOOK( g_Hook_PassesDamageFilter, "PassesDamageFilter", FIELD_BOOLEAN, "A hook used by filter_script to determine what damage should pass it when it's being used as a damage filter. Return true if the info should pass or false if it should not. If this hook is not defined in a filter_script, damage filter requests will instead check PassesFilter with the attacker as the activator." ) + DEFINE_SCRIPTHOOK_PARAM( "caller", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + + BEGIN_SCRIPTHOOK( g_Hook_PassesFinalDamageFilter, "PassesFinalDamageFilter", FIELD_BOOLEAN, "A completely optional hook used by filter_script which only runs when the entity will take damage. This is different from PassesDamageFilter, which is sometimes used in cases where damage is not actually about to be taken. This also runs after a regular PassesDamageFilter check. Return true if the info should pass or false if it should not. If this hook is not defined, it will always return true." ) + DEFINE_SCRIPTHOOK_PARAM( "caller", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + + BEGIN_SCRIPTHOOK( g_Hook_BloodAllowed, "BloodAllowed", FIELD_BOOLEAN, "A completely optional hook used by filter_script to determine if a caller is allowed to emit blood after taking damage. Return true if blood should be allowed or false if it should not. If this hook is not defined, it will always return true." ) + DEFINE_SCRIPTHOOK_PARAM( "caller", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + + BEGIN_SCRIPTHOOK( g_Hook_DamageMod, "DamageMod", FIELD_BOOLEAN, "A completely optional hook used by filter_script to modify damage being taken by an entity. You are free to use CTakeDamageInfo functions on the damage info handle and it will change how the caller is damaged. Returning true or false currently has no effect on vanilla code, but you should generally return true if the damage info has been modified by your code and false if it was not. If this hook is not defined, it will always return false." ) + DEFINE_SCRIPTHOOK_PARAM( "caller", FIELD_HSCRIPT ) + DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + +END_SCRIPTDESC() #endif diff --git a/sp/src/game/server/fish.cpp b/sp/src/game/server/fish.cpp index e6620068..553c7659 100644 --- a/sp/src/game/server/fish.cpp +++ b/sp/src/game/server/fish.cpp @@ -540,6 +540,19 @@ BEGIN_DATADESC( CFishPool ) DEFINE_FIELD( m_isDormant, FIELD_BOOLEAN ), DEFINE_UTLVECTOR( m_fishes, FIELD_EHANDLE ), +#ifdef MAPBASE + DEFINE_INPUT( m_nSkin, FIELD_INTEGER, "skin" ), + + DEFINE_KEYFIELD( m_flLoudPanicRange, FIELD_FLOAT, "LoudPanicRange" ), + DEFINE_KEYFIELD( m_flQuietPanicRange, FIELD_FLOAT, "QuietPanicRange" ), + + DEFINE_INPUTFUNC( FIELD_VOID, "SpawnFish", InputSpawnFish ), + DEFINE_INPUTFUNC( FIELD_VECTOR, "PanicLoudFromPoint", InputPanicLoudFromPoint ), + DEFINE_INPUTFUNC( FIELD_VECTOR, "PanicQuietFromPoint", InputPanicQuietFromPoint ), + + DEFINE_OUTPUT( m_OnSpawnFish, "OnSpawnFish" ), +#endif + DEFINE_THINKFUNC( Update ), END_DATADESC() @@ -553,6 +566,14 @@ CFishPool::CFishPool( void ) m_swimDepth = 0.0f; m_isDormant = false; +#ifdef MAPBASE + m_nSkin = 0; + + // Original defaults + m_flLoudPanicRange = 500.0f; + m_flQuietPanicRange = 75.0f; +#endif + m_visTimer.Start( 0.5f ); ListenForGameEvent( "player_shoot" ); @@ -588,6 +609,10 @@ void CFishPool::Spawn() CHandle hFish; hFish.Set( fish ); m_fishes.AddToTail( hFish ); +#ifdef MAPBASE + fish->m_nSkin = m_nSkin; + m_OnSpawnFish.Set( hFish, fish, this ); +#endif } } } @@ -638,10 +663,14 @@ void CFishPool::FireGameEvent( IGameEvent *event ) CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); // the fish panic +#ifdef MAPBASE + float range = (Q_strcmp( "player_footstep", event->GetName() )) ? m_flLoudPanicRange : m_flQuietPanicRange; +#else const float loudRange = 500.0f; const float quietRange = 75.0f; float range = (Q_strcmp( "player_footstep", event->GetName() )) ? loudRange : quietRange; +#endif for( int i=0; iResetVisible(); } @@ -731,3 +769,63 @@ void CFishPool::Update( void ) } } +#ifdef MAPBASE +//------------------------------------------------------------------------------------------------------------- +/** + * Inputs + */ +void CFishPool::InputSpawnFish( inputdata_t &inputdata ) +{ + QAngle heading( 0.0f, RandomFloat( 0, 360.0f ), 0.0f ); + + CFish *fish = (CFish *)Create( "fish", GetAbsOrigin(), heading, this ); + fish->Initialize( this, m_fishes.Count() ); + + if (fish) + { + CHandle hFish; + hFish.Set( fish ); + m_fishes.AddToTail( hFish ); +#ifdef MAPBASE + m_OnSpawnFish.Set( hFish, fish, this ); +#endif + } +} + +void CFishPool::InputPanicLoudFromPoint( inputdata_t &inputdata ) +{ + // Make the fish panic from this point + Vector vecPoint; + inputdata.value.Vector3D( vecPoint ); + for( int i=0; iGetAbsOrigin()).IsLengthGreaterThan( m_flLoudPanicRange )) + { + // event too far away to care + continue; + } + + m_fishes[i]->Panic(); + } +} + +void CFishPool::InputPanicQuietFromPoint( inputdata_t &inputdata ) +{ + // Make the fish panic from this point + Vector vecPoint; + inputdata.value.Vector3D( vecPoint ); + for( int i=0; iGetAbsOrigin()).IsLengthGreaterThan( m_flQuietPanicRange )) + { + // event too far away to care + continue; + } + + m_fishes[i]->Panic(); + } +} +#endif + diff --git a/sp/src/game/server/fish.h b/sp/src/game/server/fish.h index 6eb7e64d..257bdbcd 100644 --- a/sp/src/game/server/fish.h +++ b/sp/src/game/server/fish.h @@ -109,6 +109,12 @@ public: float GetWaterLevel( void ) const; ///< return Z coordinate of water in world coords float GetMaxRange( void ) const; ///< return how far a fish is allowed to wander +#ifdef MAPBASE + void InputSpawnFish( inputdata_t &inputdata ); + void InputPanicLoudFromPoint( inputdata_t &inputdata ); + void InputPanicQuietFromPoint( inputdata_t &inputdata ); +#endif + private: int m_fishCount; ///< number of fish in the pool float m_maxRange; ///< how far a fish is allowed to wander @@ -120,6 +126,15 @@ private: CUtlVector< CHandle > m_fishes; ///< vector of all fish in this pool +#ifdef MAPBASE + int m_nSkin; // Sets the skin of spawned fish + + float m_flLoudPanicRange; + float m_flQuietPanicRange; + + COutputEHANDLE m_OnSpawnFish; +#endif + CountdownTimer m_visTimer; ///< for throttling line of sight checks between all fish }; diff --git a/sp/src/game/server/hl2/ai_behavior_police.cpp b/sp/src/game/server/hl2/ai_behavior_police.cpp index ea97ec9c..ffb8dd96 100644 --- a/sp/src/game/server/hl2/ai_behavior_police.cpp +++ b/sp/src/game/server/hl2/ai_behavior_police.cpp @@ -11,6 +11,9 @@ #include "ai_memory.h" #include "collisionutils.h" #include "npc_metropolice.h" +#ifdef MAPBASE +#include "npc_combine.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -133,6 +136,16 @@ void CAI_PolicingBehavior::HostSpeakSentence( const char *pSentence, SentencePri pSentences->Speak( pSentence, nSoundPriority, nCriteria ); #endif } +#ifdef MAPBASE + else if ( CNPC_Combine *pCombine = dynamic_cast(GetOuter()) ) + { + pCombine->SpeakIfAllowed( pSentence, nSoundPriority, nCriteria ); + } + else if ( GetOuter()->GetExpresser() ) + { + GetOuter()->GetExpresser()->Speak( pSentence ); + } +#endif } #ifdef METROPOLICE_USES_RESPONSE_SYSTEM @@ -148,6 +161,16 @@ void CAI_PolicingBehavior::HostSpeakSentence( const char *pSentence, const char { pCop->SpeakIfAllowed( pSentence, modifiers, nSoundPriority, nCriteria ); } +#ifdef MAPBASE + else if ( CNPC_Combine *pCombine = dynamic_cast(GetOuter()) ) + { + pCombine->SpeakIfAllowed( pSentence, modifiers, nSoundPriority, nCriteria ); + } + else if ( GetOuter()->GetExpresser() ) + { + GetOuter()->GetExpresser()->Speak( pSentence, modifiers ); + } +#endif } #endif @@ -195,6 +218,10 @@ void CAI_PolicingBehavior::GatherConditions( void ) // See if we need to knock out our target immediately if ( ShouldKnockOutTarget( pTarget ) ) { +#ifdef MAPBASE + // If this isn't actually an enemy of ours and we're already warning, don't set this condition + if (GetOuter()->IRelationType( m_hPoliceGoal->GetTarget() ) <= D_FR || !IsCurSchedule(SCHED_POLICE_WARN_TARGET, false)) +#endif SetCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ); } @@ -209,6 +236,10 @@ void CAI_PolicingBehavior::GatherConditions( void ) if ( flDistSqr < (m_hPoliceGoal->GetRadius()*m_hPoliceGoal->GetRadius()) ) { +#ifdef MAPBASE + // If this isn't actually an enemy of ours and we're already warning, don't set this condition + if (GetOuter()->IRelationType( m_hPoliceGoal->GetTarget() ) <= D_FR || !IsCurSchedule(SCHED_POLICE_WARN_TARGET, false)) +#endif SetCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ); } } @@ -263,6 +294,12 @@ int CAI_PolicingBehavior::TranslateSchedule( int scheduleType ) { if ( m_hPoliceGoal->ShouldRemainAtPost() && !MaintainGoalPosition() ) return BaseClass::TranslateSchedule( SCHED_COMBAT_FACE ); + +#ifdef MAPBASE + // If this isn't actually an enemy of ours, keep warning + if ( GetOuter()->IRelationType(m_hPoliceGoal->GetTarget()) > D_FR ) + return BaseClass::TranslateSchedule( SCHED_POLICE_WARN_TARGET ); +#endif } return BaseClass::TranslateSchedule( scheduleType ); @@ -359,7 +396,11 @@ void CAI_PolicingBehavior::StartTask( const Task_t *pTask ) if ( GetNavigator()->SetGoal( harassPos, pTask->flTaskData ) ) { +#ifdef MAPBASE + GetNavigator()->SetMovementActivity( GetOuter()->TranslateActivity(ACT_WALK_ANGRY) ); +#else GetNavigator()->SetMovementActivity( (Activity) ACT_WALK_ANGRY ); +#endif GetNavigator()->SetArrivalDirection( m_hPoliceGoal->GetTarget() ); TaskComplete(); } diff --git a/sp/src/game/server/hl2/hl2_player.cpp b/sp/src/game/server/hl2/hl2_player.cpp index 0378d80d..f249c3e6 100644 --- a/sp/src/game/server/hl2/hl2_player.cpp +++ b/sp/src/game/server/hl2/hl2_player.cpp @@ -116,6 +116,10 @@ ConVar autoaim_unlock_target( "autoaim_unlock_target", "0.8666" ); ConVar sv_stickysprint("sv_stickysprint", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX); +#ifdef MAPBASE +ConVar player_autoswitch_enabled( "player_autoswitch_enabled", "1", FCVAR_NONE, "This convar was added by Mapbase to toggle whether players automatically switch to their ''best'' weapon upon picking up ammo for it after it was dry." ); +#endif + #define FLASH_DRAIN_TIME 1.1111 // 100 units / 90 secs #define FLASH_CHARGE_TIME 50.0f // 100 units / 2 secs @@ -254,6 +258,7 @@ public: void InputGetAmmoOnWeapon( inputdata_t &inputdata ); void InputSetHandModel( inputdata_t &inputdata ); + void InputSetHandModelSkin( inputdata_t &inputdata ); void InputSetPlayerModel( inputdata_t &inputdata ); void InputSetPlayerDrawExternally( inputdata_t &inputdata ); @@ -1371,7 +1376,10 @@ void CHL2_Player::ResetAnimation( void ) void CHL2_Player::SetAnimation( PLAYER_ANIM playerAnim ) { if (!hl2_use_hl2dm_anims.GetBool()) + { + BaseClass::SetAnimation( playerAnim ); return; + } int animDesired; @@ -3252,6 +3260,15 @@ bool CHL2_Player::ShouldKeepLockedAutoaimTarget( EHANDLE hLockedTarget ) return true; } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool CHL2_Player::CanAutoSwitchToNextBestWeapon( CBaseCombatWeapon *pWeapon ) +{ + return player_autoswitch_enabled.GetBool(); +} +#endif + //----------------------------------------------------------------------------- // Purpose: // Input : iCount - @@ -3293,6 +3310,9 @@ int CHL2_Player::GiveAmmo( int nCount, int nAmmoIndex, bool bSuppressSound) if ( pWeapon && pWeapon->GetPrimaryAmmoType() == nAmmoIndex ) { +#ifdef MAPBASE + if (CanAutoSwitchToNextBestWeapon(pWeapon)) +#endif SwitchToNextBestWeapon(GetActiveWeapon()); } } @@ -4591,6 +4611,7 @@ BEGIN_DATADESC( CLogicPlayerProxy ) DEFINE_INPUTFUNC( FIELD_VOID, "RequestPlayerFlashBattery", InputRequestPlayerFlashBattery ), DEFINE_INPUTFUNC( FIELD_STRING, "GetAmmoOnWeapon", InputGetAmmoOnWeapon ), DEFINE_INPUTFUNC( FIELD_STRING, "SetHandModel", InputSetHandModel ), + DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelSkin", InputSetHandModelSkin ), DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerModel", InputSetPlayerModel ), DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawExternally", InputSetPlayerDrawExternally ), DEFINE_INPUT( m_MaxArmor, FIELD_INTEGER, "SetMaxInputArmor" ), @@ -5023,6 +5044,17 @@ void CLogicPlayerProxy::InputSetHandModel( inputdata_t &inputdata ) vm->SetModel(STRING(iszModel)); } +void CLogicPlayerProxy::InputSetHandModelSkin( inputdata_t &inputdata ) +{ + if (!m_hPlayer) + return; + + CBasePlayer *pPlayer = static_cast( m_hPlayer.Get() ); + CBaseViewModel *vm = pPlayer->GetViewModel(1); + if (vm) + vm->m_nSkin = inputdata.value.Int(); +} + void CLogicPlayerProxy::InputSetPlayerModel( inputdata_t &inputdata ) { if (!m_hPlayer) diff --git a/sp/src/game/server/hl2/hl2_player.h b/sp/src/game/server/hl2/hl2_player.h index 89dc16ba..84ae23b9 100644 --- a/sp/src/game/server/hl2/hl2_player.h +++ b/sp/src/game/server/hl2/hl2_player.h @@ -268,6 +268,10 @@ public: void SetLocatorTargetEntity( CBaseEntity *pEntity ) { m_hLocatorTargetEntity.Set( pEntity ); } +#ifdef MAPBASE + virtual bool CanAutoSwitchToNextBestWeapon( CBaseCombatWeapon *pWeapon ); +#endif + virtual int GiveAmmo( int nCount, int nAmmoIndex, bool bSuppressSound); virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); diff --git a/sp/src/game/server/hl2/npc_citizen17.cpp b/sp/src/game/server/hl2/npc_citizen17.cpp index 292aff08..07ba67da 100644 --- a/sp/src/game/server/hl2/npc_citizen17.cpp +++ b/sp/src/game/server/hl2/npc_citizen17.cpp @@ -398,6 +398,10 @@ BEGIN_DATADESC( CNPC_Citizen ) DEFINE_INPUTFUNC( FIELD_VOID, "ThrowHealthKit", InputForceHealthKitToss ), #endif +#ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_STRING, "SetPoliceGoal", InputSetPoliceGoal ), +#endif + DEFINE_USEFUNC( CommanderUse ), DEFINE_USEFUNC( SimpleUse ), @@ -417,6 +421,7 @@ bool CNPC_Citizen::CreateBehaviors() AddBehavior( &m_FuncTankBehavior ); #ifdef MAPBASE AddBehavior( &m_RappelBehavior ); + AddBehavior( &m_PolicingBehavior ); #endif return true; @@ -4255,6 +4260,39 @@ void CNPC_Citizen::InputSpeakIdleResponse( inputdata_t &inputdata ) SpeakIfAllowed( TLK_ANSWER, NULL, true ); } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CNPC_Citizen::InputSetPoliceGoal( inputdata_t &inputdata ) +{ + if (/*!inputdata.value.String() ||*/ inputdata.value.String()[0] == 0) + { + m_PolicingBehavior.Disable(); + return; + } + + CBaseEntity *pGoal = gEntList.FindEntityByName( NULL, inputdata.value.String() ); + + if ( pGoal == NULL ) + { + DevMsg( "SetPoliceGoal: %s (%s) unable to find ai_goal_police: %s\n", GetClassname(), GetDebugName(), inputdata.value.String() ); + return; + } + + CAI_PoliceGoal *pPoliceGoal = dynamic_cast(pGoal); + + if ( pPoliceGoal == NULL ) + { + DevMsg( "SetPoliceGoal: %s (%s)'s target %s is not an ai_goal_police entity!\n", GetClassname(), GetDebugName(), inputdata.value.String() ); + return; + } + + m_PolicingBehavior.Enable( pPoliceGoal ); +} +#endif + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CNPC_Citizen::DeathSound( const CTakeDamageInfo &info ) diff --git a/sp/src/game/server/hl2/npc_citizen17.h b/sp/src/game/server/hl2/npc_citizen17.h index 548107cc..35f39a05 100644 --- a/sp/src/game/server/hl2/npc_citizen17.h +++ b/sp/src/game/server/hl2/npc_citizen17.h @@ -13,6 +13,7 @@ #include "ai_behavior_functank.h" #ifdef MAPBASE #include "ai_behavior_rappel.h" +#include "ai_behavior_police.h" #endif struct SquadCandidate_t; @@ -263,6 +264,9 @@ public: void InputSetAmmoResupplierOn( inputdata_t &inputdata ); void InputSetAmmoResupplierOff( inputdata_t &inputdata ); void InputSpeakIdleResponse( inputdata_t &inputdata ); +#ifdef MAPBASE + void InputSetPoliceGoal( inputdata_t &inputdata ); +#endif //--------------------------------- // Sounds & speech @@ -364,6 +368,7 @@ private: CAI_FuncTankBehavior m_FuncTankBehavior; #ifdef MAPBASE CAI_RappelBehavior m_RappelBehavior; + CAI_PolicingBehavior m_PolicingBehavior; // Rappel virtual bool IsWaitingToRappel( void ) { return m_RappelBehavior.IsWaitingToRappel(); } diff --git a/sp/src/game/server/hl2/npc_combine.cpp b/sp/src/game/server/hl2/npc_combine.cpp index 0ecccd66..397992ba 100644 --- a/sp/src/game/server/hl2/npc_combine.cpp +++ b/sp/src/game/server/hl2/npc_combine.cpp @@ -41,9 +41,11 @@ int g_fCombineQuestion; // true if an idle grunt asked a question. Cleared when someone answers. YUCK old global from grunt code #ifdef MAPBASE -ConVar npc_combine_idle_walk_easy("npc_combine_idle_walk_easy", "1"); -ConVar npc_combine_unarmed_anims("npc_combine_unarmed_anims", "1"); -ConVar npc_combine_altfire_not_allies_only( "npc_combine_altfire_not_allies_only", "1" ); +ConVar npc_combine_idle_walk_easy( "npc_combine_idle_walk_easy", "1", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use ACT_WALK_EASY as a walking animation when idle." ); +ConVar npc_combine_unarmed_anims( "npc_combine_unarmed_anims", "1", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use unarmed idle/walk animations when they have no weapon." ); +ConVar npc_combine_altfire_not_allies_only( "npc_combine_altfire_not_allies_only", "1", FCVAR_NONE, "Mapbase: Elites are normally only allowed to fire their alt-fire attack at the player and the player's allies; This allows elites to alt-fire at other enemies too." ); + +ConVar npc_combine_new_cover_behavior( "npc_combine_new_cover_behavior", "1", FCVAR_NONE, "Mapbase: Toggles small patches for parts of npc_combine AI related to soldiers failing to take cover. These patches are minimal and only change cases where npc_combine would otherwise look at an enemy without shooting or run up to the player to melee attack when they don't have to. Consult the Mapbase wiki for more information." ); #endif #define COMBINE_SKIN_DEFAULT 0 @@ -223,6 +225,8 @@ DEFINE_INPUTFUNC( FIELD_VOID, "DropGrenade", InputDropGrenade ), DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTacticalVariant", InputSetTacticalVariant ), +DEFINE_INPUTFUNC( FIELD_STRING, "SetPoliceGoal", InputSetPoliceGoal ), + DEFINE_AIGRENADE_DATADESC() #endif @@ -366,6 +370,37 @@ void CNPC_Combine::InputSetTacticalVariant( inputdata_t &inputdata ) { m_iTacticalVariant = inputdata.value.Int(); } + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CNPC_Combine::InputSetPoliceGoal( inputdata_t &inputdata ) +{ + if (/*!inputdata.value.String() ||*/ inputdata.value.String()[0] == 0) + { + m_PolicingBehavior.Disable(); + return; + } + + CBaseEntity *pGoal = gEntList.FindEntityByName( NULL, inputdata.value.String() ); + + if ( pGoal == NULL ) + { + DevMsg( "SetPoliceGoal: %s (%s) unable to find ai_goal_police: %s\n", GetClassname(), GetDebugName(), inputdata.value.String() ); + return; + } + + CAI_PoliceGoal *pPoliceGoal = dynamic_cast(pGoal); + + if ( pPoliceGoal == NULL ) + { + DevMsg( "SetPoliceGoal: %s (%s)'s target %s is not an ai_goal_police entity!\n", GetClassname(), GetDebugName(), inputdata.value.String() ); + return; + } + + m_PolicingBehavior.Enable( pPoliceGoal ); +} #endif //----------------------------------------------------------------------------- @@ -471,6 +506,9 @@ bool CNPC_Combine::CreateBehaviors() AddBehavior( &m_StandoffBehavior ); AddBehavior( &m_FollowBehavior ); AddBehavior( &m_FuncTankBehavior ); +#ifdef MAPBASE + AddBehavior( &m_PolicingBehavior ); +#endif return BaseClass::CreateBehaviors(); } @@ -1463,6 +1501,23 @@ void CNPC_Combine::BuildScheduleTestBits( void ) { SetCustomInterruptCondition( COND_COMBINE_ON_FIRE ); } + +#ifdef MAPBASE + if (npc_combine_new_cover_behavior.GetBool()) + { + if ( IsCurSchedule( SCHED_COMBINE_COMBAT_FAIL ) ) + { + SetCustomInterruptCondition( COND_NEW_ENEMY ); + SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); + SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); + } + else if ( IsCurSchedule( SCHED_COMBINE_MOVE_TO_MELEE ) ) + { + SetCustomInterruptCondition( COND_HEAR_DANGER ); + SetCustomInterruptCondition( COND_HEAR_MOVE_AWAY ); + } + } +#endif } @@ -2147,7 +2202,12 @@ int CNPC_Combine::SelectFailSchedule( int failedSchedule, int failedTask, AI_Tas { if( failedSchedule == SCHED_COMBINE_TAKE_COVER1 ) { +#ifdef MAPBASE + if( IsInSquad() && IsStrategySlotRangeOccupied(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2) && HasCondition(COND_SEE_ENEMY) + && ( !npc_combine_new_cover_behavior.GetBool() || (taskFailCode == FAIL_NO_COVER) ) ) +#else if( IsInSquad() && IsStrategySlotRangeOccupied(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2) && HasCondition(COND_SEE_ENEMY) ) +#endif { // This eases the effects of an unfortunate bug that usually plagues shotgunners. Since their rate of fire is low, // they spend relatively long periods of time without an attack squad slot. If you corner a shotgunner, usually @@ -2378,6 +2438,13 @@ int CNPC_Combine::TranslateSchedule( int scheduleType ) return TranslateSchedule( SCHED_RANGE_ATTACK1 ); } +#ifdef MAPBASE + if ( npc_combine_new_cover_behavior.GetBool() && HasCondition( COND_CAN_RANGE_ATTACK2 ) && OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) + { + return TranslateSchedule( SCHED_RANGE_ATTACK2 ); + } +#endif + // Run somewhere randomly return TranslateSchedule( SCHED_FAIL ); break; @@ -3563,6 +3630,37 @@ Vector CNPC_Combine::GetCrouchEyeOffset( void ) return COMBINE_EYE_CROUCHING_POSITION; } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CNPC_Combine::IsCrouchedActivity( Activity activity ) +{ + if (BaseClass::IsCrouchedActivity( activity )) + return true; + + Activity realActivity = TranslateActivity(activity); + + // Soldiers need to consider these crouched activities, but not all NPCs should. + switch ( realActivity ) + { + case ACT_RANGE_AIM_LOW: + case ACT_RANGE_AIM_AR2_LOW: + case ACT_RANGE_AIM_SMG1_LOW: + case ACT_RANGE_AIM_PISTOL_LOW: + case ACT_RANGE_ATTACK1_LOW: + case ACT_RANGE_ATTACK_AR2_LOW: + case ACT_RANGE_ATTACK_SMG1_LOW: + case ACT_RANGE_ATTACK_SHOTGUN_LOW: + case ACT_RANGE_ATTACK_PISTOL_LOW: + case ACT_RANGE_ATTACK2_LOW: + return true; + } + + return false; +} +#endif + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CNPC_Combine::SetActivity( Activity NewActivity ) diff --git a/sp/src/game/server/hl2/npc_combine.h b/sp/src/game/server/hl2/npc_combine.h index d574e770..ec541cca 100644 --- a/sp/src/game/server/hl2/npc_combine.h +++ b/sp/src/game/server/hl2/npc_combine.h @@ -23,6 +23,7 @@ #include "ai_baseactor.h" #ifdef MAPBASE #include "mapbase/ai_grenade.h" +#include "ai_behavior_police.h" #endif #ifdef EXPANDED_RESPONSE_SYSTEM_USAGE #include "mapbase/expandedrs_combine.h" @@ -74,6 +75,10 @@ public: virtual Vector GetCrouchEyeOffset( void ); +#ifdef MAPBASE + virtual bool IsCrouchedActivity( Activity activity ); +#endif + void Event_Killed( const CTakeDamageInfo &info ); @@ -95,6 +100,8 @@ public: void InputDropGrenade( inputdata_t &inputdata ); void InputSetTacticalVariant( inputdata_t &inputdata ); + + void InputSetPoliceGoal( inputdata_t &inputdata ); #endif bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL ); @@ -353,6 +360,9 @@ private: CAI_FuncTankBehavior m_FuncTankBehavior; CAI_RappelBehavior m_RappelBehavior; CAI_ActBusyBehavior m_ActBusyBehavior; +#ifdef MAPBASE + CAI_PolicingBehavior m_PolicingBehavior; +#endif public: int m_iLastAnimEventHandled; diff --git a/sp/src/game/server/hl2/npc_combinecamera.cpp b/sp/src/game/server/hl2/npc_combinecamera.cpp index 22e56379..13bbba1b 100644 --- a/sp/src/game/server/hl2/npc_combinecamera.cpp +++ b/sp/src/game/server/hl2/npc_combinecamera.cpp @@ -627,6 +627,14 @@ void CNPC_CombineCamera::ActiveThink() if ( !pTarget ) { // Nobody suspicious. Go back to being idle. +#ifdef MAPBASE + if (m_hEnemyTarget) + { + m_OnLostEnemy.FireOutput( m_hEnemyTarget, this ); + if (m_hEnemyTarget->IsPlayer()) + m_OnLostPlayer.FireOutput( m_hEnemyTarget, this ); + } +#endif m_hEnemyTarget = NULL; EmitSound("NPC_CombineCamera.BecomeIdle"); SetAngry(false); diff --git a/sp/src/game/server/hl2/npc_manhack.cpp b/sp/src/game/server/hl2/npc_manhack.cpp index 91d011fa..27dcde85 100644 --- a/sp/src/game/server/hl2/npc_manhack.cpp +++ b/sp/src/game/server/hl2/npc_manhack.cpp @@ -169,6 +169,7 @@ BEGIN_DATADESC( CNPC_Manhack ) DEFINE_FIELD( m_hSmokeTrail, FIELD_EHANDLE), #ifdef MAPBASE DEFINE_FIELD( m_hPrevOwner, FIELD_EHANDLE ), + DEFINE_KEYFIELD( m_bNoSprites, FIELD_BOOLEAN, "NoSprites" ), #endif // DEFINE_FIELD( m_pLightGlow, FIELD_CLASSPTR ), @@ -198,6 +199,10 @@ BEGIN_DATADESC( CNPC_Manhack ) // Function Pointers DEFINE_INPUTFUNC( FIELD_VOID, "DisableSwarm", InputDisableSwarm ), DEFINE_INPUTFUNC( FIELD_VOID, "Unpack", InputUnpack ), +#ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_VOID, "EnableSprites", InputEnableSprites ), + DEFINE_INPUTFUNC( FIELD_VOID, "DisableSprites", InputDisableSprites ), +#endif DEFINE_ENTITYFUNC( CrashTouch ), @@ -2479,6 +2484,11 @@ void CNPC_Manhack::Spawn(void) //----------------------------------------------------------------------------- void CNPC_Manhack::StartEye( void ) { +#ifdef MAPBASE + if (m_bNoSprites) + return; +#endif + //Create our Eye sprite if ( m_pEyeGlow == NULL ) { @@ -2998,6 +3008,26 @@ void CNPC_Manhack::InputUnpack( inputdata_t &inputdata ) SetCondition( COND_LIGHT_DAMAGE ); } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: Creates the sprite if it has been destroyed +//----------------------------------------------------------------------------- +void CNPC_Manhack::InputEnableSprites( inputdata_t &inputdata ) +{ + m_bNoSprites = false; + StartEye(); +} + +//----------------------------------------------------------------------------- +// Purpose: Destroys the sprite +//----------------------------------------------------------------------------- +void CNPC_Manhack::InputDisableSprites( inputdata_t &inputdata ) +{ + KillSprites( 0.0 ); + m_bNoSprites = true; +} +#endif + //----------------------------------------------------------------------------- // Purpose: // Input : *pPhysGunUser - diff --git a/sp/src/game/server/hl2/npc_manhack.h b/sp/src/game/server/hl2/npc_manhack.h index b2dec9b9..a080f0eb 100644 --- a/sp/src/game/server/hl2/npc_manhack.h +++ b/sp/src/game/server/hl2/npc_manhack.h @@ -145,6 +145,10 @@ public: void InputDisableSwarm( inputdata_t &inputdata ); void InputUnpack( inputdata_t &inputdata ); +#ifdef MAPBASE + void InputEnableSprites( inputdata_t &inputdata ); + void InputDisableSprites( inputdata_t &inputdata ); +#endif // CDefaultPlayerPickupVPhysics virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); @@ -263,6 +267,8 @@ private: CHandle m_hSmokeTrail; #ifdef MAPBASE EHANDLE m_hPrevOwner; + + bool m_bNoSprites; #endif int m_iPanel1; diff --git a/sp/src/game/server/mapbase/logic_externaldata.cpp b/sp/src/game/server/mapbase/logic_externaldata.cpp index 3e1a7915..b28189f7 100644 --- a/sp/src/game/server/mapbase/logic_externaldata.cpp +++ b/sp/src/game/server/mapbase/logic_externaldata.cpp @@ -199,7 +199,7 @@ void CLogicExternalData::InputWriteKeyValue( inputdata_t &inputdata ) // Separate key from value char *delimiter = Q_strstr(szValue, " "); - if (delimiter) + if (delimiter && (delimiter + 1) != '\0') { Q_strncpy(key, szValue, MIN((delimiter - szValue) + 1, sizeof(key))); Q_strncpy(value, delimiter + 1, sizeof(value)); @@ -284,8 +284,7 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValues( void ) if (m_pRoot) { // Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't. - CScriptKeyValues *pKV = new CScriptKeyValues( m_pRoot ); - hScript = g_pScriptVM->RegisterInstance( pKV ); + hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, m_pRoot, false ); } return hScript; @@ -302,8 +301,7 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValueBlock( void ) if (m_pBlock) { // Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't. - CScriptKeyValues *pKV = new CScriptKeyValues( m_pBlock ); - hScript = g_pScriptVM->RegisterInstance( pKV ); + hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, m_pBlock, false ); } return hScript; @@ -320,10 +318,10 @@ void CLogicExternalData::ScriptSetKeyValues( HSCRIPT hKV ) m_pRoot = NULL; } - CScriptKeyValues *pKV = HScriptToClass( hKV ); + KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV ); if (pKV) { - m_pRoot = pKV->m_pKeyValues; + m_pRoot = pKV; } } @@ -335,10 +333,10 @@ void CLogicExternalData::ScriptSetKeyValueBlock( HSCRIPT hKV ) m_pBlock = NULL; } - CScriptKeyValues *pKV = HScriptToClass( hKV ); + KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV ); if (pKV) { - m_pBlock = pKV->m_pKeyValues; + m_pBlock = pKV; } } diff --git a/sp/src/game/server/maprules.cpp b/sp/src/game/server/maprules.cpp index b3156e7b..91049ad8 100644 --- a/sp/src/game/server/maprules.cpp +++ b/sp/src/game/server/maprules.cpp @@ -297,6 +297,8 @@ public: #ifdef MAPBASE void InputSetText ( inputdata_t &inputdata ); void SetText( const char* pszStr ); + + void InputSetFont( inputdata_t &inputdata ) { m_strFont = inputdata.value.StringID(); } #endif void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) @@ -308,6 +310,11 @@ private: string_t m_iszMessage; hudtextparms_t m_textParms; + +#ifdef MAPBASE + string_t m_strFont; + bool m_bAutobreak; +#endif }; LINK_ENTITY_TO_CLASS( game_text, CGameText ); @@ -327,12 +334,18 @@ BEGIN_DATADESC( CGameText ) DEFINE_KEYFIELD( m_textParms.holdTime, FIELD_FLOAT, "holdtime" ), DEFINE_KEYFIELD( m_textParms.fxTime, FIELD_FLOAT, "fxtime" ), +#ifdef MAPBASE + DEFINE_KEYFIELD( m_strFont, FIELD_STRING, "font" ), + DEFINE_KEYFIELD( m_bAutobreak, FIELD_BOOLEAN, "autobreak" ), +#endif + DEFINE_ARRAY( m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ), // Inputs DEFINE_INPUTFUNC( FIELD_VOID, "Display", InputDisplay ), #ifdef MAPBASE DEFINE_INPUTFUNC( FIELD_STRING, "SetText", InputSetText ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetFont", InputSetFont ), #endif END_DATADESC() @@ -385,7 +398,11 @@ void CGameText::Display( CBaseEntity *pActivator ) if ( MessageToAll() ) { +#ifdef MAPBASE + UTIL_HudMessageAll( m_textParms, MessageGet(), STRING(m_strFont), m_bAutobreak ); +#else UTIL_HudMessageAll( m_textParms, MessageGet() ); +#endif } else { @@ -393,12 +410,20 @@ void CGameText::Display( CBaseEntity *pActivator ) if ( gpGlobals->maxClients == 1 ) { CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); +#ifdef MAPBASE + UTIL_HudMessage( pPlayer, m_textParms, MessageGet(), STRING(m_strFont), m_bAutobreak ); +#else UTIL_HudMessage( pPlayer, m_textParms, MessageGet() ); +#endif } // Otherwise show the message to the player that triggered us. else if ( pActivator && pActivator->IsNetClient() ) { +#ifdef MAPBASE + UTIL_HudMessage( ToBasePlayer( pActivator ), m_textParms, MessageGet(), STRING(m_strFont), m_bAutobreak ); +#else UTIL_HudMessage( ToBasePlayer( pActivator ), m_textParms, MessageGet() ); +#endif } } } @@ -417,7 +442,7 @@ void CGameText::SetText( const char* pszStr ) CUtlStringList vecLines; Q_SplitString( pszStr, "/n", vecLines ); - char szMsg[256]; + char szMsg[512]; Q_strncpy( szMsg, vecLines[0], sizeof( szMsg ) ); for (int i = 1; i < vecLines.Count(); i++) diff --git a/sp/src/game/server/pathtrack.cpp b/sp/src/game/server/pathtrack.cpp index 539a6e03..2a77666d 100644 --- a/sp/src/game/server/pathtrack.cpp +++ b/sp/src/game/server/pathtrack.cpp @@ -17,9 +17,15 @@ //----------------------------------------------------------------------------- BEGIN_DATADESC( CPathTrack ) +#ifdef MAPBASE + DEFINE_FIELD( m_pnext, FIELD_EHANDLE ), + DEFINE_FIELD( m_pprevious, FIELD_EHANDLE ), + DEFINE_FIELD( m_paltpath, FIELD_EHANDLE ), +#else DEFINE_FIELD( m_pnext, FIELD_CLASSPTR ), DEFINE_FIELD( m_pprevious, FIELD_CLASSPTR ), DEFINE_FIELD( m_paltpath, FIELD_CLASSPTR ), +#endif DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), DEFINE_FIELD( m_length, FIELD_FLOAT ), diff --git a/sp/src/game/server/physics.cpp b/sp/src/game/server/physics.cpp index 3117a3e1..3e2ab69c 100644 --- a/sp/src/game/server/physics.cpp +++ b/sp/src/game/server/physics.cpp @@ -724,7 +724,7 @@ bool CCollisionEvent::ShouldFreezeContacts( IPhysicsObject **pObjectList, int ob { if ( m_lastTickFrictionError > gpGlobals->tickcount || m_lastTickFrictionError < (gpGlobals->tickcount-1) ) { - DevWarning("Performance Warning: large friction system (%d objects)!!!\n", objectCount ); + CGWarning( 1, CON_GROUP_PHYSICS, "Performance Warning: large friction system (%d objects)!!!\n", objectCount ); #if _DEBUG for ( int i = 0; i < objectCount; i++ ) { @@ -997,7 +997,7 @@ int CCollisionEvent::ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObje { if ( pObj0->GetGameFlags() & FVPHYSICS_PART_OF_RAGDOLL ) { - DevMsg(2, "Solving ragdoll self penetration! %s (%s) (%d v %d)\n", pObj0->GetName(), pEntity0->GetDebugName(), pObj0->GetGameIndex(), pObj1->GetGameIndex() ); + CGMsg( 2, CON_GROUP_PHYSICS, "Solving ragdoll self penetration! %s (%s) (%d v %d)\n", pObj0->GetName(), pEntity0->GetDebugName(), pObj0->GetGameIndex(), pObj1->GetGameIndex() ); ragdoll_t *pRagdoll = Ragdoll_GetRagdoll( pEntity0 ); pRagdoll->pGroup->SolvePenetration( pObj0, pObj1 ); return false; @@ -1030,11 +1030,11 @@ int CCollisionEvent::ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObje { int index0 = physcollision->CollideIndex( pObj0->GetCollide() ); int index1 = physcollision->CollideIndex( pObj1->GetCollide() ); - DevMsg(1, "***Inter-penetration on %s (%d & %d) (%.0f, %.0f)\n", pName1?pName1:"(null)", index0, index1, gpGlobals->curtime, eventTime ); + CGMsg( 1, CON_GROUP_PHYSICS, "***Inter-penetration on %s (%d & %d) (%.0f, %.0f)\n", pName1?pName1:"(null)", index0, index1, gpGlobals->curtime, eventTime ); } else { - DevMsg(1, "***Inter-penetration between %s(%s) AND %s(%s) (%.0f, %.0f)\n", pName1?pName1:"(null)", pEntity0->GetDebugName(), pName2?pName2:"(null)", pEntity1->GetDebugName(), gpGlobals->curtime, eventTime ); + CGMsg( 1, CON_GROUP_PHYSICS, "***Inter-penetration between %s(%s) AND %s(%s) (%.0f, %.0f)\n", pName1?pName1:"(null)", pEntity0->GetDebugName(), pName2?pName2:"(null)", pEntity1->GetDebugName(), gpGlobals->curtime, eventTime ); } } #endif @@ -1333,8 +1333,8 @@ CON_COMMAND_F(surfaceprop, "Reports the surface properties at the cursor", FCVAR Vector vecVelocity = tr.startpos - tr.endpos; int length = vecVelocity.Length(); - Msg("Hit surface \"%s\" (entity %s, model \"%s\" %s), texture \"%s\"\n", physprops->GetPropName( tr.surface.surfaceProps ), tr.m_pEnt->GetClassname(), pModelName, modelStuff.Access(), tr.surface.name); - Msg("Distance to surface: %d\n", length ); + CGMsg( 0, CON_GROUP_PHYSICS, "Hit surface \"%s\" (entity %s, model \"%s\" %s), texture \"%s\"\n", physprops->GetPropName( tr.surface.surfaceProps ), tr.m_pEnt->GetClassname(), pModelName, modelStuff.Access(), tr.surface.name ); + CGMsg( 0, CON_GROUP_PHYSICS, "Distance to surface: %d\n", length ); } } @@ -1342,12 +1342,12 @@ static void OutputVPhysicsDebugInfo( CBaseEntity *pEntity ) { if ( pEntity ) { - Msg("Entity %s (%s) %s Collision Group %d\n", pEntity->GetClassname(), pEntity->GetDebugName(), pEntity->IsNavIgnored() ? "NAV IGNORE" : "", pEntity->GetCollisionGroup() ); + CGMsg( 0, CON_GROUP_PHYSICS, "Entity %s (%s) %s Collision Group %d\n", pEntity->GetClassname(), pEntity->GetDebugName(), pEntity->IsNavIgnored() ? "NAV IGNORE" : "", pEntity->GetCollisionGroup() ); CUtlVector list; g_Collisions.GetListOfPenetratingEntities( pEntity, list ); for ( int i = 0; i < list.Count(); i++ ) { - Msg(" penetration with entity %s (%s)\n", list[i]->GetDebugName(), STRING(list[i]->GetModelName()) ); + CGMsg( 0, CON_GROUP_PHYSICS, " penetration with entity %s (%s)\n", list[i]->GetDebugName(), STRING( list[i]->GetModelName() ) ); } IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; @@ -1358,7 +1358,7 @@ static void OutputVPhysicsDebugInfo( CBaseEntity *pEntity ) { for ( int i = 0; i < physCount; i++ ) { - Msg("Object %d (of %d) =========================\n", i+1, physCount ); + CGMsg( 0, CON_GROUP_PHYSICS, "Object %d (of %d) =========================\n", i + 1, physCount ); pList[i]->OutputDebugInfo(); } } @@ -1496,7 +1496,7 @@ static void DebugConstraints( CBaseEntity *pEntity ) pModel1 = STRING(pAttach[1]->GetModelName()); index1 = pAttachVPhysics[1]->GetGameIndex(); } - Msg("**********************\n%s connects %s(%s:%d) to %s(%s:%d)\n", constraints[i]->GetClassname(), pName0, pModel0, index0, pName1, pModel1, index1 ); + CGMsg( 0, CON_GROUP_PHYSICS, "**********************\n%s connects %s(%s:%d) to %s(%s:%d)\n", constraints[i]->GetClassname(), pName0, pModel0, index0, pName1, pModel1, index1 ); DebugConstraint(constraints[i]); constraints[i]->m_debugOverlays |= OVERLAY_BBOX_BIT | OVERLAY_TEXT_BIT; } @@ -1642,7 +1642,7 @@ CON_COMMAND( physics_budget, "Times the cost of each active object" ) for ( i = 0; i < ents.Count(); i++ ) { float fraction = times[i] / totalTime; - Msg( "%s (%s): %.3fms (%.3f%%) @ %s\n", ents[i]->GetClassname(), ents[i]->GetDebugName(), fraction * totalTime * 1000.0f, fraction * 100.0f, VecToString(ents[i]->GetAbsOrigin()) ); + CGMsg( 0, CON_GROUP_PHYSICS, "%s (%s): %.3fms (%.3f%%) @ %s\n", ents[i]->GetClassname(), ents[i]->GetDebugName(), fraction * totalTime * 1000.0f, fraction * 100.0f, VecToString( ents[i]->GetAbsOrigin() ) ); } g_Collisions.BufferTouchEvents( false ); } @@ -1685,7 +1685,7 @@ void PhysFrame( float deltaTime ) if ( deltaTime > 1.0f || deltaTime < 0.0f ) { deltaTime = 0; - Msg( "Reset physics clock\n" ); + CGMsg( 0, CON_GROUP_PHYSICS, "Reset physics clock\n" ); } else if ( deltaTime > 0.1f ) // limit incoming time to 100ms { @@ -1743,7 +1743,7 @@ void PhysFrame( float deltaTime ) CBaseEntity *pEntity = pItem->hEnt.Get(); if ( !pEntity ) { - Msg( "Dangling pointer to physics entity!!!\n" ); + CGMsg( 0, CON_GROUP_PHYSICS, "Dangling pointer to physics entity!!!\n" ); continue; } @@ -1765,7 +1765,7 @@ void PhysFrame( float deltaTime ) g_PhysAverageSimTime += (simRealTime * 0.2); if ( lastObjectCount != 0 || activeCount != 0 ) { - Msg( "Physics: %3d objects, %4.1fms / AVG: %4.1fms\n", activeCount, simRealTime * 1000, g_PhysAverageSimTime * 1000 ); + CGMsg( 0, CON_GROUP_PHYSICS, "Physics: %3d objects, %4.1fms / AVG: %4.1fms\n", activeCount, simRealTime * 1000, g_PhysAverageSimTime * 1000 ); } lastObjectCount = activeCount; @@ -1929,7 +1929,7 @@ void PhysForceEntityToSleep( CBaseEntity *pEntity, IPhysicsObject *pObject ) if ( !pObject || !pObject->IsMoveable() ) return; - DevMsg(2, "Putting entity to sleep: %s\n", pEntity->GetClassname() ); + CGMsg( 2, CON_GROUP_PHYSICS, "Putting entity to sleep: %s\n", pEntity->GetClassname() ); MEM_ALLOC_CREDIT(); IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int physCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); @@ -2024,7 +2024,7 @@ void CCollisionEvent::FlushQueuedOperations() // testing, if this assert fires it proves we've fixed the crash // after that the assert + warning can safely be removed Assert(0); - Warning("Physics queue not empty, error!\n"); + CGWarning( 0, CON_GROUP_PHYSICS, "Physics queue not empty, error!\n" ); loopCount++; UpdateTouchEvents(); UpdateDamageEvents(); @@ -2773,7 +2773,7 @@ void PhysCallbackDamage( CBaseEntity *pEntity, const CTakeDamageInfo &info ) g_Collisions.AddDamageEvent( pEntity, info, pInflictorPhysics, false, vec3_origin, vec3_origin ); if ( pEntity && info.GetInflictor() ) { - DevMsg( 2, "Warning: Physics damage event with no recovery info!\nObjects: %s, %s\n", pEntity->GetClassname(), info.GetInflictor()->GetClassname() ); + CGMsg( 2, CON_GROUP_PHYSICS, "Warning: Physics damage event with no recovery info!\nObjects: %s, %s\n", pEntity->GetClassname(), info.GetInflictor()->GetClassname() ); } } else @@ -2832,10 +2832,10 @@ IPhysicsObject *FindPhysicsObjectByName( const char *pName, CBaseEntity *pErrorE { const char *pErrorName = pErrorEntity ? pErrorEntity->GetClassname() : "Unknown"; Vector origin = pErrorEntity ? pErrorEntity->GetAbsOrigin() : vec3_origin; - DevWarning("entity %s at %s has physics attachment to more than one entity with the name %s!!!\n", pErrorName, VecToString(origin), pName ); + CGWarning( 1, CON_GROUP_PHYSICS, "entity %s at %s has physics attachment to more than one entity with the name %s!!!\n", pErrorName, VecToString( origin ), pName ); while ( ( pEntity = gEntList.FindEntityByName( pEntity, pName ) ) != NULL ) { - DevWarning("Found %s\n", pEntity->GetClassname() ); + CGWarning( 1, CON_GROUP_PHYSICS, "Found %s\n", pEntity->GetClassname() ); } break; @@ -2853,7 +2853,7 @@ void CC_AirDensity( const CCommand &args ) if ( args.ArgC() < 2 ) { - Msg( "air_density \nCurrent air density is %.2f\n", physenv->GetAirDensity() ); + CGMsg( 0, CON_GROUP_PHYSICS, "air_density \nCurrent air density is %.2f\n", physenv->GetAirDensity() ); } else { diff --git a/sp/src/game/server/player.cpp b/sp/src/game/server/player.cpp index 1f4c57f1..ba4ee6a7 100644 --- a/sp/src/game/server/player.cpp +++ b/sp/src/game/server/player.cpp @@ -483,6 +483,9 @@ BEGIN_DATADESC( CBasePlayer ) END_DATADESC() #ifdef MAPBASE_VSCRIPT +// TODO: Better placement? +ScriptHook_t g_Hook_PlayerRunCommand; + BEGIN_ENT_SCRIPTDESC( CBasePlayer, CBaseCombatCharacter, "The player entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptIsPlayerNoclipping, "IsNoclipping", "Returns true if the player is in noclip mode." ) @@ -523,6 +526,21 @@ BEGIN_ENT_SCRIPTDESC( CBasePlayer, CBaseCombatCharacter, "The player entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptGetFOVOwner, "GetFOVOwner", "" ) DEFINE_SCRIPTFUNC_NAMED( ScriptSetFOV, "SetFOV", "" ) + DEFINE_SCRIPTFUNC( ViewPunch, "Punches the player's view with the specified vector." ) + DEFINE_SCRIPTFUNC( SetMuzzleFlashTime, "Sets the player's muzzle flash time for AI." ) + DEFINE_SCRIPTFUNC( SetSuitUpdate, "Sets an update for the player's HEV suit." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetAutoaimVector, "GetAutoaimVector", "Gets the player's autoaim shooting direction with the specified scale." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetAutoaimVectorCustomMaxDist, "GetAutoaimVectorCustomMaxDist", "Gets the player's autoaim shooting direction with the specified scale and a custom max distance." ) + DEFINE_SCRIPTFUNC( ShouldAutoaim, "Returns true if the player should be autoaiming." ) + + // + // Hooks + // + BEGIN_SCRIPTHOOK( g_Hook_PlayerRunCommand, "PlayerRunCommand", FIELD_VOID, "Called when running a player command on the server." ) + DEFINE_SCRIPTHOOK_PARAM( "command", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + END_SCRIPTDESC(); #else BEGIN_ENT_SCRIPTDESC( CBasePlayer, CBaseAnimating, "The player entity." ) @@ -3802,13 +3820,13 @@ void CBasePlayer::PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper) #ifdef MAPBASE_VSCRIPT // Movement hook for VScript - if ( HSCRIPT hFunc = LookupScriptFunction("PlayerRunCommand") ) + if (m_ScriptScope.IsInitialized() && g_Hook_PlayerRunCommand.CanRunInScope(m_ScriptScope)) { HSCRIPT hCmd = g_pScriptVM->RegisterInstance( ucmd ); - g_pScriptVM->SetValue( "command", hCmd ); - CallScriptFunctionHandle( hFunc, NULL ); - g_pScriptVM->ClearValue( "command" ); + // command + ScriptVariant_t args[] = { hCmd }; + g_Hook_PlayerRunCommand.Call( m_ScriptScope, NULL, args ); g_pScriptVM->RemoveInstance( hCmd ); } diff --git a/sp/src/game/server/player.h b/sp/src/game/server/player.h index 56840252..2e5c56d9 100644 --- a/sp/src/game/server/player.h +++ b/sp/src/game/server/player.h @@ -588,6 +588,10 @@ public: virtual Vector GetAutoaimVector( float flScale ); virtual Vector GetAutoaimVector( float flScale, float flMaxDist ); virtual void GetAutoaimVector( autoaim_params_t ¶ms ); +#ifdef MAPBASE_VSCRIPT + Vector ScriptGetAutoaimVector( float flScale ) { return GetAutoaimVector( flScale ); } + Vector ScriptGetAutoaimVectorCustomMaxDist( float flScale, float flMaxDist ) { return GetAutoaimVector( flScale, flMaxDist ); } +#endif float GetAutoaimScore( const Vector &eyePosition, const Vector &viewDir, const Vector &vecTarget, CBaseEntity *pTarget, float fScale, CBaseCombatWeapon *pActiveWeapon ); QAngle AutoaimDeflection( Vector &vecSrc, autoaim_params_t ¶ms ); diff --git a/sp/src/game/server/point_spotlight.cpp b/sp/src/game/server/point_spotlight.cpp index 8af30ff8..5a854557 100644 --- a/sp/src/game/server/point_spotlight.cpp +++ b/sp/src/game/server/point_spotlight.cpp @@ -49,6 +49,9 @@ private: // ------------------------------ void InputLightOn( inputdata_t &inputdata ); void InputLightOff( inputdata_t &inputdata ); +#ifdef MAPBASE + void InputLightToggle( inputdata_t &inputdata ) { m_bSpotlightOn ? InputLightOff(inputdata) : InputLightOn(inputdata); } +#endif // Creates the efficient spotlight void CreateEfficientSpotlight(); @@ -99,6 +102,9 @@ BEGIN_DATADESC( CPointSpotlight ) // Inputs DEFINE_INPUTFUNC( FIELD_VOID, "LightOn", InputLightOn ), DEFINE_INPUTFUNC( FIELD_VOID, "LightOff", InputLightOff ), +#ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_VOID, "LightToggle", InputLightToggle ), +#endif DEFINE_OUTPUT( m_OnOn, "OnLightOn" ), DEFINE_OUTPUT( m_OnOff, "OnLightOff" ), diff --git a/sp/src/game/server/sceneentity.cpp b/sp/src/game/server/sceneentity.cpp index 7798ef9e..6914fd19 100644 --- a/sp/src/game/server/sceneentity.cpp +++ b/sp/src/game/server/sceneentity.cpp @@ -72,6 +72,17 @@ static int speechListIndex = 0; #define SCENE_MIN_PITCH 0.25f #define SCENE_MAX_PITCH 2.5f +// New macros introduced for Mapbase's console message color changes. +#ifdef MAPBASE +#define ChoreoMsg( lvl, msg ) CGMsg( lvl, CON_GROUP_CHOREO, msg ) +#define ChoreoMsg1( lvl, msg, a ) CGMsg( lvl, CON_GROUP_CHOREO, msg, a ) +#define ChoreoMsg2( lvl, msg, a, b ) CGMsg( lvl, CON_GROUP_CHOREO, msg, a, b ) +#else +#define ChoreoMsg( lvl, msg ) DevMsg( lvl, msg ) +#define ChoreoMsg1( lvl, msg, a ) DevMsg( lvl, msg, a ) +#define ChoreoMsg2( lvl, msg, a, b ) DevMsg( lvl, msg, a, b ) +#endif + //=========================================================================================================== // SCENE LIST MANAGER //=========================================================================================================== @@ -2725,7 +2736,7 @@ void CSceneEntity::StartPlayback( void ) m_pScene = LoadScene( STRING( m_iszSceneFile ), this ); if ( !m_pScene ) { - DevMsg( "%s missing from scenes.image\n", STRING( m_iszSceneFile ) ); + ChoreoMsg1( 1, "%s missing from scenes.image\n", STRING( m_iszSceneFile ) ); m_bSceneMissing = true; return; } @@ -3068,6 +3079,12 @@ void CSceneEntity::DispatchStartSubScene( CChoreoScene *scene, CBaseFlex *pActor if ( subscene ) { +#ifdef MAPBASE + // Somes may not be created with a CSceneEntity as the event callback + if (!scene->GetEventCallbackInterface()) + scene->SetEventCallbackInterface( this ); +#endif + subscene->ResetSimulation(); } } @@ -3305,7 +3322,7 @@ void CSceneEntity::StartEvent( float currenttime, CChoreoScene *scene, CChoreoEv if( !pEntity->ValidateScriptScope() ) { - DevMsg("\n***\nCChoreoEvent::SCRIPT - FAILED to create private ScriptScope. ABORTING script call\n***\n"); + ChoreoMsg(1, "\n***\nCChoreoEvent::SCRIPT - FAILED to create private ScriptScope. ABORTING script call\n***\n"); break; } @@ -3657,7 +3674,7 @@ bool CSceneEntity::ShouldNetwork() const CChoreoScene *CSceneEntity::LoadScene( const char *filename, IChoreoEventCallback *pCallback ) { - DevMsg( 2, "Blocking load of scene from '%s'\n", filename ); + ChoreoMsg1( 2, "Blocking load of scene from '%s'\n", filename ); char loadfile[MAX_PATH]; Q_strncpy( loadfile, filename, sizeof( loadfile ) ); diff --git a/sp/src/game/server/scripted.cpp b/sp/src/game/server/scripted.cpp index 081998aa..19fc6784 100644 --- a/sp/src/game/server/scripted.cpp +++ b/sp/src/game/server/scripted.cpp @@ -31,6 +31,23 @@ ConVar ai_task_pre_script( "ai_task_pre_script", "0", FCVAR_NONE ); +// New macros introduced for Mapbase's console message color changes. +#ifdef MAPBASE +#define ScriptMsg( lvl, msg ) CGMsg( lvl, CON_GROUP_NPC_SCRIPTS, msg ) +#define ScriptMsg1( lvl, msg, a ) CGMsg( lvl, CON_GROUP_NPC_SCRIPTS, msg, a ) +#define ScriptMsg2( lvl, msg, a, b ) CGMsg( lvl, CON_GROUP_NPC_SCRIPTS, msg, a, b ) +#define ScriptMsg3( lvl, msg, a, b, c ) CGMsg( lvl, CON_GROUP_NPC_SCRIPTS, msg, a, b, c ) +#define ScriptMsg4( lvl, msg, a, b, c, d ) CGMsg( lvl, CON_GROUP_NPC_SCRIPTS, msg, a, b, c, d ) +#define ScriptMsg5( lvl, msg, a, b, c, d, e ) CGMsg( lvl, CON_GROUP_NPC_SCRIPTS, msg, a, b, c, d, e ) +#else +#define ScriptMsg( lvl, msg ) DevMsg( lvl, msg ) +#define ScriptMsg1( lvl, msg, a ) DevMsg( lvl, msg, a ) +#define ScriptMsg2( lvl, msg, a, b ) DevMsg( lvl, msg, a, b ) +#define ScriptMsg3( lvl, msg, a, b, c ) DevMsg( lvl, msg, a, b, c ) +#define ScriptMsg4( lvl, msg, a, b, c, d ) DevMsg( lvl, msg, a, b, c, d ) +#define ScriptMsg5( lvl, msg, a, b, c, d, e ) DevMsg( lvl, msg, a, b, c, d, e ) +#endif + // // targetname "me" - there can be more than one with the same name, and they act in concert @@ -448,7 +465,7 @@ void CAI_ScriptedSequence::InputCancelSequence( inputdata_t &inputdata ) // We don't call CancelScript because entity I/O will handle dispatching // this input to all other scripts with our same name. // - DevMsg( 2, "InputCancelScript: Cancelling script '%s'\n", STRING( m_iszPlay )); + ScriptMsg1( 2, "InputCancelScript: Cancelling script '%s'\n", STRING( m_iszPlay )); StopThink(); ScriptEntityCancel( this ); } @@ -464,7 +481,7 @@ void CAI_ScriptedSequence::InputScriptPlayerDeath( inputdata_t &inputdata ) // We don't call CancelScript because entity I/O will handle dispatching // this input to all other scripts with our same name. // - DevMsg( 2, "InputCancelScript: Cancelling script '%s'\n", STRING( m_iszPlay )); + ScriptMsg1( 2, "InputCancelScript: Cancelling script '%s'\n", STRING( m_iszPlay )); StopThink(); ScriptEntityCancel( this ); } @@ -513,7 +530,7 @@ void CAI_ScriptedSequence::Blocked( CBaseEntity *pOther ) void CAI_ScriptedSequence::Touch( CBaseEntity *pOther ) { /* - DevMsg( 2, "Cine Touch\n" ); + ScriptMsg( 2, "Cine Touch\n" ); if (m_pentTarget && OFFSET(pOther->pev) == OFFSET(m_pentTarget)) { CAI_BaseNPC *pTarget = GetClassPtr((CAI_BaseNPC *)VARS(m_pentTarget)); @@ -596,7 +613,7 @@ CAI_BaseNPC *CAI_ScriptedSequence::FindScriptEntity( ) else if (!(m_spawnflags & SF_SCRIPT_NO_COMPLAINTS)) { // They cannot play the script. - DevMsg( "Found %s, but can't play!\n", STRING( m_iszEntity )); + ScriptMsg1( 1, "Found %s, but can't play!\n", STRING( m_iszEntity )); } } @@ -683,7 +700,7 @@ void CAI_ScriptedSequence::StartScript( void ) // Don't clear the currently playing script's target! pCine->SetTarget( NULL ); } - DevMsg( 2, "script \"%s\" kicking script \"%s\" out of the queue\n", GetDebugName(), pCine->GetDebugName() ); + ScriptMsg2( 2, "script \"%s\" kicking script \"%s\" out of the queue\n", GetDebugName(), pCine->GetDebugName() ); } pTarget->m_hCine->m_hNextCine = this; @@ -789,7 +806,7 @@ void CAI_ScriptedSequence::StartScript( void ) //pTarget->SetGroundEntity( NULL ); break; } - //DevMsg( 2, "\"%s\" found and used (INT: %s)\n", STRING( pTarget->m_iName ), FBitSet(m_spawnflags, SF_SCRIPT_NOINTERRUPT)?"No":"Yes" ); + //ScriptMsg2( 2, "\"%s\" found and used (INT: %s)\n", STRING( pTarget->m_iName ), FBitSet(m_spawnflags, SF_SCRIPT_NOINTERRUPT)?"No":"Yes" ); // Wait until all scripts of the same name are ready to play. @@ -824,12 +841,12 @@ void CAI_ScriptedSequence::ScriptThink( void ) else if (FindEntity()) { StartScript( ); - DevMsg( 2, "scripted_sequence %d:\"%s\" using NPC %d:\"%s\"(%s)\n", entindex(), GetDebugName(), GetTarget()->entindex(), GetTarget()->GetEntityName().ToCStr(), STRING( m_iszEntity ) ); + ScriptMsg5( 2, "scripted_sequence %d:\"%s\" using NPC %d:\"%s\"(%s)\n", entindex(), GetDebugName(), GetTarget()->entindex(), GetTarget()->GetEntityName().ToCStr(), STRING( m_iszEntity ) ); } else { CancelScript( ); - DevMsg( 2, "scripted_sequence %d:\"%s\" can't find NPC \"%s\"\n", entindex(), GetDebugName(), STRING( m_iszEntity ) ); + ScriptMsg3( 2, "scripted_sequence %d:\"%s\" can't find NPC \"%s\"\n", entindex(), GetDebugName(), STRING( m_iszEntity ) ); // FIXME: just trying again is bad. This should fire an output instead. // FIXME: Think about puting output triggers in both StartScript() and CancelScript(). SetNextThink( gpGlobals->curtime + 1.0f ); @@ -902,7 +919,7 @@ bool CAI_ScriptedSequence::StartSequence( CAI_BaseNPC *pTarget, string_t iszSeq, // Don't blend... pTarget->IncrementInterpolationFrame(); } - //DevMsg( 2, "%s (%s): started \"%s\":INT:%s\n", STRING( pTarget->m_iName ), pTarget->GetClassname(), STRING( iszSeq), (m_spawnflags & SF_SCRIPT_NOINTERRUPT) ? "No" : "Yes" ); + //ScriptMsg4( 2, "%s (%s): started \"%s\":INT:%s\n", STRING( pTarget->m_iName ), pTarget->GetClassname(), STRING( iszSeq), (m_spawnflags & SF_SCRIPT_NOINTERRUPT) ? "No" : "Yes" ); return true; } @@ -982,7 +999,7 @@ bool CAI_ScriptedSequence::FinishedActionSequence( CAI_BaseNPC *pNPC ) //----------------------------------------------------------------------------- void CAI_ScriptedSequence::SequenceDone( CAI_BaseNPC *pNPC ) { - //DevMsg( 2, "Sequence %s finished\n", STRING( pNPC->m_hCine->m_iszPlay ) ); + //ScriptMsg1( 2, "Sequence %s finished\n", STRING( pNPC->m_hCine->m_iszPlay ) ); //Msg("%s SequenceDone() at %0.2f\n", pNPC->GetDebugName(), gpGlobals->curtime ); @@ -1092,7 +1109,7 @@ void CAI_ScriptedSequence::PostIdleDone( CAI_BaseNPC *pNPC ) // Only do so if we're selected, to prevent spam if ( pNPC->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) { - DevMsg( 2, "Post Idle %s finished for %s\n", STRING( pNPC->m_hCine->m_iszPostIdle ), pNPC->GetDebugName() ); + ScriptMsg2( 2, "Post Idle %s finished for %s\n", STRING( pNPC->m_hCine->m_iszPostIdle ), pNPC->GetDebugName() ); } pNPC->m_scriptState = CAI_BaseNPC::SCRIPT_POST_IDLE; @@ -1258,7 +1275,7 @@ bool CAI_ScriptedSequence::CanEnqueueAfter( void ) if ( m_iszNextScript != NULL_STRING ) { - DevMsg( 2, "%s is specified as the 'Next Script' and cannot be kicked out of the queue\n", m_hNextCine->GetDebugName() ); + ScriptMsg1( 2, "%s is specified as the 'Next Script' and cannot be kicked out of the queue\n", m_hNextCine->GetDebugName() ); return false; } @@ -1267,7 +1284,7 @@ bool CAI_ScriptedSequence::CanEnqueueAfter( void ) return true; } - DevMsg( 2, "%s is a priority script and cannot be kicked out of the queue\n", m_hNextCine->GetDebugName() ); + ScriptMsg1( 2, "%s is a priority script and cannot be kicked out of the queue\n", m_hNextCine->GetDebugName() ); return false; } @@ -1402,7 +1419,7 @@ void CAI_ScriptedSequence::ModifyScriptedAutoMovement( Vector *vecNewPos ) //----------------------------------------------------------------------------- void CAI_ScriptedSequence::CancelScript( void ) { - DevMsg( 2, "Cancelling script: %s\n", STRING( m_iszPlay )); + ScriptMsg1( 2, "Cancelling script: %s\n", STRING( m_iszPlay )); // Don't cancel matching sequences if we're asked not to, unless we didn't actually // succeed in starting, in which case we should always cancel. This fixes @@ -1732,7 +1749,7 @@ void CAI_ScriptedSchedule::ScriptThink( void ) pTarget = FindScriptEntity( (m_spawnflags & SF_SCRIPT_SEARCH_CYCLICALLY) != 0 ); if ( pTarget ) { - DevMsg( 2, "scripted_schedule \"%s\" using NPC \"%s\"(%s)\n", GetDebugName(), STRING( m_iszEntity ), pTarget->GetEntityName().ToCStr() ); + ScriptMsg3( 2, "scripted_schedule \"%s\" using NPC \"%s\"(%s)\n", GetDebugName(), STRING( m_iszEntity ), pTarget->GetEntityName().ToCStr() ); StartSchedule( pTarget ); success = true; } @@ -1742,7 +1759,7 @@ void CAI_ScriptedSchedule::ScriptThink( void ) m_hLastFoundEntity = NULL; while ( ( pTarget = FindScriptEntity( true ) ) != NULL ) { - DevMsg( 2, "scripted_schedule \"%s\" using NPC \"%s\"(%s)\n", GetDebugName(), pTarget->GetEntityName().ToCStr(), STRING( m_iszEntity ) ); + ScriptMsg3( 2, "scripted_schedule \"%s\" using NPC \"%s\"(%s)\n", GetDebugName(), pTarget->GetEntityName().ToCStr(), STRING( m_iszEntity ) ); StartSchedule( pTarget ); success = true; } @@ -1750,7 +1767,7 @@ void CAI_ScriptedSchedule::ScriptThink( void ) if ( !success ) { - DevMsg( 2, "scripted_schedule \"%s\" can't find NPC \"%s\"\n", GetDebugName(), STRING( m_iszEntity ) ); + ScriptMsg2( 2, "scripted_schedule \"%s\" can't find NPC \"%s\"\n", GetDebugName(), STRING( m_iszEntity ) ); // FIXME: just trying again is bad. This should fire an output instead. // FIXME: Think about puting output triggers on success true and sucess false // FIXME: also needs to check the result of StartSchedule(), which can fail and not complain @@ -1811,7 +1828,7 @@ void CAI_ScriptedSchedule::StartSchedule( CAI_BaseNPC *pTarget ) CAI_Hint *pHint = CAI_HintManager::FindHint( pTarget->GetAbsOrigin(), hintCriteria ); if ( !pHint ) { - DevMsg( 1, "Can't find goal entity %s\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); + ScriptMsg2( 1, "Can't find goal entity %s\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); return; } pGoalEnt = pHint; @@ -1852,7 +1869,7 @@ void CAI_ScriptedSchedule::StartSchedule( CAI_BaseNPC *pTarget ) pTarget->SetCondition( COND_SCHEDULE_DONE ); } else - DevMsg( "Scripted schedule %s specified an invalid enemy %s\n", STRING( GetEntityName() ), STRING( m_sGoalEnt ) ); + ScriptMsg2( 1, "Scripted schedule %s specified an invalid enemy %s\n", STRING( GetEntityName() ), STRING( m_sGoalEnt ) ); } bool bDidSetSchedule = false; @@ -1877,7 +1894,7 @@ void CAI_ScriptedSchedule::StartSchedule( CAI_BaseNPC *pTarget ) { if (!(m_spawnflags & SF_SCRIPT_NO_COMPLAINTS)) { - DevMsg( 1, "ScheduledMoveToGoalEntity to goal entity %s failed\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); + ScriptMsg2( 1, "ScheduledMoveToGoalEntity to goal entity %s failed\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); } return; } @@ -1899,7 +1916,7 @@ void CAI_ScriptedSchedule::StartSchedule( CAI_BaseNPC *pTarget ) { if (!(m_spawnflags & SF_SCRIPT_NO_COMPLAINTS)) { - DevMsg( 1, "ScheduledFollowPath to goal entity %s failed\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); + ScriptMsg2( 1, "ScheduledFollowPath to goal entity %s failed\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); } return; } @@ -1924,7 +1941,7 @@ void CAI_ScriptedSchedule::InputStartSchedule( inputdata_t &inputdata ) { if (( m_nForceState == 0 ) && ( m_nSchedule == 0 )) { - DevMsg( 2, "aiscripted_schedule - no schedule or state has been set!\n" ); + ScriptMsg( 2, "aiscripted_schedule - no schedule or state has been set!\n" ); } if ( !m_bDidFireOnce || ( m_spawnflags & SF_SCRIPT_REPEATABLE ) ) @@ -1936,7 +1953,7 @@ void CAI_ScriptedSchedule::InputStartSchedule( inputdata_t &inputdata ) } else { - DevMsg( 2, "aiscripted_schedule - not playing schedule again: not flagged to repeat\n" ); + ScriptMsg( 2, "aiscripted_schedule - not playing schedule again: not flagged to repeat\n" ); } } @@ -1947,7 +1964,7 @@ void CAI_ScriptedSchedule::InputStopSchedule( inputdata_t &inputdata ) { if ( !m_bDidFireOnce ) { - DevMsg( 2, "aiscripted_schedule - StopSchedule called, but schedule's never started.\n" ); + ScriptMsg( 2, "aiscripted_schedule - StopSchedule called, but schedule's never started.\n" ); return; } @@ -1988,7 +2005,7 @@ void CAI_ScriptedSchedule::StopSchedule( CAI_BaseNPC *pTarget ) { if ( pTarget->IsCurSchedule( SCHED_IDLE_WALK ) ) { - DevMsg( 2, "%s (%s): StopSchedule called on NPC %s.\n", GetClassname(), GetDebugName(), pTarget->GetDebugName() ); + ScriptMsg3( 2, "%s (%s): StopSchedule called on NPC %s.\n", GetClassname(), GetDebugName(), pTarget->GetDebugName() ); pTarget->ClearSchedule( "Stopping scripted schedule" ); } } @@ -2272,7 +2289,7 @@ int CAI_ScriptedSentence::StartSentence( CAI_BaseNPC *pTarget ) { if ( !pTarget ) { - DevMsg( 2, "Not Playing sentence %s\n", STRING(m_iszSentence) ); + ScriptMsg1( 2, "Not Playing sentence %s\n", STRING(m_iszSentence) ); return -1; } @@ -2297,7 +2314,7 @@ int CAI_ScriptedSentence::StartSentence( CAI_BaseNPC *pTarget ) } int sentenceIndex = pTarget->PlayScriptedSentence( STRING(m_iszSentence), m_flDelay, m_flVolume, m_iSoundLevel, bConcurrent, pListener ); - DevMsg( 2, "Playing sentence %s\n", STRING(m_iszSentence) ); + ScriptMsg1( 2, "Playing sentence %s\n", STRING(m_iszSentence) ); m_OnBeginSentence.FireOutput(NULL, this); diff --git a/sp/src/game/server/server_mapbase.vpc b/sp/src/game/server/server_mapbase.vpc index 6a0cb613..c0e0d6b7 100644 --- a/sp/src/game/server/server_mapbase.vpc +++ b/sp/src/game/server/server_mapbase.vpc @@ -35,10 +35,13 @@ $Project $File "$SRCDIR\game\shared\mapbase\matchers.h" $File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT] - $File "$SRCDIR\game\shared\mapbase\vscript_funcs_math.cpp" [$MAPBASE_VSCRIPT] - $File "$SRCDIR\game\shared\mapbase\vscript_funcs_math.h" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\vscript_singletons.h" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\vscript_funcs_hl2.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\vscript_consts_shared.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\vscript_consts_weapons.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT] $File "mapbase\ai_grenade.cpp" $File "mapbase\ai_grenade.h" diff --git a/sp/src/game/server/triggers.cpp b/sp/src/game/server/triggers.cpp index 7f2f1f08..03e23cb7 100644 --- a/sp/src/game/server/triggers.cpp +++ b/sp/src/game/server/triggers.cpp @@ -138,6 +138,14 @@ BEGIN_ENT_SCRIPTDESC( CBaseTrigger, CBaseEntity, "Trigger entity" ) DEFINE_SCRIPTFUNC( Disable, "" ) DEFINE_SCRIPTFUNC( TouchTest, "" ) DEFINE_SCRIPTFUNC_NAMED( ScriptIsTouching, "IsTouching", "Checks whether the passed entity is touching the trigger." ) + + DEFINE_SCRIPTFUNC( UsesFilter, "Returns true if this trigger uses a filter." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptPassesTriggerFilters, "PassesTriggerFilters", "Returns whether a target entity satisfies the trigger's spawnflags, filter, etc." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetTouchedEntityOfType, "GetTouchedEntityOfType", "Gets the first touching entity which matches the specified class." ) + + DEFINE_SCRIPTFUNC( PointIsWithin, "Checks if the given vector is within the trigger's volume." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetTouchingEntities, "GetTouchingEntities", "Gets all entities touching this trigger (and satisfying its criteria). This function copies them to a table with a maximum number of elements." ) END_SCRIPTDESC(); #endif // MAPBASE_VSCRIPT @@ -616,6 +624,19 @@ void CBaseTrigger::InputToggle( inputdata_t &inputdata ) PhysicsTouchTriggers(); } +#ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// Purpose: Copies touching entities to a script table +//----------------------------------------------------------------------------- +void CBaseTrigger::ScriptGetTouchingEntities( HSCRIPT hTable ) +{ + for (int i = 0; i < m_hTouchingEntities.Count(); i++) + { + g_pScriptVM->ArrayAppend( hTable, ToHScript( m_hTouchingEntities[i] ) ); + } +} +#endif + //----------------------------------------------------------------------------- // Purpose: Removes anything that touches it. If the trigger has a targetname, @@ -2300,6 +2321,11 @@ public: void Touch( CBaseEntity *pOther ); void Untouch( CBaseEntity *pOther ); +#ifdef MAPBASE + void InputSetSpeed( inputdata_t &inputdata ); + void InputSetPushDir( inputdata_t &inputdata ); +#endif + Vector m_vecPushDir; DECLARE_DATADESC(); @@ -2312,6 +2338,10 @@ BEGIN_DATADESC( CTriggerPush ) DEFINE_KEYFIELD( m_vecPushDir, FIELD_VECTOR, "pushdir" ), DEFINE_KEYFIELD( m_flAlternateTicksFix, FIELD_FLOAT, "alternateticksfix" ), //DEFINE_FIELD( m_flPushSpeed, FIELD_FLOAT ), +#ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ), + DEFINE_INPUTFUNC( FIELD_VECTOR, "SetPushDir", InputSetPushDir ), +#endif END_DATADESC() LINK_ENTITY_TO_CLASS( trigger_push, CTriggerPush ); @@ -2458,6 +2488,35 @@ void CTriggerPush::Touch( CBaseEntity *pOther ) } } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerPush::InputSetSpeed( inputdata_t &inputdata ) +{ + m_flSpeed = inputdata.value.Float(); + + // Need to update push speed/alternative ticks + Activate(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerPush::InputSetPushDir( inputdata_t &inputdata ) +{ + inputdata.value.Vector3D( m_vecPushDir ); + + // Convert pushdir from angles to a vector + Vector vecAbsDir; + QAngle angPushDir = QAngle( m_vecPushDir.x, m_vecPushDir.y, m_vecPushDir.z ); + AngleVectors( angPushDir, &vecAbsDir ); + + // Transform the vector into entity space + VectorIRotate( vecAbsDir, EntityToWorldTransform(), m_vecPushDir ); +} +#endif + //----------------------------------------------------------------------------- // Teleport trigger diff --git a/sp/src/game/server/triggers.h b/sp/src/game/server/triggers.h index 1dc87e46..4aacad13 100644 --- a/sp/src/game/server/triggers.h +++ b/sp/src/game/server/triggers.h @@ -95,6 +95,13 @@ public: bool PointIsWithin( const Vector &vecPoint ); +#ifdef MAPBASE_VSCRIPT + bool ScriptPassesTriggerFilters( HSCRIPT hOther ) { return ToEnt(hOther) ? PassesTriggerFilters( ToEnt(hOther) ) : NULL; } + HSCRIPT ScriptGetTouchedEntityOfType( const char *sClassName ) { return ToHScript( GetTouchedEntityOfType(sClassName) ); } + + void ScriptGetTouchingEntities( HSCRIPT hTable ); +#endif + bool m_bDisabled; string_t m_iFilterName; CHandle m_hFilter; diff --git a/sp/src/game/server/util.cpp b/sp/src/game/server/util.cpp index a80e8fca..8a97695a 100644 --- a/sp/src/game/server/util.cpp +++ b/sp/src/game/server/util.cpp @@ -1072,7 +1072,7 @@ void UTIL_ScreenFade( CBaseEntity *pEntity, const color32 &color, float fadeTime } -void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, const char *pMessage ) +void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, const char *pMessage, const char *pszFont, bool bAutobreak ) { CRecipientFilter filter; @@ -1105,12 +1105,19 @@ void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, c WRITE_FLOAT( textparms.holdTime ); WRITE_FLOAT( textparms.fxTime ); WRITE_STRING( pMessage ); +#ifdef MAPBASE + WRITE_STRING( pszFont ); + if (bAutobreak) + { + WRITE_BYTE ( Q_strlen( pMessage ) ); + } +#endif MessageEnd(); } -void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage ) +void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage, const char *pszFont, bool bAutobreak ) { - UTIL_HudMessage( NULL, textparms, pMessage ); + UTIL_HudMessage( NULL, textparms, pMessage, pszFont, bAutobreak ); } void UTIL_HudHintText( CBaseEntity *pEntity, const char *pMessage ) diff --git a/sp/src/game/server/util.h b/sp/src/game/server/util.h index d7e7ae73..82f485ba 100644 --- a/sp/src/game/server/util.h +++ b/sp/src/game/server/util.h @@ -512,8 +512,8 @@ void UTIL_SetModel( CBaseEntity *pEntity, const char *pModelName ); // prints as transparent 'title' to the HUD -void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage ); -void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, const char *pMessage ); +void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage, const char *pszFont = NULL, bool bAutobreak = false ); +void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, const char *pMessage, const char *pszFont = NULL, bool bAutobreak = false ); // brings up hud keyboard hints display void UTIL_HudHintText( CBaseEntity *pEntity, const char *pMessage ); diff --git a/sp/src/game/server/vscript_server.cpp b/sp/src/game/server/vscript_server.cpp index 44234516..315e2a6d 100644 --- a/sp/src/game/server/vscript_server.cpp +++ b/sp/src/game/server/vscript_server.cpp @@ -135,6 +135,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptEntityIterator, "CEntities", SCRIPT_SINGLETO #endif END_SCRIPTDESC(); +#ifndef MAPBASE_VSCRIPT // Mapbase adds this to the base library so that CScriptKeyValues can be accessed anywhere, like VBSP. // ---------------------------------------------------------------------------- // KeyValues access - CBaseEntity::ScriptGetKeyFromModel returns root KeyValues // ---------------------------------------------------------------------------- @@ -150,24 +151,6 @@ BEGIN_SCRIPTDESC_ROOT( CScriptKeyValues, "Wrapper class over KeyValues instance" DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueString, "GetKeyString", "Given a KeyValues object and a key name, return associated string value" ); DEFINE_SCRIPTFUNC_NAMED( ScriptIsKeyValueEmpty, "IsKeyEmpty", "Given a KeyValues object and a key name, return true if key name has no value" ); DEFINE_SCRIPTFUNC_NAMED( ScriptReleaseKeyValues, "ReleaseKeyValues", "Given a root KeyValues object, release its contents" ); -#ifdef MAPBASE_VSCRIPT - DEFINE_SCRIPTFUNC_NAMED( ScriptGetName, "GetName", "Given a KeyValues object, return its name" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptGetInt, "GetInt", "Given a KeyValues object, return its own associated integer value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptGetFloat, "GetFloat", "Given a KeyValues object, return its own associated float value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptGetString, "GetString", "Given a KeyValues object, return its own associated string value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptGetBool, "GetBool", "Given a KeyValues object, return its own associated bool value" ); - - DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueInt, "SetKeyInt", "Given a KeyValues object and a key name, set associated integer value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueFloat, "SetKeyFloat", "Given a KeyValues object and a key name, set associated float value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueBool, "SetKeyBool", "Given a KeyValues object and a key name, set associated bool value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueString, "SetKeyString", "Given a KeyValues object and a key name, set associated string value" ); - - DEFINE_SCRIPTFUNC_NAMED( ScriptSetName, "SetName", "Given a KeyValues object, set its name" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetInt, "SetInt", "Given a KeyValues object, set its own associated integer value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetFloat, "SetFloat", "Given a KeyValues object, set its own associated float value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetBool, "SetBool", "Given a KeyValues object, set its own associated bool value" ); - DEFINE_SCRIPTFUNC_NAMED( ScriptSetString, "SetString", "Given a KeyValues object, set its own associated string value" ); -#endif END_SCRIPTDESC(); HSCRIPT CScriptKeyValues::ScriptFindKey( const char *pszName ) @@ -245,84 +228,6 @@ void CScriptKeyValues::ScriptReleaseKeyValues( ) m_pKeyValues = NULL; } -#ifdef MAPBASE_VSCRIPT -const char *CScriptKeyValues::ScriptGetName() -{ - const char *psz = m_pKeyValues->GetName(); - return psz; -} - -int CScriptKeyValues::ScriptGetInt() -{ - int i = m_pKeyValues->GetInt(); - return i; -} - -float CScriptKeyValues::ScriptGetFloat() -{ - float f = m_pKeyValues->GetFloat(); - return f; -} - -const char *CScriptKeyValues::ScriptGetString() -{ - const char *psz = m_pKeyValues->GetString(); - return psz; -} - -bool CScriptKeyValues::ScriptGetBool() -{ - bool b = m_pKeyValues->GetBool(); - return b; -} - - -void CScriptKeyValues::ScriptSetKeyValueInt( const char *pszName, int iValue ) -{ - m_pKeyValues->SetInt( pszName, iValue ); -} - -void CScriptKeyValues::ScriptSetKeyValueFloat( const char *pszName, float flValue ) -{ - m_pKeyValues->SetFloat( pszName, flValue ); -} - -void CScriptKeyValues::ScriptSetKeyValueString( const char *pszName, const char *pszValue ) -{ - m_pKeyValues->SetString( pszName, pszValue ); -} - -void CScriptKeyValues::ScriptSetKeyValueBool( const char *pszName, bool bValue ) -{ - m_pKeyValues->SetBool( pszName, bValue ); -} - -void CScriptKeyValues::ScriptSetName( const char *pszValue ) -{ - m_pKeyValues->SetName( pszValue ); -} - -void CScriptKeyValues::ScriptSetInt( int iValue ) -{ - m_pKeyValues->SetInt( NULL, iValue ); -} - -void CScriptKeyValues::ScriptSetFloat( float flValue ) -{ - m_pKeyValues->SetFloat( NULL, flValue ); -} - -void CScriptKeyValues::ScriptSetString( const char *pszValue ) -{ - m_pKeyValues->SetString( NULL, pszValue ); -} - -void CScriptKeyValues::ScriptSetBool( bool bValue ) -{ - m_pKeyValues->SetBool( NULL, bValue ); -} -#endif - // constructors CScriptKeyValues::CScriptKeyValues( KeyValues *pKeyValues = NULL ) @@ -339,12 +244,13 @@ CScriptKeyValues::~CScriptKeyValues( ) } m_pKeyValues = NULL; } +#endif #ifdef MAPBASE_VSCRIPT #define RETURN_IF_CANNOT_DRAW_OVERLAY\ if (engine->IsPaused())\ {\ - DevWarning("debugoverlay: cannot draw while the game is paused!\n");\ + CGWarning( 1, CON_GROUP_VSCRIPT, "debugoverlay: cannot draw while the game is paused!\n");\ return;\ } class CDebugOverlayScriptHelper @@ -815,7 +721,11 @@ static void SendToConsole( const char *pszCommand ) CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost(); if ( !pPlayer ) { +#ifdef MAPBASE + CGMsg( 1, CON_GROUP_VSCRIPT, "Cannot execute \"%s\", no player\n", pszCommand ); +#else DevMsg ("Cannot execute \"%s\", no player\n", pszCommand ); +#endif return; } @@ -937,7 +847,7 @@ static void DoEntFireByInstanceHandle( HSCRIPT hTarget, const char *pszAction, c if ( !pTarget ) { - Warning( "VScript error: DoEntFire was passed an invalid entity instance.\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "VScript error: DoEntFire was passed an invalid entity instance.\n" ); #ifdef MAPBASE_VSCRIPT return 0; #else @@ -977,6 +887,12 @@ static float GetEntityIOEventTimeLeft( int event ) { return g_EventQueue.GetTimeLeft(event); } + +// vscript_server.nut adds this to the base CConvars class +static const char *ScriptGetClientConvarValue( const char *pszConVar, int entindex ) +{ + return engine->GetClientConVarValue( entindex, pszConVar ); +} #endif // MAPBASE_VSCRIPT bool VScriptServerInit() @@ -1022,7 +938,7 @@ bool VScriptServerInit() #endif else { - DevWarning("-server_script does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage ); + CGWarning( 1, CON_GROUP_VSCRIPT, "-server_script does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage ); scriptLanguage = SL_NONE; } @@ -1035,7 +951,7 @@ bool VScriptServerInit() if( g_pScriptVM ) { #ifdef MAPBASE_VSCRIPT - Log( "VSCRIPT SERVER: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); + CGMsg( 0, CON_GROUP_VSCRIPT, "VSCRIPT SERVER: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); #else Log( "VSCRIPT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); #endif @@ -1068,6 +984,7 @@ bool VScriptServerInit() ScriptRegisterFunction( g_pScriptVM, CancelEntityIOEvent, "Remove entity I/O event." ); ScriptRegisterFunction( g_pScriptVM, GetEntityIOEventTimeLeft, "Get time left on entity I/O event." ); + ScriptRegisterFunction( g_pScriptVM, ScriptGetClientConvarValue, SCRIPT_HIDE ); #else ScriptRegisterFunction( g_pScriptVM, DoEntFire, SCRIPT_ALIAS( "EntFire", "Generate and entity i/o event" ) ); ScriptRegisterFunctionNamed( g_pScriptVM, DoEntFireByInstanceHandle, "EntFireByHandle", "Generate and entity i/o event. First parameter is an entity instance." ); @@ -1120,13 +1037,13 @@ bool VScriptServerInit() } else { - DevWarning("VM Did not start!\n"); + CGWarning( 1, CON_GROUP_VSCRIPT, "VM Did not start!\n" ); } } } else { - Log( "\nVSCRIPT: Scripting is disabled.\n" ); + CGMsg( 0, CON_GROUP_VSCRIPT, "\nVSCRIPT: Scripting is disabled.\n" ); } g_pScriptVM = NULL; return false; @@ -1171,13 +1088,13 @@ CON_COMMAND( script_reload_code, "Execute a vscript file, replacing existing fun { if ( !*args[1] ) { - Warning( "No script specified\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "No script specified\n" ); return; } if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } @@ -1196,7 +1113,7 @@ CON_COMMAND( script_reload_entity_code, "Execute all of this entity's VScripts, if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } @@ -1234,7 +1151,7 @@ CON_COMMAND( script_reload_think, "Execute an activation script, replacing exist if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } diff --git a/sp/src/game/server/vscript_server.h b/sp/src/game/server/vscript_server.h index f2cd0ab3..6a7d44d1 100644 --- a/sp/src/game/server/vscript_server.h +++ b/sp/src/game/server/vscript_server.h @@ -32,6 +32,7 @@ extern CBaseEntityScriptInstanceHelper g_BaseEntityScriptInstanceHelper; // Only allow scripts to create entities during map initialization bool IsEntityCreationAllowedInScripts( void ); +#ifndef MAPBASE_VSCRIPT // Mapbase adds this to the base library so that CScriptKeyValues can be accessed anywhere, like VBSP. // ---------------------------------------------------------------------------- // KeyValues access // ---------------------------------------------------------------------------- @@ -50,25 +51,9 @@ public: bool ScriptIsKeyValueEmpty( const char *pszName ); bool ScriptGetKeyValueBool( const char *pszName ); void ScriptReleaseKeyValues( ); -#ifdef MAPBASE_VSCRIPT - const char *ScriptGetName(); - int ScriptGetInt(); - float ScriptGetFloat(); - const char *ScriptGetString(); - bool ScriptGetBool(); - - void ScriptSetKeyValueInt( const char *pszName, int iValue ); - void ScriptSetKeyValueFloat( const char *pszName, float flValue ); - void ScriptSetKeyValueString( const char *pszName, const char *pszValue ); - void ScriptSetKeyValueBool( const char *pszName, bool bValue ); - void ScriptSetName( const char *pszValue ); - void ScriptSetInt( int iValue ); - void ScriptSetFloat( float flValue ); - void ScriptSetString( const char *pszValue ); - void ScriptSetBool( bool bValue ); -#endif KeyValues *m_pKeyValues; // actual KeyValue entity }; +#endif #endif // VSCRIPT_SERVER_H diff --git a/sp/src/game/server/vscript_server.nut b/sp/src/game/server/vscript_server.nut index 5294ab4b..17ba64d3 100644 --- a/sp/src/game/server/vscript_server.nut +++ b/sp/src/game/server/vscript_server.nut @@ -59,6 +59,19 @@ function EntFireByHandle( target, action, value = null, delay = 0.0, activator = return DoEntFireByInstanceHandle( target, action.tostring(), value.tostring(), delay, activator, caller ); } +function DispatchParticleEffect( particleName, origin, angles, entity = null ) +{ + DoDispatchParticleEffect( particleName, origin, angles, entity ); +} + +// CConvars is declared within the library +function CConvars::GetClientConvarValue(cvar,idx) +{ + return ::ScriptGetClientConvarValue(cvar,idx); +} + +RegisterHelp( "CConvars::GetClientConvarValue", "CConvars::GetClientConvarValue(string, int)", "Returns the convar value for the entindex as a string. Only works with client convars with the FCVAR_USERINFO flag." ); + function __ReplaceClosures( script, scope ) { if ( !scope ) diff --git a/sp/src/game/shared/basecombatweapon_shared.cpp b/sp/src/game/shared/basecombatweapon_shared.cpp index d63f961b..16cc766d 100644 --- a/sp/src/game/shared/basecombatweapon_shared.cpp +++ b/sp/src/game/shared/basecombatweapon_shared.cpp @@ -242,7 +242,13 @@ void CBaseCombatWeapon::Precache( void ) // Add this weapon to the weapon registry, and get our index into it // Get weapon data from script file +#ifdef MAPBASE + // Allow custom scripts to be loaded on a map-by-map basis + if ( ReadCustomWeaponDataFromFileForSlot( filesystem, GetWeaponScriptName(), &m_hWeaponFileInfo, GetEncryptionKey() ) || + ReadWeaponDataFromFileForSlot( filesystem, GetWeaponScriptName(), &m_hWeaponFileInfo, GetEncryptionKey() ) ) +#else if ( ReadWeaponDataFromFileForSlot( filesystem, GetClassname(), &m_hWeaponFileInfo, GetEncryptionKey() ) ) +#endif { // Get the ammo indexes for the ammo's specified in the data file if ( GetWpnData().szAmmo1[0] ) @@ -2728,6 +2734,24 @@ Activity CBaseCombatWeapon::ActivityOverride( Activity baseAct, bool *pRequired return baseAct; } +#ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +HSCRIPT CBaseCombatWeapon::ScriptGetOwner() +{ + return ToHScript( GetOwner() ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseCombatWeapon::ScriptSetOwner( HSCRIPT owner ) +{ + return SetOwner( ToEnt( owner ) ? ToEnt( owner )->MyCombatCharacterPointer() : NULL ); +} +#endif + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -2865,6 +2889,9 @@ IMPLEMENT_NETWORKCLASS_ALIASED( BaseCombatWeapon, DT_BaseCombatWeapon ) #ifdef MAPBASE_VSCRIPT BEGIN_ENT_SCRIPTDESC( CBaseCombatWeapon, CBaseAnimating, "The base class for all equippable weapons." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetOwner, "GetOwner", "Get the weapon's owner." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptSetOwner, "SetOwner", "Set the weapon's owner." ) + DEFINE_SCRIPTFUNC( Clip1, "Get the weapon's current primary ammo." ) DEFINE_SCRIPTFUNC( Clip2, "Get the weapon's current secondary ammo." ) DEFINE_SCRIPTFUNC_NAMED( ScriptSetClip1, "SetClip1", "Set the weapon's current primary ammo." ) @@ -2893,6 +2920,7 @@ BEGIN_ENT_SCRIPTDESC( CBaseCombatWeapon, CBaseAnimating, "The base class for all DEFINE_SCRIPTFUNC( SetSubType, "Set the weapon's subtype." ) DEFINE_SCRIPTFUNC( GetFireRate, "Get the weapon's firing rate." ) + DEFINE_SCRIPTFUNC( AddViewKick, "Applies the weapon's view kick." ) DEFINE_SCRIPTFUNC( GetWorldModel, "Get the weapon's world model." ) DEFINE_SCRIPTFUNC( GetViewModel, "Get the weapon's view model." ) @@ -2901,6 +2929,44 @@ BEGIN_ENT_SCRIPTDESC( CBaseCombatWeapon, CBaseAnimating, "The base class for all DEFINE_SCRIPTFUNC( CanBePickedUpByNPCs, "Check if the weapon can be picked up by NPCs." ) +#ifndef CLIENT_DLL + DEFINE_SCRIPTFUNC( CapabilitiesGet, "Get the capabilities the weapon currently possesses." ) +#endif + + DEFINE_SCRIPTFUNC( HasWeaponIdleTimeElapsed, "Returns true if the idle time has elapsed." ) + DEFINE_SCRIPTFUNC( GetWeaponIdleTime, "Returns the next time WeaponIdle() will run." ) + DEFINE_SCRIPTFUNC( SetWeaponIdleTime, "Sets the next time WeaponIdle() will run." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptWeaponClassify, "WeaponClassify", "Returns the weapon's classify class from the WEPCLASS_ constant group" ) + DEFINE_SCRIPTFUNC_NAMED( ScriptWeaponSound, "WeaponSound", "Plays one of the weapon's sounds." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetBulletSpread, "GetBulletSpread", "Returns the weapon's default bullet spread." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetBulletSpreadForProficiency, "GetBulletSpreadForProficiency", "Returns the weapon's bullet spread for the specified proficiency level." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetPrimaryAttackActivity, "GetPrimaryAttackActivity", "Returns the weapon's primary attack activity." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetSecondaryAttackActivity, "GetSecondaryAttackActivity", "Returns the weapon's secondary attack activity." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetDrawActivity, "GetDrawActivity", "Returns the weapon's draw activity." ) + DEFINE_SCRIPTFUNC( GetDefaultAnimSpeed, "Returns the weapon's default animation speed." ) + DEFINE_SCRIPTFUNC( SendWeaponAnim, "Sends a weapon animation." ) + + DEFINE_SCRIPTFUNC( FiresUnderwater, "Returns true if this weapon can fire underwater." ) + DEFINE_SCRIPTFUNC( SetFiresUnderwater, "Sets whether this weapon can fire underwater." ) + DEFINE_SCRIPTFUNC( AltFiresUnderwater, "Returns true if this weapon can alt-fire underwater." ) + DEFINE_SCRIPTFUNC( SetAltFiresUnderwater, "Sets whether this weapon can alt-fire underwater." ) + DEFINE_SCRIPTFUNC( MinRange1, "Returns the closest this weapon can be used." ) + DEFINE_SCRIPTFUNC( SetMinRange1, "Sets the closest this weapon can be used." ) + DEFINE_SCRIPTFUNC( MinRange2, "Returns the closest this weapon can be used." ) + DEFINE_SCRIPTFUNC( SetMinRange2, "Sets the closest this weapon can be used." ) + DEFINE_SCRIPTFUNC( ReloadsSingly, "Returns true if this weapon reloads 1 round at a time." ) + DEFINE_SCRIPTFUNC( SetReloadsSingly, "Sets whether this weapon reloads 1 round at a time." ) + DEFINE_SCRIPTFUNC( FireDuration, "Returns the amount of time that the weapon has sustained firing." ) + DEFINE_SCRIPTFUNC( SetFireDuration, "Sets the amount of time that the weapon has sustained firing." ) + + DEFINE_SCRIPTFUNC( NextPrimaryAttack, "Returns the next time PrimaryAttack() will run when the player is pressing +ATTACK." ) + DEFINE_SCRIPTFUNC( SetNextPrimaryAttack, "Sets the next time PrimaryAttack() will run when the player is pressing +ATTACK." ) + DEFINE_SCRIPTFUNC( NextSecondaryAttack, "Returns the next time SecondaryAttack() will run when the player is pressing +ATTACK2." ) + DEFINE_SCRIPTFUNC( SetNextSecondaryAttack, "Sets the next time SecondaryAttack() will run when the player is pressing +ATTACK2." ) + END_SCRIPTDESC(); #endif diff --git a/sp/src/game/shared/basecombatweapon_shared.h b/sp/src/game/shared/basecombatweapon_shared.h index bd95b1f3..2d19727d 100644 --- a/sp/src/game/shared/basecombatweapon_shared.h +++ b/sp/src/game/shared/basecombatweapon_shared.h @@ -450,9 +450,49 @@ public: virtual bool ShouldUseLargeViewModelVROverride() { return false; } +#ifdef MAPBASE + // Gets the weapon script name to load. + virtual const char* GetWeaponScriptName() { return GetClassname(); } +#endif + #ifdef MAPBASE_VSCRIPT void ScriptSetClip1( int ammo ) { m_iClip1 = ammo; } void ScriptSetClip2( int ammo ) { m_iClip2 = ammo; } + + HSCRIPT ScriptGetOwner(); + void ScriptSetOwner( HSCRIPT owner ); + + int ScriptWeaponClassify() { return WeaponClassify(); } + void ScriptWeaponSound( int sound_type, float soundtime = 0.0f ) { WeaponSound( (WeaponSound_t)sound_type, soundtime ); } + + const Vector& ScriptGetBulletSpread( void ) { return GetBulletSpread(); } + Vector ScriptGetBulletSpreadForProficiency( int proficiency ) { return GetBulletSpread( (WeaponProficiency_t)proficiency ); } + + int ScriptGetPrimaryAttackActivity( void ) { return GetPrimaryAttackActivity(); } + int ScriptGetSecondaryAttackActivity( void ) { return GetSecondaryAttackActivity(); } + int ScriptGetDrawActivity( void ) { return GetDrawActivity(); } + + bool FiresUnderwater() { return m_bFiresUnderwater; } + void SetFiresUnderwater( bool bVal ) { m_bFiresUnderwater = bVal; } + bool AltFiresUnderwater() { return m_bAltFiresUnderwater; } + void SetAltFiresUnderwater( bool bVal ) { m_bAltFiresUnderwater = bVal; } + float MinRange1() { return m_fMinRange1; } + void SetMinRange1( float flVal ) { m_fMinRange1 = flVal; } + float MinRange2() { return m_fMinRange2; } + void SetMinRange2( float flVal ) { m_fMinRange2 = flVal; } + float MaxRange1() { return m_fMaxRange1; } + void SetMaxRange1( float flVal ) { m_fMaxRange1 = flVal; } + float MaxRange2() { return m_fMaxRange2; } + void SetMaxRange2( float flVal ) { m_fMaxRange2 = flVal; } + //bool ReloadsSingly() { return m_bReloadsSingly; } + void SetReloadsSingly( bool bVal ) { m_bReloadsSingly = bVal; } + float FireDuration() { return m_fFireDuration; } + void SetFireDuration( float flVal ) { m_fFireDuration = flVal; } + + float NextPrimaryAttack() { return m_flNextPrimaryAttack; } + void SetNextPrimaryAttack( float flVal ) { m_flNextPrimaryAttack = flVal; } + float NextSecondaryAttack() { return m_flNextSecondaryAttack; } + void SetNextSecondaryAttack( float flVal ) { m_flNextSecondaryAttack = flVal; } #endif public: diff --git a/sp/src/game/shared/baseentity_shared.cpp b/sp/src/game/shared/baseentity_shared.cpp index fecf60d2..3b656b7a 100644 --- a/sp/src/game/shared/baseentity_shared.cpp +++ b/sp/src/game/shared/baseentity_shared.cpp @@ -1613,21 +1613,19 @@ typedef CTraceFilterSimpleList CBulletsTraceFilter; void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) { #if defined(MAPBASE_VSCRIPT) && defined(GAME_DLL) - if (HSCRIPT hFunc = LookupScriptFunction("FireBullets")) + if (m_ScriptScope.IsInitialized()) { HSCRIPT hInfo = g_pScriptVM->RegisterInstance( const_cast(&info) ); - g_pScriptVM->SetValue( "info", hInfo ); - ScriptVariant_t functionReturn; - CallScriptFunctionHandle( hFunc, &functionReturn ); + ScriptVariant_t args[] = { hInfo }; + if (g_Hook_FireBullets.Call( m_ScriptScope, &functionReturn, args )) + { + if (!functionReturn.m_bool) + return; + } g_pScriptVM->RemoveInstance( hInfo ); - - g_pScriptVM->ClearValue( "info" ); - - if (!functionReturn.m_bool) - return; } #endif diff --git a/sp/src/game/shared/basegrenade_shared.cpp b/sp/src/game/shared/basegrenade_shared.cpp index e471d870..0d616099 100644 --- a/sp/src/game/shared/basegrenade_shared.cpp +++ b/sp/src/game/shared/basegrenade_shared.cpp @@ -74,6 +74,28 @@ void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const voi #endif +#ifdef MAPBASE_VSCRIPT +BEGIN_ENT_SCRIPTDESC( CBaseGrenade, CBaseAnimating, "The base class for grenades." ) + + DEFINE_SCRIPTFUNC( GetBlastForce, "Gets the grenade's blast force override. Grenades which use base damage force calculations return 0,0,0" ) + + DEFINE_SCRIPTFUNC( GetDamage, "Gets the grenade's blast damage." ) + DEFINE_SCRIPTFUNC( GetDamageRadius, "Gets the grenade's blast damage radius." ) + DEFINE_SCRIPTFUNC( SetDamage, "Sets the grenade's blast damage." ) + DEFINE_SCRIPTFUNC( SetDamageRadius, "Sets the grenade's blast damage radius." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetThrower, "GetThrower", "Gets the grenade's thrower." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptSetThrower, "SetThrower", "Sets the grenade's thrower." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetOriginalThrower, "GetOriginalThrower", "Gets the grenade's original thrower after the thrower was changed due to being picked up by a gravity gun or something." ) + + DEFINE_SCRIPTFUNC_NAMED( GetDetonateTime, "GetTimer", "Gets the grenade's detonate time if it has one." ) + DEFINE_SCRIPTFUNC( HasWarnedAI, "Whether or not the grenade has issued its DANGER sound to the world sound list yet." ) + DEFINE_SCRIPTFUNC( IsLive, "Whether or not the grenade has issued its DANGER sound to the world sound list yet." ) + DEFINE_SCRIPTFUNC( GetWarnAITime, "Gets the time at which the grenade will warn/has warned AI." ) + +END_SCRIPTDESC(); +#endif + IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenade, DT_BaseGrenade ) BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade ) diff --git a/sp/src/game/shared/basegrenade_shared.h b/sp/src/game/shared/basegrenade_shared.h index ba603d27..47840dc4 100644 --- a/sp/src/game/shared/basegrenade_shared.h +++ b/sp/src/game/shared/basegrenade_shared.h @@ -49,6 +49,9 @@ public: #if !defined( CLIENT_DLL ) DECLARE_DATADESC(); #endif +#ifdef MAPBASE_VSCRIPT + DECLARE_ENT_SCRIPTDESC(); +#endif virtual void Precache( void ); @@ -103,6 +106,17 @@ public: void SetThrower( CBaseCombatCharacter *pThrower ); CBaseEntity *GetOriginalThrower() { return m_hOriginalThrower; } +#ifdef MAPBASE_VSCRIPT + HSCRIPT ScriptGetThrower( void ) { return ToHScript( GetThrower() ); } + void ScriptSetThrower( HSCRIPT hThrower ) { SetThrower( ToEnt(hThrower) ? ToEnt(hThrower)->MyCombatCharacterPointer() : NULL ); } + HSCRIPT ScriptGetOriginalThrower() { return ToHScript( GetOriginalThrower() ); } + + float GetDetonateTime() { return m_flDetonateTime; } + bool HasWarnedAI() { return m_bHasWarnedAI; } + bool IsLive() { return m_bIsLive; } + float GetWarnAITime() { return m_flWarnAITime; } +#endif + #if !defined( CLIENT_DLL ) // Allow +USE pickup int ObjectCaps() diff --git a/sp/src/game/shared/choreoscene.h b/sp/src/game/shared/choreoscene.h index e4d22871..0cf281d6 100644 --- a/sp/src/game/shared/choreoscene.h +++ b/sp/src/game/shared/choreoscene.h @@ -84,6 +84,9 @@ public: // Event callback handler void SetEventCallbackInterface( IChoreoEventCallback *callback ); +#ifdef MAPBASE + IChoreoEventCallback *GetEventCallbackInterface() { return m_pIChoreoEventCallback; } +#endif // Loading bool ParseFromBuffer( char const *pFilename, ISceneTokenProcessor *tokenizer ); diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index dc7ef81d..74d64ad0 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -68,6 +68,9 @@ ConVar mapbase_load_actbusy("mapbase_load_actbusy", "1", FCVAR_ARCHIVE, "Should #endif #ifdef GAME_DLL +// This cvar should change with each Mapbase update +ConVar mapbase_version( "mapbase_version", "6.0", FCVAR_NONE, "The version of Mapbase currently being used in this mod." ); + extern void MapbaseGameLog_Init(); extern void ParseCustomActbusyFile(const char *file); @@ -173,7 +176,7 @@ public: #ifdef GAME_DLL if (g_bMapContainsCustomTalker && mapbase_flush_talker.GetBool()) { - DevMsg("Mapbase: Reloading response system to flush custom talker\n"); + CGMsg( 1, "Mapbase Misc.", "Mapbase: Reloading response system to flush custom talker\n" ); ReloadResponseSystem(); g_bMapContainsCustomTalker = false; } @@ -183,7 +186,7 @@ public: virtual void LevelInitPreEntity() { #ifdef GAME_DLL - Msg("Mapbase system loaded\n"); + CGMsg( 0, "Mapbase Misc.", "Mapbase system loaded\n" ); #endif // Checks gameinfo.txt for Mapbase-specific options @@ -347,11 +350,11 @@ public: return; } - DevMsg("===== Mapbase Manifest: Loading manifest file %s =====\n", file); + CGMsg( 1, "Mapbase Misc.", "===== Mapbase Manifest: Loading manifest file %s =====\n", file ); AddManifestFile(pKV, false); - DevMsg("==============================================================================\n"); + CGMsg( 1, "Mapbase Misc.", "==============================================================================\n" ); pKV->deleteThis(); } @@ -586,7 +589,7 @@ public: const char *scriptfile = STRING(m_target); if ( filesystem->FileExists( scriptfile, "MOD" ) ) { - Msg("Mapbase: Adding manifest file \"%s\"\n", scriptfile); + CGMsg(0, "Mapbase Misc.", "Mapbase: Adding manifest file \"%s\"\n", scriptfile); g_MapbaseSystem.AddManifestFile(scriptfile); } else diff --git a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp index a1c99405..a240633e 100644 --- a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp +++ b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp @@ -108,6 +108,8 @@ void RegisterActivityConstants() //============================================================================= //============================================================================= +extern void RegisterWeaponScriptConstants(); + void RegisterSharedScriptConstants() { // @@ -120,351 +122,346 @@ void RegisterSharedScriptConstants() ScriptRegisterFunction( g_pScriptVM, RegisterActivityConstants, "Registers all activity IDs as usable constants." ); - // - // Math/world - // - ScriptRegisterConstantNamed( g_pScriptVM, ((float)(180.f / M_PI_F)), "RAD2DEG", "" ); - ScriptRegisterConstantNamed( g_pScriptVM, ((float)(M_PI_F / 180.f)), "DEG2RAD", "" ); - ScriptRegisterConstant( g_pScriptVM, MAX_COORD_FLOAT, "" ); - ScriptRegisterConstant( g_pScriptVM, MAX_TRACE_LENGTH, "" ); - // // Damage Types // - ScriptRegisterConstant( g_pScriptVM, DMG_GENERIC, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_CRUSH, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_BULLET, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_SLASH, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_BURN, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_VEHICLE, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_FALL, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_BLAST, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_CLUB, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_SHOCK, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_SONIC, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_ENERGYBEAM, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_PREVENT_PHYSICS_FORCE, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_NEVERGIB, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_ALWAYSGIB, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_DROWN, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_PARALYZE, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_NERVEGAS, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_POISON, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_RADIATION, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_DROWNRECOVER, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_ACID, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_SLOWBURN, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_REMOVENORAGDOLL, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_PHYSGUN, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_PLASMA, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_AIRBOAT, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_DISSOLVE, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_BLAST_SURFACE, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_DIRECT, "" ); - ScriptRegisterConstant( g_pScriptVM, DMG_BUCKSHOT, "" ); - - // - // Trace Contents/Masks - // - ScriptRegisterConstant( g_pScriptVM, CONTENTS_EMPTY, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_SOLID, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_WINDOW, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_AUX, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_GRATE, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_SLIME, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_WATER, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_BLOCKLOS, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_OPAQUE, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_TESTFOGVOLUME, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_TEAM1, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_TEAM2, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_IGNORE_NODRAW_OPAQUE, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_MOVEABLE, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_AREAPORTAL, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_PLAYERCLIP, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_MONSTERCLIP, "" ); - - ScriptRegisterConstant( g_pScriptVM, CONTENTS_CURRENT_0, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_CURRENT_90, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_CURRENT_180, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_CURRENT_270, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_CURRENT_UP, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_CURRENT_DOWN, "" ); - - ScriptRegisterConstant( g_pScriptVM, CONTENTS_ORIGIN, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_MONSTER, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_DEBRIS, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_DETAIL, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_TRANSLUCENT, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_LADDER, "" ); - ScriptRegisterConstant( g_pScriptVM, CONTENTS_HITBOX, "" ); - - ScriptRegisterConstant( g_pScriptVM, LAST_VISIBLE_CONTENTS, "" ); - ScriptRegisterConstant( g_pScriptVM, ALL_VISIBLE_CONTENTS, "" ); - - ScriptRegisterConstant( g_pScriptVM, MASK_SOLID, "Spatial content mask representing solid objects (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_PLAYERSOLID, "Spatial content mask representing objects solid to the player, including player clips (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_NPCSOLID, "Spatial content mask representing objects solid to NPCs, including NPC clips (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_WATER, "Spatial content mask representing water and slime solids (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_OPAQUE, "Spatial content mask representing objects which block lighting (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_OPAQUE_AND_NPCS, "Spatial content mask equivalent to MASK_OPAQUE, but also including NPCs (MASK_OPAQUE|CONTENTS_MONSTER)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_BLOCKLOS, "Spatial content mask representing objects which block LOS for AI (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_BLOCKLOS)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_BLOCKLOS_AND_NPCS, "Spatial content mask equivalent to MASK_BLOCKLOS, but also including NPCs (MASK_BLOCKLOS|CONTENTS_MONSTER)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_VISIBLE, "Spatial content mask representing objects which block LOS for players (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_VISIBLE_AND_NPCS, "Spatial content mask equivalent to MASK_VISIBLE, but also including NPCs (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_SHOT, "Spatial content mask representing objects solid to bullets (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_SHOT_HULL, "Spatial content mask representing objects solid to non-raycasted weapons, including grates (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_SHOT_PORTAL, "Spatial content mask equivalent to MASK_SHOT, but excluding debris and not using expensive hitbox calculations (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_SOLID_BRUSHONLY, "Spatial content mask equivalent to MASK_SOLID, but without NPCs (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_PLAYERSOLID_BRUSHONLY, "Spatial content mask equivalent to MASK_PLAYERSOLID, but without NPCs (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_NPCSOLID_BRUSHONLY, "Spatial content mask equivalent to MASK_NPCSOLID, but without NPCs (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_NPCWORLDSTATIC, "Spatial content mask representing objects static to NPCs, used for nodegraph rebuilding (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)" ); - ScriptRegisterConstant( g_pScriptVM, MASK_SPLITAREAPORTAL, "Spatial content mask representing objects which can split areaportals (CONTENTS_WATER|CONTENTS_SLIME)" ); + ScriptRegisterConstant( g_pScriptVM, DMG_GENERIC, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_CRUSH, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_BULLET, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_SLASH, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_BURN, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_VEHICLE, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_FALL, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_BLAST, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_CLUB, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_SHOCK, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_SONIC, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_ENERGYBEAM, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_PREVENT_PHYSICS_FORCE, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_NEVERGIB, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_ALWAYSGIB, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_DROWN, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_PARALYZE, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_NERVEGAS, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_POISON, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_RADIATION, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_DROWNRECOVER, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_ACID, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_SLOWBURN, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_REMOVENORAGDOLL, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_PHYSGUN, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_PLASMA, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_AIRBOAT, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_DISSOLVE, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_BLAST_SURFACE, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_DIRECT, "Damage type used in damage information." ); + ScriptRegisterConstant( g_pScriptVM, DMG_BUCKSHOT, "Damage type used in damage information." ); // // Collision Groups // - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NONE, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DEBRIS, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DEBRIS_TRIGGER, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_INTERACTIVE_DEBRIS, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_INTERACTIVE, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PLAYER, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_BREAKABLE_GLASS, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_VEHICLE, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PLAYER_MOVEMENT, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_IN_VEHICLE, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_WEAPON, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_VEHICLE_CLIP, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PROJECTILE, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DOOR_BLOCKER, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PASSABLE_DOOR, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DISSOLVING, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PUSHAWAY, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC_ACTOR, "" ); - ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC_SCRIPTED, "" ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NONE, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DEBRIS, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DEBRIS_TRIGGER, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_INTERACTIVE_DEBRIS, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_INTERACTIVE, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PLAYER, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_BREAKABLE_GLASS, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_VEHICLE, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PLAYER_MOVEMENT, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_IN_VEHICLE, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_WEAPON, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_VEHICLE_CLIP, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PROJECTILE, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DOOR_BLOCKER, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PASSABLE_DOOR, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_DISSOLVING, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_PUSHAWAY, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC_ACTOR, "Collision group used in GetCollisionGroup(), etc." ); + ScriptRegisterConstant( g_pScriptVM, COLLISION_GROUP_NPC_SCRIPTED, "Collision group used in GetCollisionGroup(), etc." ); // // 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, "" ); + ScriptRegisterConstant( g_pScriptVM, FL_ONGROUND, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_DUCKING, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_WATERJUMP, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_ONTRAIN, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_INRAIN, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_FROZEN, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_ATCONTROLS, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_CLIENT, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_FAKECLIENT, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_INWATER, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_FLY, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_SWIM, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_CONVEYOR, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_NPC, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_GODMODE, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_NOTARGET, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_AIMTARGET, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_PARTIALGROUND, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_STATICPROP, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_GRAPHED, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_GRENADE, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_STEPMOVEMENT, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_DONTTOUCH, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_BASEVELOCITY, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_WORLDBRUSH, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_OBJECT, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_KILLME, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_ONFIRE, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_DISSOLVING, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_TRANSRAGDOLL, "Flag used in GetFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FL_UNBLOCKABLE_BY_PLAYER, "Flag used in GetFlags(), etc." ); // // Entity Flags // - ScriptRegisterConstant( g_pScriptVM, EFL_KILLME, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DORMANT, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NOCLIP_ACTIVE, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_SETTING_UP_BONES, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_KEEP_ON_RECREATE_ENTITIES, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_HAS_PLAYER_CHILD, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_SHADOWUPDATE, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NOTIFY, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_FORCE_CHECK_TRANSMIT, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_BOT_FROZEN, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_SERVER_ONLY, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_AUTO_EDICT_ATTACH, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_ABSTRANSFORM, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_ABSVELOCITY, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_ABSANGVELOCITY, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_SPATIAL_PARTITION, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_PLUGIN_BASED_BOT, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_IN_SKYBOX, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_USE_PARTITION_WHEN_NOT_SOLID, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_TOUCHING_FLUID, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_IS_BEING_LIFTED_BY_BARNACLE, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_ROTORWASH_PUSH, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_THINK_FUNCTION, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_GAME_PHYSICS_SIMULATION, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_CHECK_UNTOUCH, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DONTBLOCKLOS, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_DONTWALKON, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_DISSOLVE, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_MEGAPHYSCANNON_RAGDOLL, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_WATER_VELOCITY_CHANGE, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_PHYSCANNON_INTERACTION, "" ); - ScriptRegisterConstant( g_pScriptVM, EFL_NO_DAMAGE_FORCES, "" ); + ScriptRegisterConstant( g_pScriptVM, EFL_KILLME, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DORMANT, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NOCLIP_ACTIVE, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_SETTING_UP_BONES, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_KEEP_ON_RECREATE_ENTITIES, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_HAS_PLAYER_CHILD, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_SHADOWUPDATE, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NOTIFY, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_FORCE_CHECK_TRANSMIT, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_BOT_FROZEN, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_SERVER_ONLY, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_AUTO_EDICT_ATTACH, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_ABSTRANSFORM, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_ABSVELOCITY, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_ABSANGVELOCITY, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DIRTY_SPATIAL_PARTITION, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_PLUGIN_BASED_BOT, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_IN_SKYBOX, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_USE_PARTITION_WHEN_NOT_SOLID, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_TOUCHING_FLUID, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_IS_BEING_LIFTED_BY_BARNACLE, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_ROTORWASH_PUSH, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_THINK_FUNCTION, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_GAME_PHYSICS_SIMULATION, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_CHECK_UNTOUCH, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DONTBLOCKLOS, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_DONTWALKON, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_DISSOLVE, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_MEGAPHYSCANNON_RAGDOLL, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_WATER_VELOCITY_CHANGE, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_PHYSCANNON_INTERACTION, "Entity flag used in GetEFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EFL_NO_DAMAGE_FORCES, "Entity flag used in GetEFlags(), etc." ); // // Effects // - ScriptRegisterConstant( g_pScriptVM, EF_BONEMERGE, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_BRIGHTLIGHT, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_DIMLIGHT, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_NOINTERP, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_NOSHADOW, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_NODRAW, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_NORECEIVESHADOW, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_BONEMERGE_FASTCULL, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_ITEM_BLINK, "" ); - ScriptRegisterConstant( g_pScriptVM, EF_PARENT_ANIMATES, "" ); + ScriptRegisterConstant( g_pScriptVM, EF_BONEMERGE, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_BRIGHTLIGHT, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_DIMLIGHT, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_NOINTERP, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_NOSHADOW, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_NODRAW, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_NORECEIVESHADOW, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_BONEMERGE_FASTCULL, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_ITEM_BLINK, "Effect flag used in GetEffects(), etc." ); + ScriptRegisterConstant( g_pScriptVM, EF_PARENT_ANIMATES, "Effect flag used in GetEffects(), etc." ); // // Solid Flags // - ScriptRegisterConstant( g_pScriptVM, FSOLID_CUSTOMRAYTEST, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_CUSTOMBOXTEST, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_NOT_SOLID, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_TRIGGER, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_NOT_STANDABLE, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_VOLUME_CONTENTS, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_FORCE_WORLD_ALIGNED, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_USE_TRIGGER_BOUNDS, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_ROOT_PARENT_ALIGNED, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_TRIGGER_TOUCH_DEBRIS, "" ); - ScriptRegisterConstant( g_pScriptVM, FSOLID_COLLIDE_WITH_OWNER, "" ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_CUSTOMRAYTEST, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_CUSTOMBOXTEST, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_NOT_SOLID, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_TRIGGER, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_NOT_STANDABLE, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_VOLUME_CONTENTS, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_FORCE_WORLD_ALIGNED, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_USE_TRIGGER_BOUNDS, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_ROOT_PARENT_ALIGNED, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_TRIGGER_TOUCH_DEBRIS, "Solid flag used in GetSolidFlags(), etc." ); + ScriptRegisterConstant( g_pScriptVM, FSOLID_COLLIDE_WITH_OWNER, "Solid flag used in GetSolidFlags(), etc." ); // // Movetypes // - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_NONE, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_ISOMETRIC, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_WALK, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_STEP, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_FLY, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_FLYGRAVITY, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_VPHYSICS, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_PUSH, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_NOCLIP, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_LADDER, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_OBSERVER, "" ); - ScriptRegisterConstant( g_pScriptVM, MOVETYPE_CUSTOM, "" ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_NONE, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_ISOMETRIC, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_WALK, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_STEP, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_FLY, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_FLYGRAVITY, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_VPHYSICS, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_PUSH, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_NOCLIP, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_LADDER, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_OBSERVER, "Move type used in GetMoveType(), etc." ); + ScriptRegisterConstant( g_pScriptVM, MOVETYPE_CUSTOM, "Move type used in GetMoveType(), etc." ); #ifdef GAME_DLL // // Sound Types, Contexts, and Channels // (QueryHearSound hook can use these) // - ScriptRegisterConstant( g_pScriptVM, SOUND_NONE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_COMBAT, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_WORLD, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_PLAYER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_DANGER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_BULLET_IMPACT, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CARCASS, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_MEAT, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_GARBAGE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_THUMPER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_BUGBAIT, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_PHYSICS_DANGER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_DANGER_SNIPERONLY, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_MOVE_AWAY, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_PLAYER_VEHICLE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_READINESS_LOW, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_READINESS_MEDIUM, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_READINESS_HIGH, "" ); + ScriptRegisterConstant( g_pScriptVM, SOUND_NONE, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_COMBAT, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_WORLD, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_PLAYER, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_DANGER, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_BULLET_IMPACT, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CARCASS, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_MEAT, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_GARBAGE, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_THUMPER, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_BUGBAIT, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_PHYSICS_DANGER, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_DANGER_SNIPERONLY, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_MOVE_AWAY, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_PLAYER_VEHICLE, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_READINESS_LOW, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_READINESS_MEDIUM, "Sound type used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_READINESS_HIGH, "Sound type used in QueryHearSound hooks, etc." ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_FROM_SNIPER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_GUNFIRE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_MORTAR, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_COMBINE_ONLY, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_REACT_TO_SOURCE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_EXPLOSION, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_EXCLUDE_COMBINE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_DANGER_APPROACH, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_ALLIES_ONLY, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_PLAYER_VEHICLE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_OWNER_ALLIES, "" ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_FROM_SNIPER, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_GUNFIRE, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_MORTAR, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_COMBINE_ONLY, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_REACT_TO_SOURCE, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_EXPLOSION, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_EXCLUDE_COMBINE, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_DANGER_APPROACH, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_ALLIES_ONLY, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_PLAYER_VEHICLE, "Sound context used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUND_CONTEXT_OWNER_ALLIES, "Sound context used in QueryHearSound hooks, etc." ); - ScriptRegisterConstant( g_pScriptVM, ALL_CONTEXTS, "" ); - ScriptRegisterConstant( g_pScriptVM, ALL_SCENTS, "" ); - ScriptRegisterConstant( g_pScriptVM, ALL_SOUNDS, "" ); + ScriptRegisterConstant( g_pScriptVM, ALL_CONTEXTS, "All sound contexts useable in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, ALL_SCENTS, "All \"scent\" sound types useable in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, ALL_SOUNDS, "All sound types useable in QueryHearSound hooks, etc." ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_UNSPECIFIED, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_REPEATING, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_REPEATED_DANGER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_REPEATED_PHYSICS_DANGER, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_WEAPON, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_INJURY, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_BULLET_IMPACT, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_NPC_FOOTSTEP, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_SPOOKY_NOISE, "" ); - ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_ZOMBINE_GRENADE, "" ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_UNSPECIFIED, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_REPEATING, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_REPEATED_DANGER, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_REPEATED_PHYSICS_DANGER, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_WEAPON, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_INJURY, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_BULLET_IMPACT, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_NPC_FOOTSTEP, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_SPOOKY_NOISE, "Sound channel used in QueryHearSound hooks, etc." ); + ScriptRegisterConstant( g_pScriptVM, SOUNDENT_CHANNEL_ZOMBINE_GRENADE, "Sound channel used in QueryHearSound hooks, etc." ); + + ScriptRegisterConstantNamed( g_pScriptVM, (int)SOUNDENT_VOLUME_MACHINEGUN, "SOUNDENT_VOLUME_MACHINEGUN", "Sound volume preset for use in InsertAISound, etc." ); + ScriptRegisterConstantNamed( g_pScriptVM, (int)SOUNDENT_VOLUME_SHOTGUN, "SOUNDENT_VOLUME_SHOTGUN", "Sound volume preset for use in InsertAISound, etc." ); + ScriptRegisterConstantNamed( g_pScriptVM, (int)SOUNDENT_VOLUME_PISTOL, "SOUNDENT_VOLUME_PISTOL", "Sound volume preset for use in InsertAISound, etc." ); + ScriptRegisterConstantNamed( g_pScriptVM, (int)SOUNDENT_VOLUME_EMPTY, "SOUNDENT_VOLUME_PISTOL", "Sound volume preset for use in InsertAISound, etc." ); // // Capabilities // - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_GROUND, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_JUMP, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_FLY, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_CLIMB, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_SWIM, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_CRAWL, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_SHOOT, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_SKIP_NAV_GROUND_CHECK, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_USE, "" ); - //ScriptRegisterConstant( g_pScriptVM, bits_CAP_HEAR, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_AUTO_DOORS, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_OPEN_DOORS, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_TURN_HEAD, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_RANGE_ATTACK1, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_RANGE_ATTACK2, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_MELEE_ATTACK1, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_MELEE_ATTACK2, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_RANGE_ATTACK1, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_RANGE_ATTACK2, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_MELEE_ATTACK1, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_MELEE_ATTACK2, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_USE_WEAPONS, "" ); - //ScriptRegisterConstant( g_pScriptVM, bits_CAP_STRAFE, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_ANIMATEDFACE, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_USE_SHOT_REGULATOR, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_FRIENDLY_DMG_IMMUNE, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_SQUAD, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_DUCK, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_NO_HIT_PLAYER, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_AIM_GUN, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_NO_HIT_SQUADMATES, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_SIMPLE_RADIUS_DAMAGE, "" ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_GROUND, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_JUMP, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_FLY, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_CLIMB, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_SWIM, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_CRAWL, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MOVE_SHOOT, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_SKIP_NAV_GROUND_CHECK, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_USE, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + //ScriptRegisterConstant( g_pScriptVM, bits_CAP_HEAR, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_AUTO_DOORS, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_OPEN_DOORS, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_TURN_HEAD, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_RANGE_ATTACK1, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_RANGE_ATTACK2, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_MELEE_ATTACK1, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_WEAPON_MELEE_ATTACK2, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_RANGE_ATTACK1, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_RANGE_ATTACK2, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_MELEE_ATTACK1, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_INNATE_MELEE_ATTACK2, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_USE_WEAPONS, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + //ScriptRegisterConstant( g_pScriptVM, bits_CAP_STRAFE, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_ANIMATEDFACE, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_USE_SHOT_REGULATOR, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_FRIENDLY_DMG_IMMUNE, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_SQUAD, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_DUCK, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_NO_HIT_PLAYER, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_AIM_GUN, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_NO_HIT_SQUADMATES, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_SIMPLE_RADIUS_DAMAGE, "NPC/player/weapon capability used in GetCapabilities(), etc." ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_DOORS_GROUP, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_RANGE_ATTACK_GROUP, "" ); - ScriptRegisterConstant( g_pScriptVM, bits_CAP_MELEE_ATTACK_GROUP, "" ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_DOORS_GROUP, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_RANGE_ATTACK_GROUP, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + ScriptRegisterConstant( g_pScriptVM, bits_CAP_MELEE_ATTACK_GROUP, "NPC/player/weapon capability used in GetCapabilities(), etc." ); + + // + // Class_T classes + // + ScriptRegisterConstant( g_pScriptVM, CLASS_NONE, "No class." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_PLAYER, "Used by players." ); + +#ifdef HL2_DLL + + ScriptRegisterConstant( g_pScriptVM, CLASS_PLAYER_ALLY, "Used by citizens, hacked manhacks, and other misc. allies." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_PLAYER_ALLY_VITAL, "Used by Alyx, Barney, and other allies vital to HL2." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ANTLION, "Used by antlions, antlion guards, etc." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_BARNACLE, "Used by barnacles." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_BULLSEYE, "Used by npc_bullseye." ); + //ScriptRegisterConstant( g_pScriptVM, CLASS_BULLSQUID, "Used by bullsquids." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_CITIZEN_PASSIVE, "Used by citizens when the \"gordon_precriminal\" or \"citizens_passive\" states are enabled." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_CITIZEN_REBEL, "UNUSED IN HL2. Rebels normally use CLASS_PLAYER_ALLY." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_COMBINE, "Used by Combine soldiers, Combine turrets, and other misc. Combine NPCs." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_COMBINE_GUNSHIP, "Used by Combine gunships, helicopters, etc." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_CONSCRIPT, "UNUSED IN HL2. Would've been used by conscripts." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_HEADCRAB, "Used by headcrabs." ); + //ScriptRegisterConstant( g_pScriptVM, CLASS_HOUNDEYE, "Used by houndeyes." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_MANHACK, "Used by Combine manhacks." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_METROPOLICE, "Used by Combine metrocops." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_MILITARY, "In HL2, this is only used by npc_combinecamera and func_guntarget. This appears to be recognized as a Combine class." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_SCANNER, "Used by Combine city scanners and claw scanners." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_STALKER, "Used by Combine stalkers." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_VORTIGAUNT, "Used by vortigaunts." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ZOMBIE, "Used by zombies." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_PROTOSNIPER, "Used by Combine snipers." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_MISSILE, "Used by RPG and APC missiles." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_FLARE, "Used by env_flares." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_EARTH_FAUNA, "Used by birds and other terrestrial animals." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_HACKED_ROLLERMINE, "Used by rollermines which were hacked by Alyx." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_COMBINE_HUNTER, "Used by Combine hunters." ); + +#elif defined( HL1_DLL ) + + ScriptRegisterConstant( g_pScriptVM, CLASS_HUMAN_PASSIVE, "Used by scientists." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_HUMAN_MILITARY, "Used by HECU marines, etc." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ALIEN_MILITARY, "Used by alien grunts, alien slaves/vortigaunts, etc." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ALIEN_MONSTER, "Used by zombies, houndeyes, barnacles, and other misc. monsters." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ALIEN_PREY, "Used by headcrabs, etc." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ALIEN_PREDATOR, "Used by bullsquids, etc." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_INSECT, "Used by cockroaches." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_PLAYER_ALLY, "Used by security guards/Barneys." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_PLAYER_BIOWEAPON, "Used by a player's hivehand hornets." ); + ScriptRegisterConstant( g_pScriptVM, CLASS_ALIEN_BIOWEAPON, "Used by an alien grunt's hivehand hornets." ); + +#else + + ScriptRegisterConstant( g_pScriptVM, CLASS_PLAYER_ALLY, "Used by player allies." ); + +#endif + + ScriptRegisterConstant( g_pScriptVM, NUM_AI_CLASSES, "Number of AI classes." ); // // 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, "" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_INVALID, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_NONE, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_IDLE, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_ALERT, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_COMBAT, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_SCRIPT, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_PLAYDEAD, "NPC state type used in GetNPCState(), etc." ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_PRONE, "When in clutches of barnacle (NPC state type used in GetNPCState(), etc.)" ); + ScriptRegisterConstant( g_pScriptVM, NPC_STATE_DEAD, "NPC state type used in GetNPCState(), etc." ); 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." ); @@ -479,8 +476,10 @@ void RegisterSharedScriptConstants() // Misc. General // #ifdef GAME_DLL - ScriptRegisterConstant( g_pScriptVM, GLOBAL_OFF, "" ); - ScriptRegisterConstant( g_pScriptVM, GLOBAL_ON, "" ); - ScriptRegisterConstant( g_pScriptVM, GLOBAL_DEAD, "" ); + ScriptRegisterConstant( g_pScriptVM, GLOBAL_OFF, "Global state used by the Globals singleton." ); + ScriptRegisterConstant( g_pScriptVM, GLOBAL_ON, "Global state used by the Globals singleton." ); + ScriptRegisterConstant( g_pScriptVM, GLOBAL_DEAD, "Global state used by the Globals singleton." ); #endif + + RegisterWeaponScriptConstants(); } diff --git a/sp/src/game/shared/mapbase/vscript_consts_weapons.cpp b/sp/src/game/shared/mapbase/vscript_consts_weapons.cpp new file mode 100644 index 00000000..ad63efb7 --- /dev/null +++ b/sp/src/game/shared/mapbase/vscript_consts_weapons.cpp @@ -0,0 +1,98 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: VScript constants and enums shared between the server and client. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "basecombatweapon_shared.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//============================================================================= +//============================================================================= + +BEGIN_SCRIPTENUM( WeaponSound, "Weapon sounds." ) + + DEFINE_ENUMCONST( EMPTY, "" ) + DEFINE_ENUMCONST( SINGLE, "" ) + DEFINE_ENUMCONST( SINGLE_NPC, "" ) + DEFINE_ENUMCONST( WPN_DOUBLE, "" ) + DEFINE_ENUMCONST( DOUBLE_NPC, "" ) + DEFINE_ENUMCONST( BURST, "" ) + DEFINE_ENUMCONST( RELOAD, "" ) + DEFINE_ENUMCONST( RELOAD_NPC, "" ) + DEFINE_ENUMCONST( MELEE_MISS, "" ) + DEFINE_ENUMCONST( MELEE_HIT, "" ) + DEFINE_ENUMCONST( MELEE_HIT_WORLD, "" ) + DEFINE_ENUMCONST( SPECIAL1, "" ) + DEFINE_ENUMCONST( SPECIAL2, "" ) + DEFINE_ENUMCONST( SPECIAL3, "" ) + DEFINE_ENUMCONST( TAUNT, "" ) + DEFINE_ENUMCONST( DEPLOY, "" ) + + DEFINE_ENUMCONST( NUM_SHOOT_SOUND_TYPES, "" ) + +END_SCRIPTENUM(); + +//============================================================================= +//============================================================================= + +void RegisterWeaponScriptConstants() +{ + // + // Weapon classify + // + ScriptRegisterConstant( g_pScriptVM, WEPCLASS_INVALID, "Invalid weapon class." ); + ScriptRegisterConstant( g_pScriptVM, WEPCLASS_HANDGUN, "Weapon class for pistols, revolvers, etc." ); + ScriptRegisterConstant( g_pScriptVM, WEPCLASS_RIFLE, "Weapon class for (assault) rifles, SMGs, etc." ); + ScriptRegisterConstant( g_pScriptVM, WEPCLASS_SHOTGUN, "Weapon class for shotguns." ); + ScriptRegisterConstant( g_pScriptVM, WEPCLASS_HEAVY, "Weapon class for RPGs, etc." ); + + ScriptRegisterConstant( g_pScriptVM, WEPCLASS_MELEE, "Weapon class for melee weapons." ); + + // + // Vector cones + // + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_PRECALCULATED, "This is just a zero vector, but it adds some context indicating that the person writing the code is not allowing " + "FireBullets() to modify the direction of the shot because the shot direction " + "being passed into the function has already been modified by another piece of " + "code and should be fired as specified." ); + + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_1DEGREES, "1-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_2DEGREES, "2-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_3DEGREES, "3-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_4DEGREES, "4-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_5DEGREES, "5-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_6DEGREES, "6-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_7DEGREES, "7-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_8DEGREES, "8-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_9DEGREES, "9-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_10DEGREES, "10-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_15DEGREES, "15-degree weapon vector cone." ); + ScriptRegisterConstantFromTemp( g_pScriptVM, VECTOR_CONE_20DEGREES, "20-degree weapon vector cone." ); + + // + // Weapon proficiency + // + ScriptRegisterConstant( g_pScriptVM, WEAPON_PROFICIENCY_INVALID, "Invalid weapon proficiency." ); + ScriptRegisterConstant( g_pScriptVM, WEAPON_PROFICIENCY_POOR, "Poor weapon proficiency. Causes low accuracy." ); + ScriptRegisterConstant( g_pScriptVM, WEAPON_PROFICIENCY_AVERAGE, "Average weapon proficiency. Causes average accuracy." ); + ScriptRegisterConstant( g_pScriptVM, WEAPON_PROFICIENCY_GOOD, "Good weapon proficiency. Causes good accuracy." ); + ScriptRegisterConstant( g_pScriptVM, WEAPON_PROFICIENCY_VERY_GOOD, "Very good weapon proficiency. Causes very good accuracy." ); + ScriptRegisterConstant( g_pScriptVM, WEAPON_PROFICIENCY_PERFECT, "Perfect weapon proficiency. Causes perfect accuracy." ); + + // + // Autoaim + // + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_2DEGREES, "2-degree autoaim cone." ); + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_5DEGREES, "5-degree autoaim cone." ); + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_8DEGREES, "8-degree autoaim cone." ); + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_10DEGREES, "10-degree autoaim cone." ); + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_20DEGREES, "20-degree autoaim cone." ); + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_SCALE_DEFAULT, "Indicates default auto aim scale." ); + ScriptRegisterConstant( g_pScriptVM, AUTOAIM_SCALE_DIRECT_ONLY, "Indicates auto aim should not be used except for direct hits." ); +} diff --git a/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp b/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp index 3d322593..76aa7cdd 100644 --- a/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp +++ b/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp @@ -1,10 +1,15 @@ //========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// // -// Purpose: Due to this being a custom integration of VScript based on the Alien Swarm SDK, we don't have access to -// some of the code normally available in games like L4D2 or Valve's original VScript DLL. -// Instead, that code is recreated here, shared between server and client. +// Purpose: This file contains general shared VScript bindings which Mapbase adds onto +// what was ported from Alien Swarm instead of cluttering the existing files. // -// It also contains other functions unique to Mapbase. +// This includes various functions, classes, etc. which were either created from +// scratch or were based on/inspired by things documented in APIs from L4D2 or even +// Source 2 games like Dota 2 or Half-Life: Alyx. +// +// Other VScript bindings can be found in files like vscript_singletons.cpp and +// things not exclusive to the game DLLs are embedded/recreated in the library itself +// via vscript_bindings_base.cpp. // // $NoKeywords: $ //=============================================================================// @@ -12,358 +17,23 @@ #include "cbase.h" #include "matchers.h" #include "takedamageinfo.h" -#include "ammodef.h" -#include -#include #ifndef CLIENT_DLL #include "globalstate.h" #include "vscript_server.h" - -#include "usermessages.h" +#include "soundent.h" #endif // !CLIENT_DLL -#include "filesystem.h" -#include "igameevents.h" -#include "icommandline.h" #include "con_nprint.h" #include "particle_parse.h" #include "vscript_funcs_shared.h" +#include "vscript_singletons.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CScriptNetPropManager -{ -public: - -#ifdef CLIENT_DLL - RecvProp *RecurseTable( RecvTable *pTable, const char *pszPropName ) -#else - SendProp *RecurseTable( SendTable *pTable, const char *pszPropName ) -#endif - { -#ifdef CLIENT_DLL - RecvProp *pProp = NULL; -#else - SendProp *pProp = NULL; -#endif - for (int i = 0; i < pTable->GetNumProps(); i++) - { - pProp = pTable->GetProp( i ); - if (pProp->GetType() == DPT_DataTable) - { - pProp = RecurseTable(pProp->GetDataTable(), pszPropName); - if (pProp) - return pProp; - } - else - { - if (FStrEq( pProp->GetName(), pszPropName )) - return pProp; - } - } - - return NULL; - } - -#ifdef CLIENT_DLL - RecvProp *RecurseNetworkClass( ClientClass *pClass, const char *pszPropName ) -#else - SendProp *RecurseNetworkClass( ServerClass *pClass, const char *pszPropName ) -#endif - { -#ifdef CLIENT_DLL - RecvProp *pProp = RecurseTable( pClass->m_pRecvTable, pszPropName ); -#else - SendProp *pProp = RecurseTable( pClass->m_pTable, pszPropName ); -#endif - if (pProp) - return pProp; - - if (pClass->m_pNext) - return RecurseNetworkClass( pClass->m_pNext, pszPropName ); - else - return NULL; - } - -#ifdef CLIENT_DLL - RecvProp *GetPropByName( CBaseEntity *pEnt, const char *pszPropName ) - { - if (pEnt) - { - return RecurseNetworkClass( pEnt->GetClientClass(), pszPropName ); - } - - return NULL; - } -#else - SendProp *GetPropByName( CBaseEntity *pEnt, const char *pszPropName ) - { - if (pEnt) - { - return RecurseNetworkClass( pEnt->GetServerClass(), pszPropName ); - } - - return NULL; - } -#endif - - int GetPropArraySize( HSCRIPT hEnt, const char *pszPropName ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp) - { - // TODO: Is this what this function wants? - return pProp->GetNumElements(); - } - - return -1; - } - - #define GetPropFunc( name, varType, propType, defaultval ) \ - varType name( HSCRIPT hEnt, const char *pszPropName ) \ - { \ - CBaseEntity *pEnt = ToEnt( hEnt ); \ - auto *pProp = GetPropByName( pEnt, pszPropName ); \ - if (pProp && pProp->GetType() == propType) \ - { \ - return *(varType*)((char *)pEnt + pProp->GetOffset()); \ - } \ - return defaultval; \ - } \ - - #define GetPropFuncArray( name, varType, propType, defaultval ) \ - varType name( HSCRIPT hEnt, const char *pszPropName, int iArrayElement ) \ - { \ - CBaseEntity *pEnt = ToEnt( hEnt ); \ - auto *pProp = GetPropByName( pEnt, pszPropName ); \ - if (pProp && pProp->GetType() == propType) \ - { \ - return ((varType*)((char *)pEnt + pProp->GetOffset()))[iArrayElement]; \ - } \ - return defaultval; \ - } \ - - GetPropFunc( GetPropFloat, float, DPT_Float, -1 ); - GetPropFuncArray( GetPropFloatArray, float, DPT_Float, -1 ); - GetPropFunc( GetPropInt, int, DPT_Int, -1 ); - GetPropFuncArray( GetPropIntArray, int, DPT_Int, -1 ); - GetPropFunc( GetPropVector, Vector, DPT_Vector, vec3_invalid ); - GetPropFuncArray( GetPropVectorArray, Vector, DPT_Vector, vec3_invalid ); - - HSCRIPT GetPropEntity( HSCRIPT hEnt, const char *pszPropName ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp && pProp->GetType() == DPT_Int) - { - return ToHScript( *(CHandle*)((char *)pEnt + pProp->GetOffset()) ); - } - - return NULL; - } - - HSCRIPT GetPropEntityArray( HSCRIPT hEnt, const char *pszPropName, int iArrayElement ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp && pProp->GetType() == DPT_Int) - { - return ToHScript( ((CHandle*)((char *)pEnt + pProp->GetOffset()))[iArrayElement] ); - } - - return NULL; - } - - const char *GetPropString( HSCRIPT hEnt, const char *pszPropName ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp && pProp->GetType() == DPT_Int) - { - return (const char*)((char *)pEnt + pProp->GetOffset()); - } - - return NULL; - } - - const char *GetPropStringArray( HSCRIPT hEnt, const char *pszPropName, int iArrayElement ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp && pProp->GetType() == DPT_Int) - { - return ((const char**)((char *)pEnt + pProp->GetOffset()))[iArrayElement]; - } - - return NULL; - } - - const char *GetPropType( HSCRIPT hEnt, const char *pszPropName ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp) - { - switch (pProp->GetType()) - { - case DPT_Int: return "integer"; - case DPT_Float: return "float"; - case DPT_Vector: return "vector"; - case DPT_VectorXY: return "vector2d"; - case DPT_String: return "string"; - case DPT_Array: return "array"; - case DPT_DataTable: return "datatable"; - } - } - - return NULL; - } - - bool HasProp( HSCRIPT hEnt, const char *pszPropName ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - return GetPropByName( pEnt, pszPropName ) != NULL; - } - - #define SetPropFunc( name, varType, propType ) \ - void name( HSCRIPT hEnt, const char *pszPropName, varType value ) \ - { \ - CBaseEntity *pEnt = ToEnt( hEnt ); \ - auto *pProp = GetPropByName( pEnt, pszPropName ); \ - if (pProp && pProp->GetType() == propType) \ - { \ - *(varType*)((char *)pEnt + pProp->GetOffset()) = value; \ - } \ - } \ - - #define SetPropFuncArray( name, varType, propType ) \ - void name( HSCRIPT hEnt, const char *pszPropName, varType value, int iArrayElement ) \ - { \ - CBaseEntity *pEnt = ToEnt( hEnt ); \ - auto *pProp = GetPropByName( pEnt, pszPropName ); \ - if (pProp && pProp->GetType() == propType) \ - { \ - ((varType*)((char *)pEnt + pProp->GetOffset()))[iArrayElement] = value; \ - } \ - } \ - - SetPropFunc( SetPropFloat, float, DPT_Float ); - SetPropFuncArray( SetPropFloatArray, float, DPT_Float ); - SetPropFunc( SetPropInt, int, DPT_Int ); - SetPropFuncArray( SetPropIntArray, int, DPT_Int ); - SetPropFunc( SetPropVector, Vector, DPT_Vector ); - SetPropFuncArray( SetPropVectorArray, Vector, DPT_Vector ); - SetPropFunc( SetPropString, const char*, DPT_String ); - SetPropFuncArray( SetPropStringArray, const char*, DPT_String ); - - void SetPropEntity( HSCRIPT hEnt, const char *pszPropName, HSCRIPT value ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp && pProp->GetType() == DPT_Int) - { - *((CHandle*)((char *)pEnt + pProp->GetOffset())) = ToEnt(value); - } - } - - HSCRIPT SetPropEntityArray( HSCRIPT hEnt, const char *pszPropName, HSCRIPT value, int iArrayElement ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - auto *pProp = GetPropByName( pEnt, pszPropName ); - if (pProp && pProp->GetType() == DPT_Int) - { - ((CHandle*)((char *)pEnt + pProp->GetOffset()))[iArrayElement] = ToEnt(value); - } - - return NULL; - } - -private: -} g_ScriptNetPropManager; - -BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptNetPropManager, "CNetPropManager", SCRIPT_SINGLETON "Allows reading and updating the network properties of an entity." ) - DEFINE_SCRIPTFUNC( GetPropArraySize, "Returns the size of an netprop array, or -1." ) - DEFINE_SCRIPTFUNC( GetPropEntity, "Reads an EHANDLE valued netprop (21 bit integer). Returns the script handle of the entity." ) - DEFINE_SCRIPTFUNC( GetPropEntityArray, "Reads an EHANDLE valued netprop (21 bit integer) from an array. Returns the script handle of the entity." ) - DEFINE_SCRIPTFUNC( GetPropFloat, "Reads a float valued netprop." ) - DEFINE_SCRIPTFUNC( GetPropFloatArray, "Reads a float valued netprop from an array." ) - DEFINE_SCRIPTFUNC( GetPropInt, "Reads an integer valued netprop." ) - DEFINE_SCRIPTFUNC( GetPropIntArray, "Reads an integer valued netprop from an array." ) - DEFINE_SCRIPTFUNC( GetPropString, "Reads a string valued netprop." ) - DEFINE_SCRIPTFUNC( GetPropStringArray, "Reads a string valued netprop from an array." ) - DEFINE_SCRIPTFUNC( GetPropVector, "Reads a 3D vector valued netprop." ) - DEFINE_SCRIPTFUNC( GetPropVectorArray, "Reads a 3D vector valued netprop from an array." ) - DEFINE_SCRIPTFUNC( GetPropType, "Returns the name of the netprop type as a string." ) - DEFINE_SCRIPTFUNC( HasProp, "Checks if a netprop exists." ) - DEFINE_SCRIPTFUNC( SetPropEntity, "Sets an EHANDLE valued netprop (21 bit integer) to reference the specified entity." ) - DEFINE_SCRIPTFUNC( SetPropEntityArray, "Sets an EHANDLE valued netprop (21 bit integer) from an array to reference the specified entity." ) - DEFINE_SCRIPTFUNC( SetPropFloat, "Sets a netprop to the specified float." ) - DEFINE_SCRIPTFUNC( SetPropFloatArray, "Sets a netprop from an array to the specified float." ) - DEFINE_SCRIPTFUNC( SetPropInt, "Sets a netprop to the specified integer." ) - DEFINE_SCRIPTFUNC( SetPropIntArray, "Sets a netprop from an array to the specified integer." ) - DEFINE_SCRIPTFUNC( SetPropString, "Sets a netprop to the specified string." ) - DEFINE_SCRIPTFUNC( SetPropStringArray, "Sets a netprop from an array to the specified string." ) - DEFINE_SCRIPTFUNC( SetPropVector, "Sets a netprop to the specified vector." ) - DEFINE_SCRIPTFUNC( SetPropVectorArray, "Sets a netprop from an array to the specified vector." ) -END_SCRIPTDESC(); - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CScriptConvarLookup -{ -public: - -#ifndef CLIENT_DLL - const char *GetClientConvarValue( const char *pszConVar, int entindex ) - { - return engine->GetClientConVarValue( entindex, pszConVar ); - } -#endif - - const char *GetStr( const char *pszConVar ) - { - ConVarRef cvar( pszConVar ); - return cvar.GetString(); - } - - float GetFloat( const char *pszConVar ) - { - ConVarRef cvar( pszConVar ); - return cvar.GetFloat(); - } - - void SetValue( const char *pszConVar, const char *pszValue ) - { - ConVarRef cvar( pszConVar ); - if (!cvar.IsValid()) - return; - - // FCVAR_NOT_CONNECTED can be used to protect specific convars from nefarious interference - if (cvar.IsFlagSet(FCVAR_NOT_CONNECTED)) - return; - - cvar.SetValue( pszValue ); - } - -private: -} g_ScriptConvarLookup; - -BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarLookup, "CConvars", SCRIPT_SINGLETON "Provides an interface for getting and setting convars." ) -#ifndef CLIENT_DLL - DEFINE_SCRIPTFUNC( GetClientConvarValue, "Returns the convar value for the entindex as a string. Only works with client convars with the FCVAR_USERINFO flag." ) -#endif - DEFINE_SCRIPTFUNC( GetStr, "Returns the convar as a string. May return null if no such convar." ) - DEFINE_SCRIPTFUNC( GetFloat, "Returns the convar as a float. May return null if no such convar." ) - DEFINE_SCRIPTFUNC( SetValue, "Sets the value of the convar. Supported types are bool, int, float, string." ) -END_SCRIPTDESC(); +extern IScriptManager *scriptmanager; #ifndef CLIENT_DLL void EmitSoundOn( const char *pszSound, HSCRIPT hEnt ) @@ -402,11 +72,6 @@ void AddThinkToEnt( HSCRIPT entity, const char *pszFuncName ) pEntity->ScriptSetThinkFunction(pszFuncName, TICK_INTERVAL); } -HSCRIPT EntIndexToHScript( int index ) -{ - return ToHScript( UTIL_EntityByIndex( index ) ); -} - void ParseScriptTableKeyValues( CBaseEntity *pEntity, HSCRIPT hKV ) { int nIterator = -1; @@ -475,27 +140,27 @@ HSCRIPT SpawnEntityFromTable( const char *pszClassname, HSCRIPT hKV ) } #endif +HSCRIPT EntIndexToHScript( int index ) +{ +#ifdef GAME_DLL + edict_t *e = INDEXENT(index); + if ( e && !e->IsFree() ) + { + return ToHScript( GetContainingEntity( e ) ); + } +#else // CLIENT_DLL + if ( index < NUM_ENT_ENTRIES ) + { + return ToHScript( CBaseEntity::Instance( index ) ); + } +#endif + return NULL; +} + //----------------------------------------------------------------------------- // Mapbase-specific functions start here //----------------------------------------------------------------------------- -static void ScriptMsg( const char *msg ) -{ - Msg( "%s", msg ); -} - -static void ScriptColorPrint( int r, int g, int b, const char *pszMsg ) -{ - const Color clr(r, g, b, 255); - ConColorMsg( clr, "%s", pszMsg ); -} - -static void ScriptColorPrintL( int r, int g, int b, const char *pszMsg ) -{ - const Color clr(r, g, b, 255); - ConColorMsg( clr, "%s\n", pszMsg ); -} - #ifndef CLIENT_DLL HSCRIPT SpawnEntityFromKeyValues( const char *pszClassname, HSCRIPT hKV ) { @@ -514,14 +179,10 @@ HSCRIPT SpawnEntityFromKeyValues( const char *pszClassname, HSCRIPT hKV ) gEntList.NotifyCreateEntity( pEntity ); - CScriptKeyValues *pScriptKV = hKV ? HScriptToClass( hKV ) : NULL; - if (pScriptKV) + KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV ); + for (pKV = pKV->GetFirstSubKey(); pKV != NULL; pKV = pKV->GetNextKey()) { - KeyValues *pKV = pScriptKV->m_pKeyValues; - for (pKV = pKV->GetFirstSubKey(); pKV != NULL; pKV = pKV->GetNextKey()) - { - pEntity->KeyValue( pKV->GetName(), pKV->GetString() ); - } + pEntity->KeyValue( pKV->GetName(), pKV->GetString() ); } DispatchSpawn( pEntity ); @@ -540,44 +201,6 @@ void ScriptDispatchSpawn( HSCRIPT hEntity ) } #endif // !CLIENT_DLL -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CScriptLocalize -{ -public: - - const char *GetTokenAsUTF8( const char *pszToken ) - { - const char *pText = g_pVGuiLocalize->FindAsUTF8( pszToken ); - if ( pText ) - { - return pText; - } - - return NULL; - } - - void AddStringAsUTF8( const char *pszToken, const char *pszString ) - { - wchar_t wpszString[256]; - g_pVGuiLocalize->ConvertANSIToUnicode( pszString, wpszString, sizeof(wpszString) ); - - // TODO: This is a fake file name! Should "fileName" mean anything? - g_pVGuiLocalize->AddString( pszToken, wpszString, "resource/vscript_localization.txt" ); - } - -private: -} g_ScriptLocalize; - -BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptLocalize, "CLocalize", SCRIPT_SINGLETON "Accesses functions related to localization strings." ) - - DEFINE_SCRIPTFUNC( GetTokenAsUTF8, "Gets the current language's token as a UTF-8 string (not Unicode)." ) - - DEFINE_SCRIPTFUNC( AddStringAsUTF8, "Adds a new localized token as a UTF-8 string (not Unicode)." ) - -END_SCRIPTDESC(); - //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- @@ -929,448 +552,6 @@ static void AddPhysVelocity( HSCRIPT hPhys, const Vector& vecVelocity, const Vec //============================================================================= //============================================================================= -class CScriptGameEventListener : public IGameEventListener2, public CAutoGameSystem -{ -public: - CScriptGameEventListener() : m_bActive(false) {} - ~CScriptGameEventListener() - { - StopListeningForEvent(); - } - - intptr_t ListenToGameEvent( const char* szEvent, HSCRIPT hFunc, const char* szContext ); - void StopListeningForEvent(); - -public: - static bool StopListeningToGameEvent( intptr_t listener ); - static void StopListeningToAllGameEvents( const char* szContext ); - -public: - void FireGameEvent( IGameEvent *event ); - void LevelShutdownPreEntity(); - -private: - bool m_bActive; - const char *m_pszContext; - HSCRIPT m_hCallback; - - static const char *FindContext( const char *szContext, CScriptGameEventListener *pIgnore = NULL ); - //inline const char *GetContext( CScriptGameEventListener *p ); - //inline const char *GetContext(); - -public: - static void DumpEventListeners(); -#ifndef CLIENT_DLL - static void LoadAllEvents(); - static void LoadEventsFromFile( const char *filename, const char *pathID = NULL ); - static void WriteEventData( IGameEvent *event, HSCRIPT hTable ); -#endif // !CLIENT_DLL - -private: -#ifndef CLIENT_DLL - static CUtlVector< KeyValues* > s_GameEvents; -#endif // !CLIENT_DLL - static CUtlVectorAutoPurge< CScriptGameEventListener* > s_GameEventListeners; - -}; - -#ifndef CLIENT_DLL -CUtlVector< KeyValues* > CScriptGameEventListener::s_GameEvents; -#endif // !CLIENT_DLL -CUtlVectorAutoPurge< CScriptGameEventListener* > CScriptGameEventListener::s_GameEventListeners; - -#if 0 -#ifdef CLIENT_DLL -CON_COMMAND_F( cl_dump_script_game_event_listeners, "Dump all game event listeners created from script.", FCVAR_CHEAT ) -{ - CScriptGameEventListener::DumpEventListeners(); -} -#else // GAME_DLL -CON_COMMAND_F( dump_script_game_event_listeners, "Dump all game event listeners created from script.", FCVAR_CHEAT ) -{ - CScriptGameEventListener::DumpEventListeners(); -} -#endif // CLIENT_DLL -#endif - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CScriptGameEventListener::DumpEventListeners() -{ - Msg("--- Script game event listener dump start\n"); - FOR_EACH_VEC( s_GameEventListeners, i ) - { - Msg(" %d (0x%p) %d : %s\n", i,s_GameEventListeners[i], - s_GameEventListeners[i], - s_GameEventListeners[i]->m_pszContext ? s_GameEventListeners[i]->m_pszContext : ""); - } - Msg("--- Script game event listener dump end\n"); -} - -void CScriptGameEventListener::FireGameEvent( IGameEvent *event ) -{ - ScriptVariant_t hTable; - g_pScriptVM->CreateTable( hTable ); - // TODO: pass event data on client -#ifdef GAME_DLL - WriteEventData( event, hTable ); -#endif - g_pScriptVM->SetValue( hTable, "game_event_listener", reinterpret_cast(this) ); // POINTER_TO_INT - // g_pScriptVM->SetValue( hTable, "game_event_name", event->GetName() ); - g_pScriptVM->ExecuteFunction( m_hCallback, &hTable, 1, NULL, NULL, true ); - g_pScriptVM->ReleaseScript( hTable ); -} - -void CScriptGameEventListener::LevelShutdownPreEntity() -{ - s_GameEventListeners.FindAndFastRemove(this); - delete this; -} - -//----------------------------------------------------------------------------- -// Executed in LevelInitPreEntity -//----------------------------------------------------------------------------- -#ifndef CLIENT_DLL -void CScriptGameEventListener::LoadAllEvents() -{ - // Listed in the same order they are loaded in GameEventManager - const char *filenames[] = - { - "resource/serverevents.res", - "resource/gameevents.res", - "resource/mapbaseevents.res", - "resource/modevents.res" - }; - - const char *pathlist[] = - { - "GAME", - "MOD" - }; - - // Destroy old KeyValues - if ( s_GameEvents.Count() ) - { - for ( int i = 0; i < s_GameEvents.Count(); ++i ) - s_GameEvents[i]->deleteThis(); - s_GameEvents.Purge(); - } - - for ( int j = 0; j < ARRAYSIZE(pathlist); ++j ) - for ( int i = 0; i < ARRAYSIZE(filenames); ++i ) - { - LoadEventsFromFile( filenames[i], pathlist[j] ); - } -} - -//----------------------------------------------------------------------------- -// Load event files into a lookup array to be able to return the event data to the VM. -//----------------------------------------------------------------------------- -void CScriptGameEventListener::LoadEventsFromFile( const char *filename, const char *pathID ) -{ - KeyValues *pKV = new KeyValues("GameEvents"); - - if ( !pKV->LoadFromFile( filesystem, filename, pathID ) ) - { - // DevMsg( "CScriptGameEventListener::LoadEventsFromFile: Failed to load file %s, %s\n", filename, pathID ); - pKV->deleteThis(); - return; - } - - // Set the key value types to what they are from their string description values to read the correct data type in WriteEventData. - // There might be a better way of doing this, but this is okay since it's only done on file load. - for ( KeyValues *key = pKV->GetFirstSubKey(); key; key = key->GetNextKey() ) - for ( KeyValues *sub = key->GetFirstSubKey(); sub; sub = sub->GetNextKey() ) - { - if ( sub->GetDataType() == KeyValues::TYPE_STRING ) - { - const char *szVal = sub->GetString(); - if ( !V_stricmp( szVal, "byte" ) || !V_stricmp( szVal, "short" ) || !V_stricmp( szVal, "long" ) || !V_stricmp( szVal, "bool" ) ) - { - sub->SetInt( NULL, 0 ); - } - else if ( !V_stricmp( szVal, "float" ) ) - { - sub->SetFloat( NULL, 0.0f ); - } - } - // none : value is not networked - // string : a zero terminated string - // bool : unsigned int, 1 bit - // byte : unsigned int, 8 bit - // short : signed int, 16 bit - // long : signed int, 32 bit - // float : float, 32 bit - } - - DevMsg( 2, "CScriptGameEventListener::LoadEventsFromFile: Loaded %s, %s\n", filename, pathID ); - - s_GameEvents.AddToTail(pKV); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CScriptGameEventListener::WriteEventData( IGameEvent *event, HSCRIPT hTable ) -{ - // TODO: Something more efficient than iterating through all the events that ever exist one by one - - const char *szEvent = event->GetName(); - for ( int i = 0; i < s_GameEvents.Count(); ++i ) - { - KeyValues *pKV = s_GameEvents[i]; - for ( KeyValues *key = pKV->GetFirstSubKey(); key; key = key->GetNextKey() ) - { - if ( !V_stricmp( key->GetName(), szEvent ) ) - { - for ( KeyValues *sub = key->GetFirstSubKey(); sub; sub = sub->GetNextKey() ) - { - const char *szKey = sub->GetName(); - switch ( sub->GetDataType() ) - { - case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, szKey, event->GetString( szKey ) ); break; - case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, szKey, event->GetInt ( szKey ) ); break; - case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, szKey, event->GetFloat ( szKey ) ); break; - // default: DevWarning( 2, "CScriptGameEventListener::WriteEventData: unknown data type '%d' on key '%s' in event '%s'\n", sub->GetDataType(), szKey, szEvent ); - } - } - return; - } - } - } -} -#endif // !CLIENT_DLL -//----------------------------------------------------------------------------- -// Find if context is in use by others; used to alloc/dealloc only when required. -// Returns allocated pointer to string -// Expects non-NULL context input -//----------------------------------------------------------------------------- -const char *CScriptGameEventListener::FindContext( const char *szContext, CScriptGameEventListener *pIgnore ) -{ - for ( int i = s_GameEventListeners.Count(); i--; ) - { - CScriptGameEventListener *pCur = s_GameEventListeners[i]; - if ( pCur != pIgnore ) - { - if ( pCur->m_pszContext && !V_stricmp( szContext, pCur->m_pszContext ) ) - { - return pCur->m_pszContext; - } - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -intptr_t CScriptGameEventListener::ListenToGameEvent( const char* szEvent, HSCRIPT hFunc, const char* szContext ) -{ - m_bActive = true; - - char *psz; - - if ( szContext && *szContext ) - { - psz = const_cast(FindContext(szContext)); - if ( !psz ) - { - int len = V_strlen(szContext) + 1; - if ( len > 1 ) - { - int size = min( len, 256 ); // arbitrary clamp - psz = new char[size]; - V_strncpy( psz, szContext, size ); - } - } - } - else - { - psz = NULL; - } - - m_pszContext = psz; - m_hCallback = hFunc; - - if ( gameeventmanager ) -#ifdef CLIENT_DLL - gameeventmanager->AddListener( this, szEvent, false ); -#else - gameeventmanager->AddListener( this, szEvent, true ); -#endif - s_GameEventListeners.AddToTail( this ); - - return reinterpret_cast(this); // POINTER_TO_INT -} - -//----------------------------------------------------------------------------- -// Free stuff. Called from the destructor, does not remove itself from the listener list. -//----------------------------------------------------------------------------- -void CScriptGameEventListener::StopListeningForEvent() -{ - if ( !m_bActive ) - return; - - if ( g_pScriptVM ) - { - g_pScriptVM->ReleaseScript( m_hCallback ); - } - else if ( m_hCallback ) - { - AssertMsg( 0, "LEAK (0x%p)\n", (void*)m_hCallback ); - } - - if ( m_pszContext ) - { - if ( !FindContext( m_pszContext, this ) ) - { - delete[] m_pszContext; - } - - m_pszContext = NULL; - } - - m_hCallback = NULL; - - if ( gameeventmanager ) - gameeventmanager->RemoveListener( this ); - - m_bActive = false; -} - -//----------------------------------------------------------------------------- -// Stop the specified event listener. -//----------------------------------------------------------------------------- -bool CScriptGameEventListener::StopListeningToGameEvent( intptr_t listener ) -{ - CScriptGameEventListener *p = reinterpret_cast(listener); // INT_TO_POINTER - - bool bRemoved = s_GameEventListeners.FindAndFastRemove(p); - if ( bRemoved ) - { - delete p; - } - - return bRemoved; -} - -//----------------------------------------------------------------------------- -// Stops listening to all events within a context. -//----------------------------------------------------------------------------- -void CScriptGameEventListener::StopListeningToAllGameEvents( const char* szContext ) -{ - if ( szContext ) - { - if ( *szContext ) - { - // Iterate from the end so they can be safely removed as they are deleted - for ( int i = s_GameEventListeners.Count(); i--; ) - { - CScriptGameEventListener *pCur = s_GameEventListeners[i]; - if ( pCur->m_pszContext && !V_stricmp( szContext, pCur->m_pszContext ) ) - { - s_GameEventListeners.Remove(i); // keep list order - delete pCur; - } - } - } - else // empty (NULL) context - { - for ( int i = s_GameEventListeners.Count(); i--; ) - { - CScriptGameEventListener *pCur = s_GameEventListeners[i]; - if ( !pCur->m_pszContext ) - { - s_GameEventListeners.Remove(i); - delete pCur; - } - } - } - } -#if 0 - if ( !szContext ) - { - for ( int i = s_GameEventListeners.Count(); i--; ) - delete s_GameEventListeners[i]; - s_GameEventListeners.Purge(); - } -#endif -} - -//============================================================================= -//============================================================================= - -static int ListenToGameEvent( const char* szEvent, HSCRIPT hFunc, const char* szContext ) -{ - CScriptGameEventListener *p = new CScriptGameEventListener(); - return p->ListenToGameEvent( szEvent, hFunc, szContext ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -static void FireGameEvent( const char* szEvent, HSCRIPT hTable ) -{ - IGameEvent *event = gameeventmanager->CreateEvent( szEvent ); - if ( event ) - { - ScriptVariant_t key, val; - int nIterator = -1; - while ( ( nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &key, &val ) ) != -1 ) - { - switch ( val.m_type ) - { - case FIELD_FLOAT: event->SetFloat ( key.m_pszString, val.m_float ); break; - case FIELD_INTEGER: event->SetInt ( key.m_pszString, val.m_int ); break; - case FIELD_BOOLEAN: event->SetBool ( key.m_pszString, val.m_bool ); break; - case FIELD_CSTRING: event->SetString( key.m_pszString, val.m_pszString ); break; - } - - g_pScriptVM->ReleaseValue(key); - g_pScriptVM->ReleaseValue(val); - } - -#ifdef CLIENT_DLL - gameeventmanager->FireEventClientSide(event); -#else - gameeventmanager->FireEvent(event); -#endif - } -} - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// Copy of FireGameEvent, server only with no broadcast to clients. -//----------------------------------------------------------------------------- -static void FireGameEventLocal( const char* szEvent, HSCRIPT hTable ) -{ - IGameEvent *event = gameeventmanager->CreateEvent( szEvent ); - if ( event ) - { - ScriptVariant_t key, val; - int nIterator = -1; - while ( ( nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &key, &val ) ) != -1 ) - { - switch ( val.m_type ) - { - case FIELD_FLOAT: event->SetFloat ( key.m_pszString, val.m_float ); break; - case FIELD_INTEGER: event->SetInt ( key.m_pszString, val.m_int ); break; - case FIELD_BOOLEAN: event->SetBool ( key.m_pszString, val.m_bool ); break; - case FIELD_CSTRING: event->SetString( key.m_pszString, val.m_pszString ); break; - } - - g_pScriptVM->ReleaseValue(key); - g_pScriptVM->ReleaseValue(val); - } - - gameeventmanager->FireEvent(event,true); - } -} -#endif // !CLIENT_DLL -//============================================================================= -//============================================================================= - static int ScriptPrecacheModel( const char *modelname ) { return CBaseEntity::PrecacheModel( modelname ); @@ -1381,6 +562,14 @@ static void ScriptPrecacheOther( const char *classname ) UTIL_PrecacheOther( classname ); } +#ifndef CLIENT_DLL +// TODO: Move this? +static void ScriptInsertSound( int iType, const Vector &vecOrigin, int iVolume, float flDuration, HSCRIPT hOwner, int soundChannelIndex, HSCRIPT hSoundTarget ) +{ + CSoundEnt::InsertSound( iType, vecOrigin, iVolume, flDuration, ToEnt(hOwner), soundChannelIndex, ToEnt(hSoundTarget) ); +} +#endif + //============================================================================= //============================================================================= @@ -1428,11 +617,20 @@ static void ScriptDecalTrace( HSCRIPT hTrace, const char *decalName ) //----------------------------------------------------------------------------- // Simple particle effect dispatch //----------------------------------------------------------------------------- -static void ScriptDispatchParticleEffect( const char *pszParticleName, const Vector &vecOrigin, const QAngle &vecAngles ) +static void ScriptDispatchParticleEffect( const char *pszParticleName, const Vector &vecOrigin, const QAngle &vecAngles, HSCRIPT hEntity ) { - DispatchParticleEffect( pszParticleName, vecOrigin, vecAngles ); + DispatchParticleEffect( pszParticleName, vecOrigin, vecAngles, ToEnt(hEntity) ); } +#ifndef CLIENT_DLL +const Vector& ScriptPredictedPosition( HSCRIPT hTarget, float flTimeDelta ) +{ + static Vector predicted; + UTIL_PredictedPosition( ToEnt(hTarget), flTimeDelta, &predicted ); + return predicted; +} +#endif + //============================================================================= //============================================================================= @@ -1488,491 +686,9 @@ void NXPrint( int pos, int r, int g, int b, bool fixed, float ftime, const char* // delete info; } -class CGlobalSys -{ -public: - const char* ScriptGetCommandLine() - { - return CommandLine()->GetCmdLine(); - } - - bool CommandLineCheck(const char* name) - { - return !!CommandLine()->FindParm(name); - } - - const char* CommandLineCheckStr(const char* name) - { - return CommandLine()->ParmValue(name); - } - - float CommandLineCheckFloat(const char* name) - { - return CommandLine()->ParmValue(name, 0); - } - - int CommandLineCheckInt(const char* name) - { - return CommandLine()->ParmValue(name, 0); - } -} g_ScriptGlobalSys; - -BEGIN_SCRIPTDESC_ROOT_NAMED( CGlobalSys, "CGlobalSys", SCRIPT_SINGLETON "GlobalSys" ) - DEFINE_SCRIPTFUNC_NAMED( ScriptGetCommandLine, "GetCommandLine", "returns the command line" ) - DEFINE_SCRIPTFUNC( CommandLineCheck, "returns true if the command line param was used, otherwise false." ) - DEFINE_SCRIPTFUNC( CommandLineCheckStr, "returns the command line param as a string." ) - DEFINE_SCRIPTFUNC( CommandLineCheckFloat, "returns the command line param as a float." ) - DEFINE_SCRIPTFUNC( CommandLineCheckInt, "returns the command line param as an int." ) -END_SCRIPTDESC(); - - -class CScriptSaveRestoreUtil : public CAutoGameSystem -{ -public: - static void SaveTable( const char *szId, HSCRIPT hTable ); - static void RestoreTable( const char *szId, HSCRIPT hTable ); - static void ClearSavedTable( const char *szId ); - -// IGameSystem interface -public: - void OnSave() - { - if ( g_pScriptVM ) - { - HSCRIPT hFunc = g_pScriptVM->LookupFunction( "OnSave" ); - if ( hFunc ) - { - g_pScriptVM->Call( hFunc ); - } - } - } - - void OnRestore() - { - if ( g_pScriptVM ) - { - HSCRIPT hFunc = g_pScriptVM->LookupFunction( "OnRestore" ); - if ( hFunc ) - { - g_pScriptVM->Call( hFunc ); - } - } - } - - void Shutdown() - { - FOR_EACH_VEC( m_aKeyValues, i ) - m_aKeyValues[i]->deleteThis(); - m_aKeyValues.Purge(); - m_aContext.PurgeAndDeleteElements(); - } - -private: - static int GetIndexForContext( const char *szId ); - - // indices must match, always remove keeping order - static CUtlStringList m_aContext; - static CUtlVector m_aKeyValues; - -} g_ScriptSaveRestoreUtil; - -CUtlStringList CScriptSaveRestoreUtil::m_aContext; -CUtlVector CScriptSaveRestoreUtil::m_aKeyValues; - -int CScriptSaveRestoreUtil::GetIndexForContext( const char *szId ) -{ - int idx = -1; - FOR_EACH_VEC( m_aContext, i ) - { - if ( !V_stricmp( szId, m_aContext[i] ) ) - { - idx = i; - break; - } - } - return idx; -} - -//----------------------------------------------------------------------------- -// Store a table with primitive values that will persist across level transitions and save loads. -//----------------------------------------------------------------------------- -void CScriptSaveRestoreUtil::SaveTable( const char *szId, HSCRIPT hTable ) -{ - int idx = GetIndexForContext(szId); - - KeyValues *pKV; - - if ( idx == -1 ) - { - pKV = new KeyValues("ScriptSavedTable"); - m_aKeyValues.AddToTail(pKV); - - if ( V_strlen(szId) > 255 ) // arbitrary clamp - { - char c[256]; - V_strncpy( c, szId, sizeof(c) ); - m_aContext.CopyAndAddToTail(c); - } - else - { - m_aContext.CopyAndAddToTail(szId); - } - } - else - { - pKV = m_aKeyValues[idx]; - pKV->Clear(); - } - - ScriptVariant_t key, val; - int nIterator = -1; - while ( ( nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &key, &val ) ) != -1 ) - { - switch ( val.m_type ) - { - case FIELD_FLOAT: pKV->SetFloat ( key.m_pszString, val.m_float ); break; - case FIELD_INTEGER: pKV->SetInt ( key.m_pszString, val.m_int ); break; - case FIELD_BOOLEAN: pKV->SetBool ( key.m_pszString, val.m_bool ); break; - case FIELD_CSTRING: pKV->SetString( key.m_pszString, val.m_pszString ); break; - } - - g_pScriptVM->ReleaseValue(key); - g_pScriptVM->ReleaseValue(val); - } -} - -//----------------------------------------------------------------------------- -// Retrieves a table from storage. Write into input table. -//----------------------------------------------------------------------------- -void CScriptSaveRestoreUtil::RestoreTable( const char *szId, HSCRIPT hTable ) -{ - int idx = GetIndexForContext(szId); - - KeyValues *pKV; - - if ( idx == -1 ) - { - // DevWarning( 2, "RestoreTable could not find saved table with context '%s'\n", szId ); - return; - } - else - { - pKV = m_aKeyValues[idx]; - } - - FOR_EACH_SUBKEY( pKV, key ) - { - switch ( key->GetDataType() ) - { - case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetString() ); break; - case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetInt() ); break; - case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetFloat() ); break; - } - } -} - -//----------------------------------------------------------------------------- -// Remove a saved table. -//----------------------------------------------------------------------------- -void CScriptSaveRestoreUtil::ClearSavedTable( const char *szId ) -{ - int idx = GetIndexForContext(szId); - - if ( idx == -1 ) - { - // DevWarning( 2, "ClearSavedTable could not find saved table with context '%s'\n", szId ); - return; - } - - m_aKeyValues[idx]->deleteThis(); - m_aKeyValues.Remove(idx); - - delete[] m_aContext[idx]; - m_aContext.Remove(idx); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -#define SCRIPT_MAX_FILE_READ_SIZE (16 * 1024) // 16KB -#define SCRIPT_MAX_FILE_WRITE_SIZE (64 * 1024 * 1024) // 64MB -#define SCRIPT_RW_PATH_ID "MOD" -#define SCRIPT_RW_FULL_PATH_FMT "export/%s" - -class CScriptReadWriteFile : public CAutoGameSystem -{ -public: - static bool ScriptFileWrite( const char *szFile, const char *szInput ); - static const char *ScriptFileRead( const char *szFile ); - //static const char *CRC32_Checksum( const char *szFilename ); - - void LevelShutdownPostEntity() - { - if ( m_pszReturnReadFile ) - { - delete[] m_pszReturnReadFile; - m_pszReturnReadFile = NULL; - } - - //if ( m_pszReturnCRC32 ) - //{ - // delete[] m_pszReturnCRC32; - // m_pszReturnCRC32 = NULL; - //} - } - -private: - static const char *m_pszReturnReadFile; - //static const char *m_pszReturnCRC32; - -} g_ScriptReadWrite; - -const char *CScriptReadWriteFile::m_pszReturnReadFile = NULL; -//const char *CScriptReadWriteFile::m_pszReturnCRC32 = NULL; - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -bool CScriptReadWriteFile::ScriptFileWrite( const char *szFile, const char *szInput ) -{ - size_t len = strlen(szInput); - if ( len > SCRIPT_MAX_FILE_WRITE_SIZE ) - { - DevWarning( 2, "Input is too large for a ScriptFileWrite ( %s / %d MB )\n", V_pretifymem(len,2,true), (SCRIPT_MAX_FILE_WRITE_SIZE >> 20) ); - return false; - } - - char pszFullName[MAX_PATH]; - V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile ); - - if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) - { - DevWarning( 2, "Invalid file location : %s\n", szFile ); - return false; - } - - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - buf.PutString(szInput); - - int nSize = V_strlen(pszFullName) + 1; - char *pszDir = (char*)stackalloc(nSize); - V_memcpy( pszDir, pszFullName, nSize ); - V_StripFilename( pszDir ); - - g_pFullFileSystem->CreateDirHierarchy( pszDir, SCRIPT_RW_PATH_ID ); - bool res = g_pFullFileSystem->WriteFile( pszFullName, SCRIPT_RW_PATH_ID, buf ); - buf.Purge(); - return res; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -const char *CScriptReadWriteFile::ScriptFileRead( const char *szFile ) -{ - char pszFullName[MAX_PATH]; - V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile ); - - if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) - { - DevWarning( 2, "Invalid file location : %s\n", szFile ); - return NULL; - } - - unsigned int size = g_pFullFileSystem->Size( pszFullName, SCRIPT_RW_PATH_ID ); - if ( size >= SCRIPT_MAX_FILE_READ_SIZE ) - { - DevWarning( 2, "File '%s' (from '%s') is too large for a ScriptFileRead ( %s / %u bytes )\n", pszFullName, szFile, V_pretifymem(size,2,true), SCRIPT_MAX_FILE_READ_SIZE ); - return NULL; - } - - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - if ( !g_pFullFileSystem->ReadFile( pszFullName, SCRIPT_RW_PATH_ID, buf, SCRIPT_MAX_FILE_READ_SIZE ) ) - { - return NULL; - } - - // first time calling, allocate - if ( !m_pszReturnReadFile ) - m_pszReturnReadFile = new char[SCRIPT_MAX_FILE_READ_SIZE]; - - V_strncpy( const_cast(m_pszReturnReadFile), (const char*)buf.Base(), buf.Size() ); - buf.Purge(); - return m_pszReturnReadFile; -} - -//----------------------------------------------------------------------------- -// Get the checksum of any file. Can be used to check the existence or validity of a file. -// Returns unsigned int as hex string. -//----------------------------------------------------------------------------- -/* -const char *CScriptReadWriteFile::CRC32_Checksum( const char *szFilename ) -{ - CUtlBuffer buf( 0, 0, CUtlBuffer::READ_ONLY ); - if ( !g_pFullFileSystem->ReadFile( szFilename, NULL, buf ) ) - return NULL; - - // first time calling, allocate - if ( !m_pszReturnCRC32 ) - m_pszReturnCRC32 = new char[9]; // 'FFFFFFFF\0' - - V_snprintf( const_cast(m_pszReturnCRC32), 9, "%X", CRC32_ProcessSingleBuffer( buf.Base(), buf.Size()-1 ) ); - buf.Purge(); - - return m_pszReturnCRC32; -} -*/ -#undef SCRIPT_MAX_FILE_READ_SIZE -#undef SCRIPT_MAX_FILE_WRITE_SIZE -#undef SCRIPT_RW_PATH_ID -#undef SCRIPT_RW_FULL_PATH_FMT - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -#ifndef CLIENT_DLL -class CNetMsgScriptHelper -{ -private: - CRecipientFilter filter; - bf_write message; - byte data_msg[ MAX_USER_MSG_DATA ]; - - inline void SendMsg( bf_write *bf ) - { - bf_read buffer = bf_read(); - buffer.StartReading( message.GetData(), message.m_nDataBytes ); - bf->WriteBitsFromBuffer( &buffer, message.GetNumBitsWritten() ); - engine->MessageEnd(); - } - -public: - inline void Reset() - { - message.StartWriting( data_msg, sizeof(data_msg) ); - filter.Reset(); - } - - void SendUserMessage( HSCRIPT player, const char *msg, bool bReliable ) - { - int msg_type = usermessages->LookupUserMessage(msg); - if ( msg_type == -1 ) - { - g_pScriptVM->RaiseException("UserMessageBegin: Unregistered message"); - return; - } - - CBaseEntity *pPlayer = ToEnt(player); - if ( pPlayer ) - { - filter.AddRecipient( (CBasePlayer*)pPlayer ); - } - - if ( bReliable ) - { - filter.MakeReliable(); - } - - SendMsg( engine->UserMessageBegin( &filter, msg_type ) ); - } - - void SendEntityMessage( HSCRIPT hEnt, bool bReliable ) - { - CBaseEntity *entity = ToEnt(hEnt); - if ( !entity ) - { - g_pScriptVM->RaiseException("EntityMessageBegin: invalid entity"); - return; - } - - SendMsg( engine->EntityMessageBegin( entity->entindex(), entity->GetServerClass(), bReliable ) ); - } - -public: - void AddRecipient( HSCRIPT player ) - { - CBaseEntity *pPlayer = ToEnt(player); - if ( pPlayer ) - { - filter.AddRecipient( (CBasePlayer*)pPlayer ); - } - } - - void AddRecipientsByPVS( const Vector &pos ) - { - filter.AddRecipientsByPVS(pos); - } - - void AddAllPlayers() - { - filter.AddAllPlayers(); - } - -public: - void WriteByte( int iValue ) { message.WriteByte( iValue ); } - void WriteChar( int iValue ) { message.WriteChar( iValue ); } - void WriteShort( int iValue ) { message.WriteShort( iValue ); } - void WriteWord( int iValue ) { message.WriteWord( iValue ); } - void WriteLong( int iValue ) { message.WriteLong( iValue ); } - void WriteFloat( float flValue ) { message.WriteFloat( flValue ); } - void WriteAngle( float flValue ) { message.WriteBitAngle( flValue, 8 ); } - void WriteCoord( float flValue ) { message.WriteBitCoord( flValue ); } - void WriteVec3Coord( const Vector& rgflValue ) { message.WriteBitVec3Coord( rgflValue ); } - void WriteVec3Normal( const Vector& rgflValue ) { message.WriteBitVec3Normal( rgflValue ); } - void WriteAngles( const QAngle& rgflValue ) { message.WriteBitAngles( rgflValue ); } - void WriteString( const char *sz ) { message.WriteString( sz ); } - void WriteEntity( int iValue ) { message.WriteShort( iValue ); } - void WriteBool( bool bValue ) { message.WriteOneBit( bValue ? 1 : 0 ); } - void WriteEHandle( HSCRIPT hEnt ) - { - CBaseEntity *pEnt = ToEnt( hEnt ); - long iEncodedEHandle; - if ( pEnt ) - { - EHANDLE hEnt = pEnt; - int iSerialNum = hEnt.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; - iEncodedEHandle = hEnt.GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); - } - else - { - iEncodedEHandle = INVALID_NETWORKED_EHANDLE_VALUE; - } - message.WriteLong( iEncodedEHandle ); - } - -} g_ScriptNetMsg; - -BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "NetworkMessages" ) - DEFINE_SCRIPTFUNC( Reset, "" ) - DEFINE_SCRIPTFUNC( SendUserMessage, "" ) - DEFINE_SCRIPTFUNC( SendEntityMessage, "" ) - DEFINE_SCRIPTFUNC( AddRecipient, "" ) - DEFINE_SCRIPTFUNC( AddRecipientsByPVS, "" ) - DEFINE_SCRIPTFUNC( AddAllPlayers, "" ) - DEFINE_SCRIPTFUNC( WriteByte, "" ) - DEFINE_SCRIPTFUNC( WriteChar, "" ) - DEFINE_SCRIPTFUNC( WriteShort, "" ) - DEFINE_SCRIPTFUNC( WriteWord, "" ) - DEFINE_SCRIPTFUNC( WriteLong, "" ) - DEFINE_SCRIPTFUNC( WriteFloat, "" ) - DEFINE_SCRIPTFUNC( WriteAngle, "" ) - DEFINE_SCRIPTFUNC( WriteCoord, "" ) - DEFINE_SCRIPTFUNC( WriteVec3Coord, "" ) - DEFINE_SCRIPTFUNC( WriteVec3Normal, "" ) - DEFINE_SCRIPTFUNC( WriteAngles, "" ) - DEFINE_SCRIPTFUNC( WriteString, "" ) - DEFINE_SCRIPTFUNC( WriteEntity, "" ) - DEFINE_SCRIPTFUNC( WriteEHandle, "" ) - DEFINE_SCRIPTFUNC( WriteBool, "" ) -END_SCRIPTDESC(); - -#endif // !CLIENT_DLL - //============================================================================= //============================================================================= -extern void RegisterMathScriptFunctions(); - void RegisterSharedScriptFunctions() { // @@ -1986,46 +702,19 @@ void RegisterSharedScriptFunctions() ScriptRegisterFunction( g_pScriptVM, EmitSoundOnClient, "Play named sound only on the client for the specified player." ); ScriptRegisterFunction( g_pScriptVM, AddThinkToEnt, "This will put a think function onto an entity, or pass null to remove it. This is NOT chained, so be careful." ); - ScriptRegisterFunction( g_pScriptVM, EntIndexToHScript, "Returns the script handle for the given entity index." ); ScriptRegisterFunction( g_pScriptVM, PrecacheEntityFromTable, "Precache an entity from KeyValues in a table." ); ScriptRegisterFunction( g_pScriptVM, SpawnEntityFromTable, "Native function for entity spawning." ); #endif // !CLIENT_DLL - - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptSaveRestoreUtil::SaveTable, "SaveTable", "Store a table with primitive values that will persist across level transitions and save loads." ); - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptSaveRestoreUtil::RestoreTable, "RestoreTable", "Retrieves a table from storage. Write into input table." ); - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptSaveRestoreUtil::ClearSavedTable, "ClearSavedTable", "Removes the table with the given context." ); - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptReadWriteFile::ScriptFileWrite, "StringToFile", "Stores the string into the file" ); - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptReadWriteFile::ScriptFileRead, "FileToString", "Returns the string from the file, null if no file or file is too big." ); - - ScriptRegisterFunction( g_pScriptVM, ListenToGameEvent, "Register as a listener for a game event from script." ); - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptGameEventListener::StopListeningToGameEvent, "StopListeningToGameEvent", "Stop the specified event listener." ); - ScriptRegisterFunctionNamed( g_pScriptVM, CScriptGameEventListener::StopListeningToAllGameEvents, "StopListeningToAllGameEvents", "Stop listening to all game events within a specific context." ); - ScriptRegisterFunction( g_pScriptVM, FireGameEvent, "Fire a game event." ); -#ifndef CLIENT_DLL - ScriptRegisterFunction( g_pScriptVM, FireGameEventLocal, "Fire a game event without broadcasting to the client." ); -#endif - - g_pScriptVM->RegisterInstance( &g_ScriptConvarLookup, "Convars" ); - g_pScriptVM->RegisterInstance( &g_ScriptNetPropManager, "NetProps" ); - g_pScriptVM->RegisterInstance( &g_ScriptGlobalSys, "GlobalSys" ); + ScriptRegisterFunction( g_pScriptVM, EntIndexToHScript, "Returns the script handle for the given entity index." ); //----------------------------------------------------------------------------- - // Functions, singletons, etc. unique to Mapbase + // Functions, etc. unique to Mapbase //----------------------------------------------------------------------------- - g_pScriptVM->RegisterInstance( GetAmmoDef(), "AmmoDef" ); - g_pScriptVM->RegisterInstance( &g_ScriptLocalize, "Localize" ); -#ifndef CLIENT_DLL - g_pScriptVM->RegisterInstance( &g_ScriptNetMsg, "NetMsg" ); -#endif - //----------------------------------------------------------------------------- - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMsg, "Msg", "" ); ScriptRegisterFunction( g_pScriptVM, NPrint, "Notification print" ); ScriptRegisterFunction( g_pScriptVM, NXPrint, "Notification print, customised" ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptColorPrint, "printc", "Version of print() which takes a color before the message." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptColorPrintL, "printcl", "Version of printl() which takes a color before the message." ); #ifndef CLIENT_DLL ScriptRegisterFunction( g_pScriptVM, SpawnEntityFromKeyValues, "Spawns an entity with the keyvalues in a CScriptKeyValues handle." ); @@ -2062,33 +751,38 @@ void RegisterSharedScriptFunctions() ScriptRegisterFunction( g_pScriptVM, PrecacheParticleSystem, "Precaches a particle system for later usage." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPrecacheOther, "PrecacheOther", "Precaches an entity class for later usage." ); + // + // NPCs + // +#ifndef CLIENT_DLL + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptInsertSound, "InsertAISound", "Inserts an AI sound." ); +#endif + // // Misc. Utility // - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptEntitiesInBox, "EntitiesInBox", "Gets all entities which are within a worldspace box." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptEntitiesAtPoint, "EntitiesAtPoint", "Gets all entities which are intersecting a point in space." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptEntitiesInSphere, "EntitiesInSphere", "Gets all entities which are within a sphere." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptEntitiesInBox, "EntitiesInBox", "Gets all entities which are within a worldspace box. This function copies them to an array with a maximum number of elements." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptEntitiesAtPoint, "EntitiesAtPoint", "Gets all entities which are intersecting a point in space. This function copies them to an array with a maximum number of elements." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptEntitiesInSphere, "EntitiesInSphere", "Gets all entities which are within a sphere. This function copies them to an array with a maximum number of elements." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptDecalTrace, "DecalTrace", "Creates a dynamic decal based on the given trace info. The trace information can be generated by TraceLineComplex() and the decal name must be from decals_subrect.txt." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptDispatchParticleEffect, "DispatchParticleEffect", "Dispatches a one-off particle system" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptDispatchParticleEffect, "DoDispatchParticleEffect", SCRIPT_ALIAS( "DispatchParticleEffect", "Dispatches a one-off particle system" ) ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatcherMatch, "Matcher_Match", "Compares a string to a query using Mapbase's matcher system, supporting wildcards, RS matchers, etc." ); ScriptRegisterFunction( g_pScriptVM, Matcher_NamesMatch, "Compares a string to a query using Mapbase's matcher system using wildcards only." ); ScriptRegisterFunction( g_pScriptVM, AppearsToBeANumber, "Checks if the given string appears to be a number." ); +#ifndef CLIENT_DLL + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPredictedPosition, "PredictedPosition", "Predicts what an entity's position will be in a given amount of time." ); +#endif + #ifndef CLIENT_DLL ScriptRegisterFunction( g_pScriptVM, IsDedicatedServer, "Is this a dedicated server?" ); #endif ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsServer, "IsServer", "Returns true if the script is being run on the server." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsClient, "IsClient", "Returns true if the script is being run on the client." ); - ScriptRegisterFunction( g_pScriptVM, GetCPUUsage, "Get CPU usage percentage." ); - - RegisterMathScriptFunctions(); - -#ifndef CLIENT_DLL - CScriptGameEventListener::LoadAllEvents(); -#endif // !CLIENT_DLL + RegisterScriptSingletons(); #ifdef CLIENT_DLL VScriptRunScript( "vscript_client", true ); diff --git a/sp/src/game/shared/mapbase/vscript_funcs_shared.h b/sp/src/game/shared/mapbase/vscript_funcs_shared.h index ff4a1aff..2c6aaa1d 100644 --- a/sp/src/game/shared/mapbase/vscript_funcs_shared.h +++ b/sp/src/game/shared/mapbase/vscript_funcs_shared.h @@ -1,10 +1,6 @@ //========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= // -// Purpose: Due to this being a custom integration of VScript based on the Alien Swarm SDK, we don't have access to -// some of the code normally available in games like L4D2 or Valve's original VScript DLL. -// Instead, that code is recreated here, shared between server and client. -// -// It also contains other functions unique to Mapbase. +// Purpose: See vscript_funcs_shared.cpp // // $NoKeywords: $ //============================================================================= diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp new file mode 100644 index 00000000..297b1b9a --- /dev/null +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -0,0 +1,1354 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: This file contains brand new VScript singletons and singletons replicated from API +// documentation in other games. +// +// See vscript_funcs_shared.cpp for more information. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include +#include +#include "ammodef.h" + +#ifndef CLIENT_DLL +#include "usermessages.h" +#include "ai_squad.h" +#endif // !CLIENT_DLL + +#include "filesystem.h" +#include "igameevents.h" + +#include "vscript_singletons.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern IScriptManager *scriptmanager; + +//============================================================================= +// Net Prop Manager +// Based on L4D2 API +//============================================================================= +class CScriptNetPropManager +{ +public: + +#ifdef CLIENT_DLL + RecvProp *RecurseTable( RecvTable *pTable, const char *pszPropName ) +#else + SendProp *RecurseTable( SendTable *pTable, const char *pszPropName ) +#endif + { +#ifdef CLIENT_DLL + RecvProp *pProp = NULL; +#else + SendProp *pProp = NULL; +#endif + for (int i = 0; i < pTable->GetNumProps(); i++) + { + pProp = pTable->GetProp( i ); + if (pProp->GetType() == DPT_DataTable) + { + pProp = RecurseTable(pProp->GetDataTable(), pszPropName); + if (pProp) + return pProp; + } + else + { + if (FStrEq( pProp->GetName(), pszPropName )) + return pProp; + } + } + + return NULL; + } + +#ifdef CLIENT_DLL + RecvProp *RecurseNetworkClass( ClientClass *pClass, const char *pszPropName ) +#else + SendProp *RecurseNetworkClass( ServerClass *pClass, const char *pszPropName ) +#endif + { +#ifdef CLIENT_DLL + RecvProp *pProp = RecurseTable( pClass->m_pRecvTable, pszPropName ); +#else + SendProp *pProp = RecurseTable( pClass->m_pTable, pszPropName ); +#endif + if (pProp) + return pProp; + + if (pClass->m_pNext) + return RecurseNetworkClass( pClass->m_pNext, pszPropName ); + else + return NULL; + } + +#ifdef CLIENT_DLL + RecvProp *GetPropByName( CBaseEntity *pEnt, const char *pszPropName ) + { + if (pEnt) + { + return RecurseNetworkClass( pEnt->GetClientClass(), pszPropName ); + } + + return NULL; + } +#else + SendProp *GetPropByName( CBaseEntity *pEnt, const char *pszPropName ) + { + if (pEnt) + { + return RecurseNetworkClass( pEnt->GetServerClass(), pszPropName ); + } + + return NULL; + } +#endif + + int GetPropArraySize( HSCRIPT hEnt, const char *pszPropName ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp) + { + // TODO: Is this what this function wants? + return pProp->GetNumElements(); + } + + return -1; + } + + #define GetPropFunc( name, varType, propType, defaultval ) \ + varType name( HSCRIPT hEnt, const char *pszPropName ) \ + { \ + CBaseEntity *pEnt = ToEnt( hEnt ); \ + auto *pProp = GetPropByName( pEnt, pszPropName ); \ + if (pProp && pProp->GetType() == propType) \ + { \ + return *(varType*)((char *)pEnt + pProp->GetOffset()); \ + } \ + return defaultval; \ + } \ + + #define GetPropFuncArray( name, varType, propType, defaultval ) \ + varType name( HSCRIPT hEnt, const char *pszPropName, int iArrayElement ) \ + { \ + CBaseEntity *pEnt = ToEnt( hEnt ); \ + auto *pProp = GetPropByName( pEnt, pszPropName ); \ + if (pProp && pProp->GetType() == propType) \ + { \ + return ((varType*)((char *)pEnt + pProp->GetOffset()))[iArrayElement]; \ + } \ + return defaultval; \ + } \ + + GetPropFunc( GetPropFloat, float, DPT_Float, -1 ); + GetPropFuncArray( GetPropFloatArray, float, DPT_Float, -1 ); + GetPropFunc( GetPropInt, int, DPT_Int, -1 ); + GetPropFuncArray( GetPropIntArray, int, DPT_Int, -1 ); + GetPropFunc( GetPropVector, Vector, DPT_Vector, vec3_invalid ); + GetPropFuncArray( GetPropVectorArray, Vector, DPT_Vector, vec3_invalid ); + + HSCRIPT GetPropEntity( HSCRIPT hEnt, const char *pszPropName ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp && pProp->GetType() == DPT_Int) + { + return ToHScript( *(CHandle*)((char *)pEnt + pProp->GetOffset()) ); + } + + return NULL; + } + + HSCRIPT GetPropEntityArray( HSCRIPT hEnt, const char *pszPropName, int iArrayElement ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp && pProp->GetType() == DPT_Int) + { + return ToHScript( ((CHandle*)((char *)pEnt + pProp->GetOffset()))[iArrayElement] ); + } + + return NULL; + } + + const char *GetPropString( HSCRIPT hEnt, const char *pszPropName ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp && pProp->GetType() == DPT_Int) + { + return (const char*)((char *)pEnt + pProp->GetOffset()); + } + + return NULL; + } + + const char *GetPropStringArray( HSCRIPT hEnt, const char *pszPropName, int iArrayElement ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp && pProp->GetType() == DPT_Int) + { + return ((const char**)((char *)pEnt + pProp->GetOffset()))[iArrayElement]; + } + + return NULL; + } + + const char *GetPropType( HSCRIPT hEnt, const char *pszPropName ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp) + { + switch (pProp->GetType()) + { + case DPT_Int: return "integer"; + case DPT_Float: return "float"; + case DPT_Vector: return "vector"; + case DPT_VectorXY: return "vector2d"; + case DPT_String: return "string"; + case DPT_Array: return "array"; + case DPT_DataTable: return "datatable"; + } + } + + return NULL; + } + + bool HasProp( HSCRIPT hEnt, const char *pszPropName ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + return GetPropByName( pEnt, pszPropName ) != NULL; + } + + #define SetPropFunc( name, varType, propType ) \ + void name( HSCRIPT hEnt, const char *pszPropName, varType value ) \ + { \ + CBaseEntity *pEnt = ToEnt( hEnt ); \ + auto *pProp = GetPropByName( pEnt, pszPropName ); \ + if (pProp && pProp->GetType() == propType) \ + { \ + *(varType*)((char *)pEnt + pProp->GetOffset()) = value; \ + } \ + } \ + + #define SetPropFuncArray( name, varType, propType ) \ + void name( HSCRIPT hEnt, const char *pszPropName, varType value, int iArrayElement ) \ + { \ + CBaseEntity *pEnt = ToEnt( hEnt ); \ + auto *pProp = GetPropByName( pEnt, pszPropName ); \ + if (pProp && pProp->GetType() == propType) \ + { \ + ((varType*)((char *)pEnt + pProp->GetOffset()))[iArrayElement] = value; \ + } \ + } \ + + SetPropFunc( SetPropFloat, float, DPT_Float ); + SetPropFuncArray( SetPropFloatArray, float, DPT_Float ); + SetPropFunc( SetPropInt, int, DPT_Int ); + SetPropFuncArray( SetPropIntArray, int, DPT_Int ); + SetPropFunc( SetPropVector, Vector, DPT_Vector ); + SetPropFuncArray( SetPropVectorArray, Vector, DPT_Vector ); + SetPropFunc( SetPropString, const char*, DPT_String ); + SetPropFuncArray( SetPropStringArray, const char*, DPT_String ); + + void SetPropEntity( HSCRIPT hEnt, const char *pszPropName, HSCRIPT value ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp && pProp->GetType() == DPT_Int) + { + *((CHandle*)((char *)pEnt + pProp->GetOffset())) = ToEnt(value); + } + } + + HSCRIPT SetPropEntityArray( HSCRIPT hEnt, const char *pszPropName, HSCRIPT value, int iArrayElement ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + auto *pProp = GetPropByName( pEnt, pszPropName ); + if (pProp && pProp->GetType() == DPT_Int) + { + ((CHandle*)((char *)pEnt + pProp->GetOffset()))[iArrayElement] = ToEnt(value); + } + + return NULL; + } + +private: +} g_ScriptNetPropManager; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptNetPropManager, "CNetPropManager", SCRIPT_SINGLETON "Allows reading and updating the network properties of an entity." ) + DEFINE_SCRIPTFUNC( GetPropArraySize, "Returns the size of an netprop array, or -1." ) + DEFINE_SCRIPTFUNC( GetPropEntity, "Reads an EHANDLE valued netprop (21 bit integer). Returns the script handle of the entity." ) + DEFINE_SCRIPTFUNC( GetPropEntityArray, "Reads an EHANDLE valued netprop (21 bit integer) from an array. Returns the script handle of the entity." ) + DEFINE_SCRIPTFUNC( GetPropFloat, "Reads a float valued netprop." ) + DEFINE_SCRIPTFUNC( GetPropFloatArray, "Reads a float valued netprop from an array." ) + DEFINE_SCRIPTFUNC( GetPropInt, "Reads an integer valued netprop." ) + DEFINE_SCRIPTFUNC( GetPropIntArray, "Reads an integer valued netprop from an array." ) + DEFINE_SCRIPTFUNC( GetPropString, "Reads a string valued netprop." ) + DEFINE_SCRIPTFUNC( GetPropStringArray, "Reads a string valued netprop from an array." ) + DEFINE_SCRIPTFUNC( GetPropVector, "Reads a 3D vector valued netprop." ) + DEFINE_SCRIPTFUNC( GetPropVectorArray, "Reads a 3D vector valued netprop from an array." ) + DEFINE_SCRIPTFUNC( GetPropType, "Returns the name of the netprop type as a string." ) + DEFINE_SCRIPTFUNC( HasProp, "Checks if a netprop exists." ) + DEFINE_SCRIPTFUNC( SetPropEntity, "Sets an EHANDLE valued netprop (21 bit integer) to reference the specified entity." ) + DEFINE_SCRIPTFUNC( SetPropEntityArray, "Sets an EHANDLE valued netprop (21 bit integer) from an array to reference the specified entity." ) + DEFINE_SCRIPTFUNC( SetPropFloat, "Sets a netprop to the specified float." ) + DEFINE_SCRIPTFUNC( SetPropFloatArray, "Sets a netprop from an array to the specified float." ) + DEFINE_SCRIPTFUNC( SetPropInt, "Sets a netprop to the specified integer." ) + DEFINE_SCRIPTFUNC( SetPropIntArray, "Sets a netprop from an array to the specified integer." ) + DEFINE_SCRIPTFUNC( SetPropString, "Sets a netprop to the specified string." ) + DEFINE_SCRIPTFUNC( SetPropStringArray, "Sets a netprop from an array to the specified string." ) + DEFINE_SCRIPTFUNC( SetPropVector, "Sets a netprop to the specified vector." ) + DEFINE_SCRIPTFUNC( SetPropVectorArray, "Sets a netprop from an array to the specified vector." ) +END_SCRIPTDESC(); + +//============================================================================= +// Localization Interface +// Unique to Mapbase +//============================================================================= +class CScriptLocalize +{ +public: + + const char *GetTokenAsUTF8( const char *pszToken ) + { + const char *pText = g_pVGuiLocalize->FindAsUTF8( pszToken ); + if ( pText ) + { + return pText; + } + + return NULL; + } + + void AddStringAsUTF8( const char *pszToken, const char *pszString ) + { + wchar_t wpszString[256]; + g_pVGuiLocalize->ConvertANSIToUnicode( pszString, wpszString, sizeof(wpszString) ); + + // TODO: This is a fake file name! Should "fileName" mean anything? + g_pVGuiLocalize->AddString( pszToken, wpszString, "resource/vscript_localization.txt" ); + } + +private: +} g_ScriptLocalize; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptLocalize, "CLocalize", SCRIPT_SINGLETON "Accesses functions related to localization strings." ) + + DEFINE_SCRIPTFUNC( GetTokenAsUTF8, "Gets the current language's token as a UTF-8 string (not Unicode)." ) + + DEFINE_SCRIPTFUNC( AddStringAsUTF8, "Adds a new localized token as a UTF-8 string (not Unicode)." ) + +END_SCRIPTDESC(); + +//============================================================================= +// Game Event Listener +// Based on Source 2 API +//============================================================================= +class CScriptGameEventListener : public IGameEventListener2, public CAutoGameSystem +{ +public: + CScriptGameEventListener() : m_bActive(false) {} + ~CScriptGameEventListener() + { + StopListeningForEvent(); + } + + intptr_t ListenToGameEvent( const char* szEvent, HSCRIPT hFunc, const char* szContext ); + void StopListeningForEvent(); + +public: + static bool StopListeningToGameEvent( intptr_t listener ); + static void StopListeningToAllGameEvents( const char* szContext ); + +public: + void FireGameEvent( IGameEvent *event ); + void LevelShutdownPreEntity(); + +private: + bool m_bActive; + const char *m_pszContext; + HSCRIPT m_hCallback; + + static const char *FindContext( const char *szContext, CScriptGameEventListener *pIgnore = NULL ); + //inline const char *GetContext( CScriptGameEventListener *p ); + //inline const char *GetContext(); + +public: + static void DumpEventListeners(); +#ifndef CLIENT_DLL + static void LoadAllEvents(); + static void LoadEventsFromFile( const char *filename, const char *pathID = NULL ); + static void WriteEventData( IGameEvent *event, HSCRIPT hTable ); +#endif // !CLIENT_DLL + +private: +#ifndef CLIENT_DLL + static CUtlVector< KeyValues* > s_GameEvents; +#endif // !CLIENT_DLL + static CUtlVectorAutoPurge< CScriptGameEventListener* > s_GameEventListeners; + +}; + +#ifndef CLIENT_DLL +CUtlVector< KeyValues* > CScriptGameEventListener::s_GameEvents; +#endif // !CLIENT_DLL +CUtlVectorAutoPurge< CScriptGameEventListener* > CScriptGameEventListener::s_GameEventListeners; + +#if 0 +#ifdef CLIENT_DLL +CON_COMMAND_F( cl_dump_script_game_event_listeners, "Dump all game event listeners created from script.", FCVAR_CHEAT ) +{ + CScriptGameEventListener::DumpEventListeners(); +} +#else // GAME_DLL +CON_COMMAND_F( dump_script_game_event_listeners, "Dump all game event listeners created from script.", FCVAR_CHEAT ) +{ + CScriptGameEventListener::DumpEventListeners(); +} +#endif // CLIENT_DLL +#endif + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CScriptGameEventListener::DumpEventListeners() +{ + CGMsg( 0, CON_GROUP_VSCRIPT, "--- Script game event listener dump start\n" ); + FOR_EACH_VEC( s_GameEventListeners, i ) + { + CGMsg( 0, CON_GROUP_VSCRIPT, " %d (0x%p) %d : %s\n", i,s_GameEventListeners[i], + s_GameEventListeners[i], + s_GameEventListeners[i]->m_pszContext ? s_GameEventListeners[i]->m_pszContext : ""); + } + CGMsg( 0, CON_GROUP_VSCRIPT, "--- Script game event listener dump end\n" ); +} + +void CScriptGameEventListener::FireGameEvent( IGameEvent *event ) +{ + ScriptVariant_t hTable; + g_pScriptVM->CreateTable( hTable ); + // TODO: pass event data on client +#ifdef GAME_DLL + WriteEventData( event, hTable ); +#endif + g_pScriptVM->SetValue( hTable, "game_event_listener", reinterpret_cast(this) ); // POINTER_TO_INT + // g_pScriptVM->SetValue( hTable, "game_event_name", event->GetName() ); + g_pScriptVM->ExecuteFunction( m_hCallback, &hTable, 1, NULL, NULL, true ); + g_pScriptVM->ReleaseScript( hTable ); +} + +void CScriptGameEventListener::LevelShutdownPreEntity() +{ + s_GameEventListeners.FindAndFastRemove(this); + delete this; +} + +//----------------------------------------------------------------------------- +// Executed in LevelInitPreEntity +//----------------------------------------------------------------------------- +#ifndef CLIENT_DLL +void CScriptGameEventListener::LoadAllEvents() +{ + // Listed in the same order they are loaded in GameEventManager + const char *filenames[] = + { + "resource/serverevents.res", + "resource/gameevents.res", + "resource/mapbaseevents.res", + "resource/modevents.res" + }; + + const char *pathlist[] = + { + "GAME", + "MOD" + }; + + // Destroy old KeyValues + if ( s_GameEvents.Count() ) + { + for ( int i = 0; i < s_GameEvents.Count(); ++i ) + s_GameEvents[i]->deleteThis(); + s_GameEvents.Purge(); + } + + for ( int j = 0; j < ARRAYSIZE(pathlist); ++j ) + for ( int i = 0; i < ARRAYSIZE(filenames); ++i ) + { + LoadEventsFromFile( filenames[i], pathlist[j] ); + } +} + +//----------------------------------------------------------------------------- +// Load event files into a lookup array to be able to return the event data to the VM. +//----------------------------------------------------------------------------- +void CScriptGameEventListener::LoadEventsFromFile( const char *filename, const char *pathID ) +{ + KeyValues *pKV = new KeyValues("GameEvents"); + + if ( !pKV->LoadFromFile( filesystem, filename, pathID ) ) + { + // CGMsg( 1, CON_GROUP_VSCRIPT, "CScriptGameEventListener::LoadEventsFromFile: Failed to load file %s, %s\n", filename, pathID ); + pKV->deleteThis(); + return; + } + + // Set the key value types to what they are from their string description values to read the correct data type in WriteEventData. + // There might be a better way of doing this, but this is okay since it's only done on file load. + for ( KeyValues *key = pKV->GetFirstSubKey(); key; key = key->GetNextKey() ) + for ( KeyValues *sub = key->GetFirstSubKey(); sub; sub = sub->GetNextKey() ) + { + if ( sub->GetDataType() == KeyValues::TYPE_STRING ) + { + const char *szVal = sub->GetString(); + if ( !V_stricmp( szVal, "byte" ) || !V_stricmp( szVal, "short" ) || !V_stricmp( szVal, "long" ) || !V_stricmp( szVal, "bool" ) ) + { + sub->SetInt( NULL, 0 ); + } + else if ( !V_stricmp( szVal, "float" ) ) + { + sub->SetFloat( NULL, 0.0f ); + } + } + // none : value is not networked + // string : a zero terminated string + // bool : unsigned int, 1 bit + // byte : unsigned int, 8 bit + // short : signed int, 16 bit + // long : signed int, 32 bit + // float : float, 32 bit + } + + CGMsg( 2, CON_GROUP_VSCRIPT, "CScriptGameEventListener::LoadEventsFromFile: Loaded %s, %s\n", filename, pathID ); + + s_GameEvents.AddToTail(pKV); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CScriptGameEventListener::WriteEventData( IGameEvent *event, HSCRIPT hTable ) +{ + // TODO: Something more efficient than iterating through all the events that ever exist one by one + + const char *szEvent = event->GetName(); + for ( int i = 0; i < s_GameEvents.Count(); ++i ) + { + KeyValues *pKV = s_GameEvents[i]; + for ( KeyValues *key = pKV->GetFirstSubKey(); key; key = key->GetNextKey() ) + { + if ( !V_stricmp( key->GetName(), szEvent ) ) + { + for ( KeyValues *sub = key->GetFirstSubKey(); sub; sub = sub->GetNextKey() ) + { + const char *szKey = sub->GetName(); + switch ( sub->GetDataType() ) + { + case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, szKey, event->GetString( szKey ) ); break; + case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, szKey, event->GetInt ( szKey ) ); break; + case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, szKey, event->GetFloat ( szKey ) ); break; + // default: DevWarning( 2, "CScriptGameEventListener::WriteEventData: unknown data type '%d' on key '%s' in event '%s'\n", sub->GetDataType(), szKey, szEvent ); + } + } + return; + } + } + } +} +#endif // !CLIENT_DLL +//----------------------------------------------------------------------------- +// Find if context is in use by others; used to alloc/dealloc only when required. +// Returns allocated pointer to string +// Expects non-NULL context input +//----------------------------------------------------------------------------- +const char *CScriptGameEventListener::FindContext( const char *szContext, CScriptGameEventListener *pIgnore ) +{ + for ( int i = s_GameEventListeners.Count(); i--; ) + { + CScriptGameEventListener *pCur = s_GameEventListeners[i]; + if ( pCur != pIgnore ) + { + if ( pCur->m_pszContext && !V_stricmp( szContext, pCur->m_pszContext ) ) + { + return pCur->m_pszContext; + } + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +intptr_t CScriptGameEventListener::ListenToGameEvent( const char* szEvent, HSCRIPT hFunc, const char* szContext ) +{ + m_bActive = true; + + char *psz; + + if ( szContext && *szContext ) + { + psz = const_cast(FindContext(szContext)); + if ( !psz ) + { + int len = V_strlen(szContext) + 1; + if ( len > 1 ) + { + int size = min( len, 256 ); // arbitrary clamp + psz = new char[size]; + V_strncpy( psz, szContext, size ); + } + } + } + else + { + psz = NULL; + } + + m_pszContext = psz; + m_hCallback = hFunc; + + if ( gameeventmanager ) +#ifdef CLIENT_DLL + gameeventmanager->AddListener( this, szEvent, false ); +#else + gameeventmanager->AddListener( this, szEvent, true ); +#endif + s_GameEventListeners.AddToTail( this ); + + return reinterpret_cast(this); // POINTER_TO_INT +} + +//----------------------------------------------------------------------------- +// Free stuff. Called from the destructor, does not remove itself from the listener list. +//----------------------------------------------------------------------------- +void CScriptGameEventListener::StopListeningForEvent() +{ + if ( !m_bActive ) + return; + + if ( g_pScriptVM ) + { + g_pScriptVM->ReleaseScript( m_hCallback ); + } + else if ( m_hCallback ) + { + AssertMsg( 0, "LEAK (0x%p)\n", (void*)m_hCallback ); + } + + if ( m_pszContext ) + { + if ( !FindContext( m_pszContext, this ) ) + { + delete[] m_pszContext; + } + + m_pszContext = NULL; + } + + m_hCallback = NULL; + + if ( gameeventmanager ) + gameeventmanager->RemoveListener( this ); + + m_bActive = false; +} + +//----------------------------------------------------------------------------- +// Stop the specified event listener. +//----------------------------------------------------------------------------- +bool CScriptGameEventListener::StopListeningToGameEvent( intptr_t listener ) +{ + CScriptGameEventListener *p = reinterpret_cast(listener); // INT_TO_POINTER + + bool bRemoved = s_GameEventListeners.FindAndFastRemove(p); + if ( bRemoved ) + { + delete p; + } + + return bRemoved; +} + +//----------------------------------------------------------------------------- +// Stops listening to all events within a context. +//----------------------------------------------------------------------------- +void CScriptGameEventListener::StopListeningToAllGameEvents( const char* szContext ) +{ + if ( szContext ) + { + if ( *szContext ) + { + // Iterate from the end so they can be safely removed as they are deleted + for ( int i = s_GameEventListeners.Count(); i--; ) + { + CScriptGameEventListener *pCur = s_GameEventListeners[i]; + if ( pCur->m_pszContext && !V_stricmp( szContext, pCur->m_pszContext ) ) + { + s_GameEventListeners.Remove(i); // keep list order + delete pCur; + } + } + } + else // empty (NULL) context + { + for ( int i = s_GameEventListeners.Count(); i--; ) + { + CScriptGameEventListener *pCur = s_GameEventListeners[i]; + if ( !pCur->m_pszContext ) + { + s_GameEventListeners.Remove(i); + delete pCur; + } + } + } + } +#if 0 + if ( !szContext ) + { + for ( int i = s_GameEventListeners.Count(); i--; ) + delete s_GameEventListeners[i]; + s_GameEventListeners.Purge(); + } +#endif +} + +//============================================================================= +//============================================================================= + +static int ListenToGameEvent( const char* szEvent, HSCRIPT hFunc, const char* szContext ) +{ + CScriptGameEventListener *p = new CScriptGameEventListener(); + return p->ListenToGameEvent( szEvent, hFunc, szContext ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +static void FireGameEvent( const char* szEvent, HSCRIPT hTable ) +{ + IGameEvent *event = gameeventmanager->CreateEvent( szEvent ); + if ( event ) + { + ScriptVariant_t key, val; + int nIterator = -1; + while ( ( nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &key, &val ) ) != -1 ) + { + switch ( val.m_type ) + { + case FIELD_FLOAT: event->SetFloat ( key.m_pszString, val.m_float ); break; + case FIELD_INTEGER: event->SetInt ( key.m_pszString, val.m_int ); break; + case FIELD_BOOLEAN: event->SetBool ( key.m_pszString, val.m_bool ); break; + case FIELD_CSTRING: event->SetString( key.m_pszString, val.m_pszString ); break; + } + + g_pScriptVM->ReleaseValue(key); + g_pScriptVM->ReleaseValue(val); + } + +#ifdef CLIENT_DLL + gameeventmanager->FireEventClientSide(event); +#else + gameeventmanager->FireEvent(event); +#endif + } +} + +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Copy of FireGameEvent, server only with no broadcast to clients. +//----------------------------------------------------------------------------- +static void FireGameEventLocal( const char* szEvent, HSCRIPT hTable ) +{ + IGameEvent *event = gameeventmanager->CreateEvent( szEvent ); + if ( event ) + { + ScriptVariant_t key, val; + int nIterator = -1; + while ( ( nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &key, &val ) ) != -1 ) + { + switch ( val.m_type ) + { + case FIELD_FLOAT: event->SetFloat ( key.m_pszString, val.m_float ); break; + case FIELD_INTEGER: event->SetInt ( key.m_pszString, val.m_int ); break; + case FIELD_BOOLEAN: event->SetBool ( key.m_pszString, val.m_bool ); break; + case FIELD_CSTRING: event->SetString( key.m_pszString, val.m_pszString ); break; + } + + g_pScriptVM->ReleaseValue(key); + g_pScriptVM->ReleaseValue(val); + } + + gameeventmanager->FireEvent(event,true); + } +} +#endif // !CLIENT_DLL + +//============================================================================= +// Save/Restore Utility +// Based on Source 2 API +//============================================================================= +class CScriptSaveRestoreUtil : public CAutoGameSystem +{ +public: + static void SaveTable( const char *szId, HSCRIPT hTable ); + static void RestoreTable( const char *szId, HSCRIPT hTable ); + static void ClearSavedTable( const char *szId ); + +// IGameSystem interface +public: + void OnSave() + { + if ( g_pScriptVM ) + { + HSCRIPT hFunc = g_pScriptVM->LookupFunction( "OnSave" ); + if ( hFunc ) + { + g_pScriptVM->Call( hFunc ); + } + } + } + + void OnRestore() + { + if ( g_pScriptVM ) + { + HSCRIPT hFunc = g_pScriptVM->LookupFunction( "OnRestore" ); + if ( hFunc ) + { + g_pScriptVM->Call( hFunc ); + } + } + } + + void Shutdown() + { + FOR_EACH_VEC( m_aKeyValues, i ) + m_aKeyValues[i]->deleteThis(); + m_aKeyValues.Purge(); + m_aContext.PurgeAndDeleteElements(); + } + +private: + static int GetIndexForContext( const char *szId ); + + // indices must match, always remove keeping order + static CUtlStringList m_aContext; + static CUtlVector m_aKeyValues; + +} g_ScriptSaveRestoreUtil; + +CUtlStringList CScriptSaveRestoreUtil::m_aContext; +CUtlVector CScriptSaveRestoreUtil::m_aKeyValues; + +int CScriptSaveRestoreUtil::GetIndexForContext( const char *szId ) +{ + int idx = -1; + FOR_EACH_VEC( m_aContext, i ) + { + if ( !V_stricmp( szId, m_aContext[i] ) ) + { + idx = i; + break; + } + } + return idx; +} + +//----------------------------------------------------------------------------- +// Store a table with primitive values that will persist across level transitions and save loads. +//----------------------------------------------------------------------------- +void CScriptSaveRestoreUtil::SaveTable( const char *szId, HSCRIPT hTable ) +{ + int idx = GetIndexForContext(szId); + + KeyValues *pKV; + + if ( idx == -1 ) + { + pKV = new KeyValues("ScriptSavedTable"); + m_aKeyValues.AddToTail(pKV); + + if ( V_strlen(szId) > 255 ) // arbitrary clamp + { + char c[256]; + V_strncpy( c, szId, sizeof(c) ); + m_aContext.CopyAndAddToTail(c); + } + else + { + m_aContext.CopyAndAddToTail(szId); + } + } + else + { + pKV = m_aKeyValues[idx]; + pKV->Clear(); + } + + ScriptVariant_t key, val; + int nIterator = -1; + while ( ( nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &key, &val ) ) != -1 ) + { + switch ( val.m_type ) + { + case FIELD_FLOAT: pKV->SetFloat ( key.m_pszString, val.m_float ); break; + case FIELD_INTEGER: pKV->SetInt ( key.m_pszString, val.m_int ); break; + case FIELD_BOOLEAN: pKV->SetBool ( key.m_pszString, val.m_bool ); break; + case FIELD_CSTRING: pKV->SetString( key.m_pszString, val.m_pszString ); break; + } + + g_pScriptVM->ReleaseValue(key); + g_pScriptVM->ReleaseValue(val); + } +} + +//----------------------------------------------------------------------------- +// Retrieves a table from storage. Write into input table. +//----------------------------------------------------------------------------- +void CScriptSaveRestoreUtil::RestoreTable( const char *szId, HSCRIPT hTable ) +{ + int idx = GetIndexForContext(szId); + + KeyValues *pKV; + + if ( idx == -1 ) + { + // DevWarning( 2, "RestoreTable could not find saved table with context '%s'\n", szId ); + return; + } + else + { + pKV = m_aKeyValues[idx]; + } + + FOR_EACH_SUBKEY( pKV, key ) + { + switch ( key->GetDataType() ) + { + case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetString() ); break; + case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetInt() ); break; + case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetFloat() ); break; + } + } +} + +//----------------------------------------------------------------------------- +// Remove a saved table. +//----------------------------------------------------------------------------- +void CScriptSaveRestoreUtil::ClearSavedTable( const char *szId ) +{ + int idx = GetIndexForContext(szId); + + if ( idx == -1 ) + { + // DevWarning( 2, "ClearSavedTable could not find saved table with context '%s'\n", szId ); + return; + } + + m_aKeyValues[idx]->deleteThis(); + m_aKeyValues.Remove(idx); + + delete[] m_aContext[idx]; + m_aContext.Remove(idx); +} + +//============================================================================= +// Read/Write to File +// Based on L4D2/Source 2 API +//============================================================================= +#define SCRIPT_MAX_FILE_READ_SIZE (16 * 1024) // 16KB +#define SCRIPT_MAX_FILE_WRITE_SIZE (64 * 1024 * 1024) // 64MB +#define SCRIPT_RW_PATH_ID "MOD" +#define SCRIPT_RW_FULL_PATH_FMT "vscript_io/%s" + +class CScriptReadWriteFile : public CAutoGameSystem +{ +public: + static bool ScriptFileWrite( const char *szFile, const char *szInput ); + static const char *ScriptFileRead( const char *szFile ); + //static const char *CRC32_Checksum( const char *szFilename ); + + // NOTE: These two functions are new with Mapbase and have no Valve equivalent + static bool ScriptKeyValuesWrite( const char *szFile, HSCRIPT hInput ); + static HSCRIPT ScriptKeyValuesRead( const char *szFile ); + + void LevelShutdownPostEntity() + { + if ( m_pszReturnReadFile ) + { + delete[] m_pszReturnReadFile; + m_pszReturnReadFile = NULL; + } + + //if ( m_pszReturnCRC32 ) + //{ + // delete[] m_pszReturnCRC32; + // m_pszReturnCRC32 = NULL; + //} + } + +private: + static const char *m_pszReturnReadFile; + //static const char *m_pszReturnCRC32; + +} g_ScriptReadWrite; + +const char *CScriptReadWriteFile::m_pszReturnReadFile = NULL; +//const char *CScriptReadWriteFile::m_pszReturnCRC32 = NULL; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CScriptReadWriteFile::ScriptFileWrite( const char *szFile, const char *szInput ) +{ + size_t len = strlen(szInput); + if ( len > SCRIPT_MAX_FILE_WRITE_SIZE ) + { + DevWarning( 2, "Input is too large for a ScriptFileWrite ( %s / %d MB )\n", V_pretifymem(len,2,true), (SCRIPT_MAX_FILE_WRITE_SIZE >> 20) ); + return false; + } + + char pszFullName[MAX_PATH]; + V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile ); + + if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) + { + DevWarning( 2, "Invalid file location : %s\n", szFile ); + return false; + } + + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + buf.PutString(szInput); + + int nSize = V_strlen(pszFullName) + 1; + char *pszDir = (char*)stackalloc(nSize); + V_memcpy( pszDir, pszFullName, nSize ); + V_StripFilename( pszDir ); + + g_pFullFileSystem->CreateDirHierarchy( pszDir, SCRIPT_RW_PATH_ID ); + bool res = g_pFullFileSystem->WriteFile( pszFullName, SCRIPT_RW_PATH_ID, buf ); + buf.Purge(); + return res; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +const char *CScriptReadWriteFile::ScriptFileRead( const char *szFile ) +{ + char pszFullName[MAX_PATH]; + V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile ); + + if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) + { + DevWarning( 2, "Invalid file location : %s\n", szFile ); + return NULL; + } + + unsigned int size = g_pFullFileSystem->Size( pszFullName, SCRIPT_RW_PATH_ID ); + if ( size >= SCRIPT_MAX_FILE_READ_SIZE ) + { + DevWarning( 2, "File '%s' (from '%s') is too large for a ScriptFileRead ( %s / %u bytes )\n", pszFullName, szFile, V_pretifymem(size,2,true), SCRIPT_MAX_FILE_READ_SIZE ); + return NULL; + } + + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + if ( !g_pFullFileSystem->ReadFile( pszFullName, SCRIPT_RW_PATH_ID, buf, SCRIPT_MAX_FILE_READ_SIZE ) ) + { + return NULL; + } + + // first time calling, allocate + if ( !m_pszReturnReadFile ) + m_pszReturnReadFile = new char[SCRIPT_MAX_FILE_READ_SIZE]; + + V_strncpy( const_cast(m_pszReturnReadFile), (const char*)buf.Base(), buf.Size() ); + buf.Purge(); + return m_pszReturnReadFile; +} + +//----------------------------------------------------------------------------- +// Get the checksum of any file. Can be used to check the existence or validity of a file. +// Returns unsigned int as hex string. +//----------------------------------------------------------------------------- +/* +const char *CScriptReadWriteFile::CRC32_Checksum( const char *szFilename ) +{ + CUtlBuffer buf( 0, 0, CUtlBuffer::READ_ONLY ); + if ( !g_pFullFileSystem->ReadFile( szFilename, NULL, buf ) ) + return NULL; + + // first time calling, allocate + if ( !m_pszReturnCRC32 ) + m_pszReturnCRC32 = new char[9]; // 'FFFFFFFF\0' + + V_snprintf( const_cast(m_pszReturnCRC32), 9, "%X", CRC32_ProcessSingleBuffer( buf.Base(), buf.Size()-1 ) ); + buf.Purge(); + + return m_pszReturnCRC32; +} +*/ + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CScriptReadWriteFile::ScriptKeyValuesWrite( const char *szFile, HSCRIPT hInput ) +{ + KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hInput ); + if (!pKV) + { + return false; + } + + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + pKV->RecursiveSaveToFile( buf, 0 ); + + if ( buf.Size() > SCRIPT_MAX_FILE_WRITE_SIZE ) + { + DevWarning( 2, "Input is too large for a ScriptFileWrite ( %s / %d MB )\n", V_pretifymem(buf.Size(),2,true), (SCRIPT_MAX_FILE_WRITE_SIZE >> 20) ); + buf.Purge(); + return false; + } + + char pszFullName[MAX_PATH]; + V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile ); + + if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) + { + DevWarning( 2, "Invalid file location : %s\n", szFile ); + buf.Purge(); + return false; + } + + int nSize = V_strlen(pszFullName) + 1; + char *pszDir = (char*)stackalloc(nSize); + V_memcpy( pszDir, pszFullName, nSize ); + V_StripFilename( pszDir ); + + g_pFullFileSystem->CreateDirHierarchy( pszDir, SCRIPT_RW_PATH_ID ); + bool res = g_pFullFileSystem->WriteFile( pszFullName, SCRIPT_RW_PATH_ID, buf ); + buf.Purge(); + return res; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +HSCRIPT CScriptReadWriteFile::ScriptKeyValuesRead( const char *szFile ) +{ + char pszFullName[MAX_PATH]; + V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile ); + + if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) + { + DevWarning( 2, "Invalid file location : %s\n", szFile ); + return NULL; + } + + unsigned int size = g_pFullFileSystem->Size( pszFullName, SCRIPT_RW_PATH_ID ); + if ( size >= SCRIPT_MAX_FILE_READ_SIZE ) + { + DevWarning( 2, "File '%s' (from '%s') is too large for a ScriptFileRead ( %s / %u bytes )\n", pszFullName, szFile, V_pretifymem(size,2,true), SCRIPT_MAX_FILE_READ_SIZE ); + return NULL; + } + + KeyValues *pKV = new KeyValues( szFile ); + if ( !pKV->LoadFromFile( g_pFullFileSystem, pszFullName, SCRIPT_RW_PATH_ID ) ) + { + return NULL; + } + + HSCRIPT hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV, true ); // bAllowDestruct is supposed to automatically remove the involved KV + + return hScript; +} +#undef SCRIPT_MAX_FILE_READ_SIZE +#undef SCRIPT_MAX_FILE_WRITE_SIZE +#undef SCRIPT_RW_PATH_ID +#undef SCRIPT_RW_FULL_PATH_FMT + +//============================================================================= +// User Message Helper +// Based on Source 2 API +//============================================================================= +#ifndef CLIENT_DLL +class CNetMsgScriptHelper +{ +private: + CRecipientFilter filter; + bf_write message; + byte data_msg[ MAX_USER_MSG_DATA ]; + + inline void SendMsg( bf_write *bf ) + { + bf_read buffer = bf_read(); + buffer.StartReading( message.GetData(), message.m_nDataBytes ); + bf->WriteBitsFromBuffer( &buffer, message.GetNumBitsWritten() ); + engine->MessageEnd(); + } + +public: + inline void Reset() + { + message.StartWriting( data_msg, sizeof(data_msg) ); + filter.Reset(); + } + + void SendUserMessage( HSCRIPT player, const char *msg, bool bReliable ) + { + int msg_type = usermessages->LookupUserMessage(msg); + if ( msg_type == -1 ) + { + g_pScriptVM->RaiseException("UserMessageBegin: Unregistered message"); + return; + } + + CBaseEntity *pPlayer = ToEnt(player); + if ( pPlayer ) + { + filter.AddRecipient( (CBasePlayer*)pPlayer ); + } + + if ( bReliable ) + { + filter.MakeReliable(); + } + + SendMsg( engine->UserMessageBegin( &filter, msg_type ) ); + } + + void SendEntityMessage( HSCRIPT hEnt, bool bReliable ) + { + CBaseEntity *entity = ToEnt(hEnt); + if ( !entity ) + { + g_pScriptVM->RaiseException("EntityMessageBegin: invalid entity"); + return; + } + + SendMsg( engine->EntityMessageBegin( entity->entindex(), entity->GetServerClass(), bReliable ) ); + } + +public: + void AddRecipient( HSCRIPT player ) + { + CBaseEntity *pPlayer = ToEnt(player); + if ( pPlayer ) + { + filter.AddRecipient( (CBasePlayer*)pPlayer ); + } + } + + void AddRecipientsByPVS( const Vector &pos ) + { + filter.AddRecipientsByPVS(pos); + } + + void AddAllPlayers() + { + filter.AddAllPlayers(); + } + +public: + void WriteByte( int iValue ) { message.WriteByte( iValue ); } + void WriteChar( int iValue ) { message.WriteChar( iValue ); } + void WriteShort( int iValue ) { message.WriteShort( iValue ); } + void WriteWord( int iValue ) { message.WriteWord( iValue ); } + void WriteLong( int iValue ) { message.WriteLong( iValue ); } + void WriteFloat( float flValue ) { message.WriteFloat( flValue ); } + void WriteAngle( float flValue ) { message.WriteBitAngle( flValue, 8 ); } + void WriteCoord( float flValue ) { message.WriteBitCoord( flValue ); } + void WriteVec3Coord( const Vector& rgflValue ) { message.WriteBitVec3Coord( rgflValue ); } + void WriteVec3Normal( const Vector& rgflValue ) { message.WriteBitVec3Normal( rgflValue ); } + void WriteAngles( const QAngle& rgflValue ) { message.WriteBitAngles( rgflValue ); } + void WriteString( const char *sz ) { message.WriteString( sz ); } + void WriteEntity( int iValue ) { message.WriteShort( iValue ); } + void WriteBool( bool bValue ) { message.WriteOneBit( bValue ? 1 : 0 ); } + void WriteEHandle( HSCRIPT hEnt ) + { + CBaseEntity *pEnt = ToEnt( hEnt ); + long iEncodedEHandle; + if ( pEnt ) + { + EHANDLE hEnt = pEnt; + int iSerialNum = hEnt.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; + iEncodedEHandle = hEnt.GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); + } + else + { + iEncodedEHandle = INVALID_NETWORKED_EHANDLE_VALUE; + } + message.WriteLong( iEncodedEHandle ); + } + +} g_ScriptNetMsg; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "NetworkMessages" ) + DEFINE_SCRIPTFUNC( Reset, "" ) + DEFINE_SCRIPTFUNC( SendUserMessage, "" ) + DEFINE_SCRIPTFUNC( SendEntityMessage, "" ) + DEFINE_SCRIPTFUNC( AddRecipient, "" ) + DEFINE_SCRIPTFUNC( AddRecipientsByPVS, "" ) + DEFINE_SCRIPTFUNC( AddAllPlayers, "" ) + DEFINE_SCRIPTFUNC( WriteByte, "" ) + DEFINE_SCRIPTFUNC( WriteChar, "" ) + DEFINE_SCRIPTFUNC( WriteShort, "" ) + DEFINE_SCRIPTFUNC( WriteWord, "" ) + DEFINE_SCRIPTFUNC( WriteLong, "" ) + DEFINE_SCRIPTFUNC( WriteFloat, "" ) + DEFINE_SCRIPTFUNC( WriteAngle, "" ) + DEFINE_SCRIPTFUNC( WriteCoord, "" ) + DEFINE_SCRIPTFUNC( WriteVec3Coord, "" ) + DEFINE_SCRIPTFUNC( WriteVec3Normal, "" ) + DEFINE_SCRIPTFUNC( WriteAngles, "" ) + DEFINE_SCRIPTFUNC( WriteString, "" ) + DEFINE_SCRIPTFUNC( WriteEntity, "" ) + DEFINE_SCRIPTFUNC( WriteEHandle, "" ) + DEFINE_SCRIPTFUNC( WriteBool, "" ) +END_SCRIPTDESC(); + +#endif // !CLIENT_DLL + +void RegisterScriptSingletons() +{ + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptSaveRestoreUtil::SaveTable, "SaveTable", "Store a table with primitive values that will persist across level transitions and save loads." ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptSaveRestoreUtil::RestoreTable, "RestoreTable", "Retrieves a table from storage. Write into input table." ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptSaveRestoreUtil::ClearSavedTable, "ClearSavedTable", "Removes the table with the given context." ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptReadWriteFile::ScriptFileWrite, "StringToFile", "Stores the string into the file" ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptReadWriteFile::ScriptFileRead, "FileToString", "Returns the string from the file, null if no file or file is too big." ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptReadWriteFile::ScriptKeyValuesWrite, "KeyValuesToFile", "Stores the CScriptKeyValues into the file" ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptReadWriteFile::ScriptKeyValuesRead, "KeyValuesToString", "Returns the CScriptKeyValues from the file, null if no file or file is too big." ); + + ScriptRegisterFunction( g_pScriptVM, ListenToGameEvent, "Register as a listener for a game event from script." ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptGameEventListener::StopListeningToGameEvent, "StopListeningToGameEvent", "Stop the specified event listener." ); + ScriptRegisterFunctionNamed( g_pScriptVM, CScriptGameEventListener::StopListeningToAllGameEvents, "StopListeningToAllGameEvents", "Stop listening to all game events within a specific context." ); + ScriptRegisterFunction( g_pScriptVM, FireGameEvent, "Fire a game event." ); +#ifndef CLIENT_DLL + ScriptRegisterFunction( g_pScriptVM, FireGameEventLocal, "Fire a game event without broadcasting to the client." ); +#endif + + g_pScriptVM->RegisterInstance( &g_ScriptNetPropManager, "NetProps" ); + g_pScriptVM->RegisterInstance( &g_ScriptLocalize, "Localize" ); +#ifndef CLIENT_DLL + g_pScriptVM->RegisterInstance( &g_ScriptNetMsg, "NetMsg" ); +#endif + + // Singletons not unique to VScript (not declared or defined here) + g_pScriptVM->RegisterInstance( GetAmmoDef(), "AmmoDef" ); +#ifndef CLIENT_DLL + g_pScriptVM->RegisterInstance( &g_AI_SquadManager, "Squads" ); +#endif + +#ifndef CLIENT_DLL + CScriptGameEventListener::LoadAllEvents(); +#endif // !CLIENT_DLL +} diff --git a/sp/src/game/shared/mapbase/vscript_singletons.h b/sp/src/game/shared/mapbase/vscript_singletons.h new file mode 100644 index 00000000..b190fe45 --- /dev/null +++ b/sp/src/game/shared/mapbase/vscript_singletons.h @@ -0,0 +1,16 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: See vscript_singletons.cpp +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VSCRIPT_FUNCS_MATH +#define VSCRIPT_FUNCS_MATH +#ifdef _WIN32 +#pragma once +#endif + +void RegisterScriptSingletons(); + +#endif diff --git a/sp/src/game/shared/mapbase/weapon_custom_scripted.cpp b/sp/src/game/shared/mapbase/weapon_custom_scripted.cpp new file mode 100644 index 00000000..7bd4862c --- /dev/null +++ b/sp/src/game/shared/mapbase/weapon_custom_scripted.cpp @@ -0,0 +1,600 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: VScript-driven custom weapon class. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "tier1/fmtstr.h" +#include "weapon_custom_scripted.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//========================================================= +//========================================================= + +BEGIN_DATADESC( CWeaponCustomScripted ) + + DEFINE_AUTO_ARRAY( m_iszClientScripts, FIELD_CHARACTER ), + DEFINE_AUTO_ARRAY( m_iszWeaponScriptName, FIELD_CHARACTER ), + +END_DATADESC() + +IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCustomScripted, DT_WeaponCustomScripted ) + +BEGIN_NETWORK_TABLE( CWeaponCustomScripted, DT_WeaponCustomScripted ) + +#ifdef CLIENT_DLL + RecvPropString( RECVINFO(m_iszClientScripts) ), + RecvPropString( RECVINFO(m_iszWeaponScriptName) ), +#else + SendPropString( SENDINFO(m_iszClientScripts) ), + SendPropString( SENDINFO(m_iszWeaponScriptName) ), +#endif + +END_NETWORK_TABLE() + +BEGIN_PREDICTION_DATA( CWeaponCustomScripted ) +END_PREDICTION_DATA() + +LINK_ENTITY_TO_CLASS( weapon_custom_scripted1, CWeaponCustomScripted ); + +// Only need one of the names +PRECACHE_WEAPON_REGISTER( weapon_custom_scripted1 ); + +//IMPLEMENT_ACTTABLE( CWeaponCustomScripted ); + +#define DEFINE_STATIC_HOOK( name ) ScriptHook_t CWeaponCustomScripted::g_Hook_##name + +DEFINE_STATIC_HOOK( HasAnyAmmo ); +DEFINE_STATIC_HOOK( HasPrimaryAmmo ); +DEFINE_STATIC_HOOK( HasSecondaryAmmo ); + +DEFINE_STATIC_HOOK( CanHolster ); +DEFINE_STATIC_HOOK( CanDeploy ); +DEFINE_STATIC_HOOK( Deploy ); +DEFINE_STATIC_HOOK( Holster ); + +DEFINE_STATIC_HOOK( ItemPreFrame ); +DEFINE_STATIC_HOOK( ItemPostFrame ); +DEFINE_STATIC_HOOK( ItemBusyFrame ); +DEFINE_STATIC_HOOK( ItemHolsterFrame ); +DEFINE_STATIC_HOOK( WeaponIdle ); +DEFINE_STATIC_HOOK( HandleFireOnEmpty ); + +DEFINE_STATIC_HOOK( CheckReload ); +DEFINE_STATIC_HOOK( FinishReload ); +DEFINE_STATIC_HOOK( AbortReload ); +DEFINE_STATIC_HOOK( Reload ); +DEFINE_STATIC_HOOK( Reload_NPC ); + +DEFINE_STATIC_HOOK( PrimaryAttack ); +DEFINE_STATIC_HOOK( SecondaryAttack ); + +DEFINE_STATIC_HOOK( GetPrimaryAttackActivity ); +DEFINE_STATIC_HOOK( GetSecondaryAttackActivity ); +DEFINE_STATIC_HOOK( GetDrawActivity ); +DEFINE_STATIC_HOOK( GetDefaultAnimSpeed ); + +DEFINE_STATIC_HOOK( GetBulletSpread ); +DEFINE_STATIC_HOOK( GetBulletSpreadForProficiency ); +DEFINE_STATIC_HOOK( GetFireRate ); +DEFINE_STATIC_HOOK( GetMinBurst ); +DEFINE_STATIC_HOOK( GetMaxBurst ); +DEFINE_STATIC_HOOK( GetMinRestTime ); +DEFINE_STATIC_HOOK( GetMaxRestTime ); + +DEFINE_STATIC_HOOK( AddViewKick ); + +#ifndef CLIENT_DLL +DEFINE_STATIC_HOOK( WeaponLOSCondition ); +DEFINE_STATIC_HOOK( WeaponRangeAttack1Condition ); +DEFINE_STATIC_HOOK( WeaponRangeAttack2Condition ); +DEFINE_STATIC_HOOK( WeaponMeleeAttack1Condition ); +DEFINE_STATIC_HOOK( WeaponMeleeAttack2Condition ); +#endif + +DEFINE_STATIC_HOOK( ActivityList ); +DEFINE_STATIC_HOOK( ActivityListCount ); + +#define DEFINE_SIMPLE_WEAPON_HOOK( name, returnType, description ) DEFINE_SIMPLE_SCRIPTHOOK( CWeaponCustomScripted::g_Hook_##name, #name, returnType, description ) +#define BEGIN_WEAPON_HOOK( name, returnType, description ) BEGIN_SCRIPTHOOK( CWeaponCustomScripted::g_Hook_##name, #name, returnType, description ) + +BEGIN_ENT_SCRIPTDESC( CWeaponCustomScripted, CBaseCombatWeapon, "Special weapon class with tons of hooks" ) + + DEFINE_SIMPLE_WEAPON_HOOK( HasAnyAmmo, FIELD_BOOLEAN, "Should return true if weapon has ammo" ) + DEFINE_SIMPLE_WEAPON_HOOK( HasPrimaryAmmo, FIELD_BOOLEAN, "Should return true if weapon has primary ammo" ) + DEFINE_SIMPLE_WEAPON_HOOK( HasSecondaryAmmo, FIELD_BOOLEAN, "Should return true if weapon has secondary ammo" ) + + DEFINE_SIMPLE_WEAPON_HOOK( CanHolster, FIELD_BOOLEAN, "Should return true if weapon can be holstered" ) + DEFINE_SIMPLE_WEAPON_HOOK( CanDeploy, FIELD_BOOLEAN, "Should return true if weapon can be deployed" ) + DEFINE_SIMPLE_WEAPON_HOOK( Deploy, FIELD_BOOLEAN, "Called when weapon is being deployed" ) + BEGIN_WEAPON_HOOK( Holster, FIELD_BOOLEAN, "Called when weapon is being holstered" ) + DEFINE_SCRIPTHOOK_PARAM( "switchingto", FIELD_HSCRIPT ) + END_SCRIPTHOOK() + + DEFINE_SIMPLE_WEAPON_HOOK( ItemPreFrame, FIELD_VOID, "Called each frame by the player PreThink" ) + DEFINE_SIMPLE_WEAPON_HOOK( ItemPostFrame, FIELD_VOID, "Called each frame by the player PostThink" ) + DEFINE_SIMPLE_WEAPON_HOOK( ItemBusyFrame, FIELD_VOID, "Called each frame by the player PostThink, if the player's not ready to attack yet" ) + DEFINE_SIMPLE_WEAPON_HOOK( ItemHolsterFrame, FIELD_VOID, "Called each frame by the player PreThink, if the weapon is holstered" ) + DEFINE_SIMPLE_WEAPON_HOOK( WeaponIdle, FIELD_VOID, "Called when no buttons pressed" ) + DEFINE_SIMPLE_WEAPON_HOOK( HandleFireOnEmpty, FIELD_VOID, "Called when they have the attack button down but they are out of ammo. The default implementation either reloads, switches weapons, or plays an empty sound." ) + + DEFINE_SIMPLE_WEAPON_HOOK( CheckReload, FIELD_VOID, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( FinishReload, FIELD_VOID, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( AbortReload, FIELD_VOID, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( Reload, FIELD_BOOLEAN, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( Reload_NPC, FIELD_VOID, "" ) + + DEFINE_SIMPLE_WEAPON_HOOK( PrimaryAttack, FIELD_VOID, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( SecondaryAttack, FIELD_VOID, "" ) + + DEFINE_SIMPLE_WEAPON_HOOK( GetPrimaryAttackActivity, FIELD_VARIANT, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetSecondaryAttackActivity, FIELD_VARIANT, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetDrawActivity, FIELD_VARIANT, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetDefaultAnimSpeed, FIELD_FLOAT, "" ) + + DEFINE_SIMPLE_WEAPON_HOOK( GetBulletSpread, FIELD_VECTOR, "" ) + BEGIN_WEAPON_HOOK( GetBulletSpreadForProficiency, FIELD_VECTOR, "Returns the bullet spread of a specific proficiency level. If this isn't defined, it will fall back to GetBulletSpread." ) + DEFINE_SCRIPTHOOK_PARAM( "proficiency", FIELD_INTEGER ) + END_SCRIPTHOOK() + DEFINE_SIMPLE_WEAPON_HOOK( GetFireRate, FIELD_FLOAT, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetMinBurst, FIELD_INTEGER, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetMaxBurst, FIELD_INTEGER, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetMinRestTime, FIELD_FLOAT, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( GetMaxRestTime, FIELD_FLOAT, "" ) + + DEFINE_SIMPLE_WEAPON_HOOK( AddViewKick, FIELD_VOID, "" ) + +#ifndef CLIENT_DLL + DEFINE_SIMPLE_WEAPON_HOOK( WeaponLOSCondition, FIELD_BOOLEAN, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( WeaponRangeAttack1Condition, FIELD_INTEGER, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( WeaponRangeAttack2Condition, FIELD_INTEGER, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( WeaponMeleeAttack1Condition, FIELD_INTEGER, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( WeaponMeleeAttack2Condition, FIELD_INTEGER, "" ) +#endif + + DEFINE_SIMPLE_WEAPON_HOOK( ActivityList, FIELD_HSCRIPT, "" ) + DEFINE_SIMPLE_WEAPON_HOOK( ActivityListCount, FIELD_INTEGER, "" ) + +END_SCRIPTDESC(); + +CWeaponCustomScripted::CWeaponCustomScripted() +{ + //m_fMinRange1 = 65; + //m_fMaxRange1 = 2048; + // + //m_fMinRange2 = 256; + //m_fMaxRange2 = 1024; + // + //m_nShotsFired = 0; + //m_nVentPose = -1; + // + //m_bAltFiresUnderwater = false; +} + +bool CWeaponCustomScripted::RunWeaponHook( ScriptHook_t &hook, HSCRIPT &cached, ScriptVariant_t *retVal, ScriptVariant_t *pArgs ) +{ + if (!hook.CheckFuncValid(cached)) + cached = hook.CanRunInScope(m_ScriptScope); + + if (cached) + { + return hook.Call( m_ScriptScope, retVal, pArgs, false ); + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponCustomScripted::Spawn( void ) +{ +#ifdef CLIENT_DLL + if (m_iszClientScripts[0] != '\0' && ValidateScriptScope()) + { + RunScriptFile( m_iszClientScripts ); + } +#endif + + BaseClass::Spawn(); +} + +bool CWeaponCustomScripted::KeyValue( const char *szKeyName, const char *szValue ) +{ + if ( FStrEq( szKeyName, "vscripts_client" ) ) + { + Q_strcpy( m_iszClientScripts.GetForModify(), szValue ); + } + else if ( FStrEq( szKeyName, "weapondatascript_name" ) ) + { + Q_strcpy( m_iszWeaponScriptName.GetForModify(), szValue ); + } + else + { + return BaseClass::KeyValue( szKeyName, szValue ); + } + + return true; +} + +bool CWeaponCustomScripted::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen ) +{ + if ( FStrEq( szKeyName, "vscripts_client" ) ) + { + Q_snprintf( szValue, iMaxLen, "%s", m_iszClientScripts.Get() ); + return true; + } + else if ( FStrEq( szKeyName, "weapondatascript_name" ) ) + { + Q_snprintf( szValue, iMaxLen, "%s", m_iszWeaponScriptName.Get() ); + return true; + } + return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +#define SIMPLE_VOID_OVERRIDE( name, pArgs ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal, pArgs ) && retVal.m_bool == false) \ + return; + +#define SIMPLE_BOOL_OVERRIDE( name, pArgs ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal, pArgs ) && retVal.m_type == FIELD_BOOLEAN) \ + return retVal.m_bool; + +#define SIMPLE_FLOAT_OVERRIDE( name, pArgs ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal, pArgs ) && retVal.m_type == FIELD_FLOAT) \ + return retVal.m_float; + +#define SIMPLE_INT_OVERRIDE( name, pArgs ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal, pArgs ) && retVal.m_type == FIELD_INTEGER) \ + return retVal.m_int; + +#define SIMPLE_VECTOR_OVERRIDE( name, pArgs ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal, pArgs ) && retVal.m_type == FIELD_VECTOR) \ + return *retVal.m_pVector; + +#define SIMPLE_VECTOR_REF_OVERRIDE( name, pArgs ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal, pArgs ) && retVal.m_type == FIELD_VECTOR) \ + { \ + static Vector vec = *retVal.m_pVector; \ + return vec; \ + } + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CWeaponCustomScripted::HasAnyAmmo( void ) +{ + SIMPLE_BOOL_OVERRIDE( HasAnyAmmo, NULL ); + + return BaseClass::HasAnyAmmo(); +} + +bool CWeaponCustomScripted::HasPrimaryAmmo( void ) +{ + SIMPLE_BOOL_OVERRIDE( HasPrimaryAmmo, NULL ); + + return BaseClass::HasPrimaryAmmo(); +} + +bool CWeaponCustomScripted::HasSecondaryAmmo( void ) +{ + SIMPLE_BOOL_OVERRIDE( HasSecondaryAmmo, NULL ); + + return BaseClass::HasSecondaryAmmo(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CWeaponCustomScripted::CanHolster( void ) +{ + SIMPLE_BOOL_OVERRIDE( CanHolster, NULL ); + + return BaseClass::CanHolster(); +} + +bool CWeaponCustomScripted::CanDeploy( void ) +{ + SIMPLE_BOOL_OVERRIDE( CanDeploy, NULL ); + + return BaseClass::CanDeploy(); +} + +bool CWeaponCustomScripted::Deploy( void ) +{ + SIMPLE_BOOL_OVERRIDE( Deploy, NULL ); + + return BaseClass::Deploy(); +} + +bool CWeaponCustomScripted::Holster( CBaseCombatWeapon *pSwitchingTo ) +{ + ScriptVariant_t pArgs[] = { ToHScript( pSwitchingTo ) }; + SIMPLE_BOOL_OVERRIDE( Holster, pArgs ); + + return BaseClass::Holster( pSwitchingTo ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponCustomScripted::ItemPreFrame( void ) +{ + SIMPLE_VOID_OVERRIDE( ItemPreFrame, NULL ); + + BaseClass::ItemPostFrame(); +} + +void CWeaponCustomScripted::ItemPostFrame( void ) +{ + SIMPLE_VOID_OVERRIDE( ItemPostFrame, NULL ); + + BaseClass::ItemPostFrame(); +} + +void CWeaponCustomScripted::ItemBusyFrame( void ) +{ + SIMPLE_VOID_OVERRIDE( ItemBusyFrame, NULL ); + + BaseClass::ItemBusyFrame(); +} + +void CWeaponCustomScripted::ItemHolsterFrame( void ) +{ + SIMPLE_VOID_OVERRIDE( ItemHolsterFrame, NULL ); + + BaseClass::ItemHolsterFrame(); +} + +void CWeaponCustomScripted::WeaponIdle( void ) +{ + SIMPLE_VOID_OVERRIDE( WeaponIdle, NULL ); + + BaseClass::WeaponIdle(); +} + +void CWeaponCustomScripted::HandleFireOnEmpty( void ) +{ + SIMPLE_VOID_OVERRIDE( HandleFireOnEmpty, NULL ); + + BaseClass::HandleFireOnEmpty(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponCustomScripted::CheckReload( void ) +{ + SIMPLE_VOID_OVERRIDE( CheckReload, NULL ); + + BaseClass::CheckReload(); +} + +void CWeaponCustomScripted::FinishReload( void ) +{ + SIMPLE_VOID_OVERRIDE( FinishReload, NULL ); + + BaseClass::FinishReload(); +} + +void CWeaponCustomScripted::AbortReload( void ) +{ + SIMPLE_VOID_OVERRIDE( AbortReload, NULL ); + + BaseClass::AbortReload(); +} + +bool CWeaponCustomScripted::Reload( void ) +{ + SIMPLE_BOOL_OVERRIDE( Reload, NULL ); + + return BaseClass::Reload(); +} + +void CWeaponCustomScripted::Reload_NPC( void ) +{ + SIMPLE_VOID_OVERRIDE( Reload_NPC, NULL ); + + BaseClass::Reload_NPC(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponCustomScripted::PrimaryAttack( void ) +{ + SIMPLE_VOID_OVERRIDE( PrimaryAttack, NULL ); + + BaseClass::PrimaryAttack(); +} + +void CWeaponCustomScripted::SecondaryAttack( void ) +{ + SIMPLE_VOID_OVERRIDE( SecondaryAttack, NULL ); + + BaseClass::SecondaryAttack(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +#define ACTIVITY_FUNC_OVERRIDE( name ) ScriptVariant_t retVal; \ + if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal ) && retVal.m_bool == false) \ + { \ + if (retVal.m_type == FIELD_INTEGER) \ + { \ + Activity activity = (Activity)retVal.m_int; \ + if (activity != ACT_INVALID) \ + return (Activity)retVal.m_int; \ + } \ + else \ + { \ + Activity activity = (Activity)LookupActivity( retVal.m_pszString ); \ + if (activity != ACT_INVALID) \ + return activity; \ + } \ + } + +Activity CWeaponCustomScripted::GetPrimaryAttackActivity( void ) +{ + ACTIVITY_FUNC_OVERRIDE( GetPrimaryAttackActivity ); + + return BaseClass::GetPrimaryAttackActivity(); +} + +Activity CWeaponCustomScripted::GetSecondaryAttackActivity( void ) +{ + ACTIVITY_FUNC_OVERRIDE( GetSecondaryAttackActivity ); + + return BaseClass::GetSecondaryAttackActivity(); +} + +Activity CWeaponCustomScripted::GetDrawActivity( void ) +{ + ACTIVITY_FUNC_OVERRIDE( GetDrawActivity ); + + return BaseClass::GetDrawActivity(); +} + +float CWeaponCustomScripted::GetDefaultAnimSpeed( void ) +{ + SIMPLE_FLOAT_OVERRIDE( GetDefaultAnimSpeed, NULL ); + + return BaseClass::GetDefaultAnimSpeed(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const Vector& CWeaponCustomScripted::GetBulletSpread( void ) +{ + SIMPLE_VECTOR_REF_OVERRIDE( GetBulletSpread, NULL ); + + // HACKHACK: Need to skip CBaseHLCombatWeapon here to recognize this overload for some reason + return CBaseCombatWeapon::GetBulletSpread(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Vector CWeaponCustomScripted::GetBulletSpread( WeaponProficiency_t proficiency ) +{ + ScriptVariant_t pArgs[] = { (int)proficiency }; + SIMPLE_VECTOR_OVERRIDE( GetBulletSpreadForProficiency, pArgs ); + + return BaseClass::GetBulletSpread( proficiency ); +} + +float CWeaponCustomScripted::GetFireRate( void ) +{ + SIMPLE_FLOAT_OVERRIDE( GetFireRate, NULL ); + + return BaseClass::GetFireRate(); +} + +int CWeaponCustomScripted::GetMinBurst( void ) +{ + SIMPLE_INT_OVERRIDE( GetMinBurst, NULL ); + + return BaseClass::GetMinBurst(); +} + +int CWeaponCustomScripted::GetMaxBurst( void ) +{ + SIMPLE_INT_OVERRIDE( GetMaxBurst, NULL ); + + return BaseClass::GetMaxBurst(); +} + +float CWeaponCustomScripted::GetMinRestTime( void ) +{ + SIMPLE_FLOAT_OVERRIDE( GetMinRestTime, NULL ); + + return BaseClass::GetMinRestTime(); +} + +float CWeaponCustomScripted::GetMaxRestTime( void ) +{ + SIMPLE_FLOAT_OVERRIDE( GetMaxRestTime, NULL ); + + return BaseClass::GetMaxRestTime(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWeaponCustomScripted::AddViewKick( void ) +{ + SIMPLE_VOID_OVERRIDE( AddViewKick, NULL ); + + return BaseClass::AddViewKick(); +} + +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CWeaponCustomScripted::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) +{ + ScriptVariant_t pArgs[] = { ownerPos, targetPos, bSetConditions }; + SIMPLE_BOOL_OVERRIDE( WeaponLOSCondition, pArgs ); + + return BaseClass::WeaponLOSCondition( ownerPos, targetPos, bSetConditions ); +} + +int CWeaponCustomScripted::WeaponRangeAttack1Condition( float flDot, float flDist ) +{ + ScriptVariant_t pArgs[] = { flDot, flDist }; + SIMPLE_INT_OVERRIDE( WeaponRangeAttack1Condition, pArgs ); + + return BaseClass::WeaponRangeAttack1Condition( flDot, flDist ); +} + +int CWeaponCustomScripted::WeaponRangeAttack2Condition( float flDot, float flDist ) +{ + ScriptVariant_t pArgs[] = { flDot, flDist }; + SIMPLE_INT_OVERRIDE( WeaponRangeAttack2Condition, pArgs ); + + return BaseClass::WeaponRangeAttack2Condition( flDot, flDist ); +} + +int CWeaponCustomScripted::WeaponMeleeAttack1Condition( float flDot, float flDist ) +{ + ScriptVariant_t pArgs[] = { flDot, flDist }; + SIMPLE_INT_OVERRIDE( WeaponMeleeAttack1Condition, pArgs ); + + return BaseClass::WeaponMeleeAttack1Condition( flDot, flDist ); +} + +int CWeaponCustomScripted::WeaponMeleeAttack2Condition( float flDot, float flDist ) +{ + ScriptVariant_t pArgs[] = { flDot, flDist }; + SIMPLE_INT_OVERRIDE( WeaponMeleeAttack2Condition, pArgs ); + + return BaseClass::WeaponMeleeAttack2Condition( flDot, flDist ); +} +#endif + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +acttable_t *CWeaponCustomScripted::ActivityList( void ) +{ + // TODO + + return BaseClass::ActivityList(); +} + +int CWeaponCustomScripted::ActivityListCount( void ) +{ + // TODO + + return BaseClass::ActivityListCount(); +} diff --git a/sp/src/game/shared/mapbase/weapon_custom_scripted.h b/sp/src/game/shared/mapbase/weapon_custom_scripted.h new file mode 100644 index 00000000..90630a65 --- /dev/null +++ b/sp/src/game/shared/mapbase/weapon_custom_scripted.h @@ -0,0 +1,202 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: VScript-driven custom weapon class. +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VSCRIPT_FUNCS_MATH +#define VSCRIPT_FUNCS_MATH +#ifdef _WIN32 +#pragma once +#endif + +#include "basecombatweapon_shared.h" +#ifdef CLIENT_DLL +#include "vscript_client.h" +#endif + +// The base class of the scripted weapon is game-specific. +#if defined(HL2_DLL) || defined(HL2_CLIENT_DLL) +#include "basehlcombatweapon_shared.h" +#define SCRIPTED_WEAPON_DERIVED_FROM CBaseHLCombatWeapon +#else +#define SCRIPTED_WEAPON_DERIVED_FROM CBaseCombatWeapon +#endif + +#ifdef CLIENT_DLL +#define CWeaponCustomScripted C_WeaponCustomScripted +#endif + +#define DECLARE_CACHED_HOOK(name) static ScriptHook_t g_Hook_##name; \ + HSCRIPT m_Func_##name; + +class CWeaponCustomScripted : public SCRIPTED_WEAPON_DERIVED_FROM +{ +public: + DECLARE_CLASS( CWeaponCustomScripted, SCRIPTED_WEAPON_DERIVED_FROM ); + DECLARE_NETWORKCLASS(); + DECLARE_PREDICTABLE(); + + CWeaponCustomScripted(); + + bool RunWeaponHook( ScriptHook_t &hook, HSCRIPT &cached, ScriptVariant_t *retVal = NULL, ScriptVariant_t *pArgs = NULL ); + + bool KeyValue( const char *szKeyName, const char *szValue ); + bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen ); + + // Base script has a function for this + //void Precache( void ); + + void Spawn( void ); + + bool IsPredicted( void ) const { return m_iszClientScripts[0] != '\0'; } + + const char* GetWeaponScriptName() { return m_iszWeaponScriptName[0] != '\0' ? m_iszWeaponScriptName : BaseClass::GetWeaponScriptName(); } + + // Weapon selection + bool HasAnyAmmo( void ); // Returns true is weapon has ammo + bool HasPrimaryAmmo( void ); // Returns true is weapon has ammo + bool HasSecondaryAmmo( void ); // Returns true is weapon has ammo + + bool CanHolster( void ); // returns true if the weapon can be holstered + bool CanDeploy( void ); // return true if the weapon's allowed to deploy + bool Deploy( void ); // returns true is deploy was successful + bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); + + // Weapon behaviour + void ItemPreFrame( void ); // called each frame by the player PreThink + void ItemPostFrame( void ); // called each frame by the player PostThink + void ItemBusyFrame( void ); // called each frame by the player PostThink, if the player's not ready to attack yet + void ItemHolsterFrame( void ); // called each frame by the player PreThink, if the weapon is holstered + void WeaponIdle( void ); // called when no buttons pressed + void HandleFireOnEmpty(); // Called when they have the attack button down + + // Reloading + void CheckReload( void ); + void FinishReload( void ); + void AbortReload( void ); + bool Reload( void ); + void Reload_NPC( void ); + + // Weapon firing + void PrimaryAttack( void ); // do "+ATTACK" + void SecondaryAttack( void ); // do "+ATTACK2" + + // Firing animations + Activity GetPrimaryAttackActivity( void ); + Activity GetSecondaryAttackActivity( void ); + Activity GetDrawActivity( void ); + float GetDefaultAnimSpeed( void ); + + // Bullet launch information + const Vector& GetBulletSpread( void ); + Vector GetBulletSpread( WeaponProficiency_t proficiency ); + float GetFireRate( void ); + int GetMinBurst(); + int GetMaxBurst(); + float GetMinRestTime(); + float GetMaxRestTime(); + + void AddViewKick( void ); + +#ifndef CLIENT_DLL + bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); + int WeaponRangeAttack1Condition( float flDot, float flDist ); + int WeaponRangeAttack2Condition( float flDot, float flDist ); + int WeaponMeleeAttack1Condition( float flDot, float flDist ); + int WeaponMeleeAttack2Condition( float flDot, float flDist ); +#endif + + ALLOW_SCRIPT_ACCESS(); +private: + + // Weapon selection + DECLARE_CACHED_HOOK( HasAnyAmmo ); + DECLARE_CACHED_HOOK( HasPrimaryAmmo ); + DECLARE_CACHED_HOOK( HasSecondaryAmmo ); + + DECLARE_CACHED_HOOK( CanHolster ); + DECLARE_CACHED_HOOK( CanDeploy ); + DECLARE_CACHED_HOOK( Deploy ); + DECLARE_CACHED_HOOK( Holster ); + + // Weapon behaviour + DECLARE_CACHED_HOOK( ItemPreFrame ); + DECLARE_CACHED_HOOK( ItemPostFrame ); + DECLARE_CACHED_HOOK( ItemBusyFrame ); + DECLARE_CACHED_HOOK( ItemHolsterFrame ); + DECLARE_CACHED_HOOK( WeaponIdle ); + DECLARE_CACHED_HOOK( HandleFireOnEmpty ); + + // Reloading + DECLARE_CACHED_HOOK( CheckReload ); + DECLARE_CACHED_HOOK( FinishReload ); + DECLARE_CACHED_HOOK( AbortReload ); + DECLARE_CACHED_HOOK( Reload ); + DECLARE_CACHED_HOOK( Reload_NPC ); + + // Weapon firing + DECLARE_CACHED_HOOK( PrimaryAttack ); + DECLARE_CACHED_HOOK( SecondaryAttack ); + + // Firing animations + DECLARE_CACHED_HOOK( GetPrimaryAttackActivity ); + DECLARE_CACHED_HOOK( GetSecondaryAttackActivity ); + DECLARE_CACHED_HOOK( GetDrawActivity ); + DECLARE_CACHED_HOOK( GetDefaultAnimSpeed ); + + // Bullet launch information + DECLARE_CACHED_HOOK( GetBulletSpread ); + DECLARE_CACHED_HOOK( GetBulletSpreadForProficiency ); + DECLARE_CACHED_HOOK( GetFireRate ); + DECLARE_CACHED_HOOK( GetMinBurst ); + DECLARE_CACHED_HOOK( GetMaxBurst ); + DECLARE_CACHED_HOOK( GetMinRestTime ); + DECLARE_CACHED_HOOK( GetMaxRestTime ); + + DECLARE_CACHED_HOOK( AddViewKick ); + +#ifndef CLIENT_DLL + DECLARE_CACHED_HOOK( WeaponLOSCondition ); + DECLARE_CACHED_HOOK( WeaponRangeAttack1Condition ); + DECLARE_CACHED_HOOK( WeaponRangeAttack2Condition ); + DECLARE_CACHED_HOOK( WeaponMeleeAttack1Condition ); + DECLARE_CACHED_HOOK( WeaponMeleeAttack2Condition ); +#endif + + DECLARE_CACHED_HOOK( ActivityList ); + DECLARE_CACHED_HOOK( ActivityListCount ); + +private: + + CNetworkString( m_iszClientScripts, 256 ); + CNetworkString( m_iszWeaponScriptName, 256 ); + +protected: + + DECLARE_ACTTABLE(); + DECLARE_DATADESC(); + DECLARE_ENT_SCRIPTDESC(); +}; + +/* +class CWeaponCustomScripted1 : public CWeaponCustomScripted +{ + DECLARE_PREDICTABLE(); +}; +class CWeaponCustomScripted2 : public CWeaponCustomScripted +{ + DECLARE_PREDICTABLE(); +}; +class CWeaponCustomScripted3 : public CWeaponCustomScripted +{ + DECLARE_PREDICTABLE(); +}; +class CWeaponCustomScripted4 : public CWeaponCustomScripted +{ + DECLARE_PREDICTABLE(); +}; +*/ + +#endif diff --git a/sp/src/game/shared/precipitation_shared.h b/sp/src/game/shared/precipitation_shared.h index b3820aa7..cb5f819c 100644 --- a/sp/src/game/shared/precipitation_shared.h +++ b/sp/src/game/shared/precipitation_shared.h @@ -18,14 +18,29 @@ enum PrecipitationType_t PRECIPITATION_TYPE_SNOW, PRECIPITATION_TYPE_ASH, PRECIPITATION_TYPE_SNOWFALL, -#ifdef MAPBASE PRECIPITATION_TYPE_PARTICLERAIN, PRECIPITATION_TYPE_PARTICLEASH, PRECIPITATION_TYPE_PARTICLERAINSTORM, PRECIPITATION_TYPE_PARTICLESNOW, -#endif NUM_PRECIPITATION_TYPES }; +// Returns true if the precipitation type involves the new particle system code +// +// NOTE: We can get away with >= PARTICLERAIN, but if you're adding any new precipitation types +// which DO NOT use the new particle system, please change this code to prevent it from being recognized +// as a particle type. +inline bool IsParticleRainType( PrecipitationType_t type ) +{ + // m_nPrecipType == PRECIPITATION_TYPE_PARTICLERAIN || m_nPrecipType == PRECIPITATION_TYPE_PARTICLEASH + // || m_nPrecipType == PRECIPITATION_TYPE_PARTICLERAINSTORM || m_nPrecipType == PRECIPITATION_TYPE_PARTICLESNOW + return type >= PRECIPITATION_TYPE_PARTICLERAIN; +} + +#ifdef MAPBASE +#define SF_PRECIP_PARTICLE_CLAMP (1 << 0) // Clamps particle types to the precipitation bounds; Mapbase uses this to compensate for the lack of blocker support. +#define SF_PRECIP_PARTICLE_NO_OUTER (1 << 1) // Suppresses the outer particle system. +#endif + #endif // PRECIPITATION_SHARED_H diff --git a/sp/src/game/shared/sceneentity_shared.cpp b/sp/src/game/shared/sceneentity_shared.cpp index 653586ba..e8cb1905 100644 --- a/sp/src/game/shared/sceneentity_shared.cpp +++ b/sp/src/game/shared/sceneentity_shared.cpp @@ -44,7 +44,11 @@ void Scene_Printf( const char *pFormat, ... ) Q_vsnprintf(msg, sizeof(msg), pFormat, marker); va_end(marker); +#ifdef MAPBASE + CGMsg( 0, CON_GROUP_CHOREO, "%8.3f[%d] %s: %s", gpGlobals->curtime, gpGlobals->tickcount, CBaseEntity::IsServer() ? "sv" : "cl", msg ); +#else Msg( "%8.3f[%d] %s: %s", gpGlobals->curtime, gpGlobals->tickcount, CBaseEntity::IsServer() ? "sv" : "cl", msg ); +#endif } //----------------------------------------------------------------------------- diff --git a/sp/src/game/shared/vscript_shared.cpp b/sp/src/game/shared/vscript_shared.cpp index 987359fd..ebe997a8 100644 --- a/sp/src/game/shared/vscript_shared.cpp +++ b/sp/src/game/shared/vscript_shared.cpp @@ -59,7 +59,7 @@ HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing ) const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' ); if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 ) { - Warning( "Script file type does not match VM type\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type does not match VM type\n" ); return NULL; } @@ -91,7 +91,7 @@ HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing ) if( !bResult ) #endif { - Warning( "Script not found (%s) \n", scriptPath.operator const char *() ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Script not found (%s) \n", scriptPath.operator const char *() ); Assert( "Error running script" ); } @@ -109,7 +109,7 @@ HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing ) HSCRIPT hScript = g_pScriptVM->CompileScript( pBase, pszFilename ); if ( !hScript ) { - Warning( "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() ); + CGWarning( 0, CON_GROUP_VSCRIPT, "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() ); Assert( "Error running script" ); } return hScript; @@ -126,14 +126,14 @@ bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMiss if ( !pszScriptName || !*pszScriptName ) { - Warning( "Cannot run script: NULL script name\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Cannot run script: NULL script name\n" ); return false; } // Prevent infinite recursion in VM if ( g_ScriptServerRunScriptDepth > 16 ) { - Warning( "IncludeScript stack overflow\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "IncludeScript stack overflow\n" ); return false; } @@ -171,13 +171,13 @@ CON_COMMAND( script, "Run the text as a script" ) { if ( !*args[1] ) { - Warning( "No function name specified\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "No function name specified\n" ); return; } if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } @@ -226,13 +226,13 @@ CON_COMMAND_SHARED( script_execute, "Run a vscript file" ) { if ( !*args[1] ) { - Warning( "No script specified\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "No script specified\n" ); return; } if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } @@ -243,7 +243,7 @@ CON_COMMAND_SHARED( script_debug, "Connect the vscript VM to the script debugger { if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } g_pScriptVM->ConnectDebugger(); @@ -253,7 +253,7 @@ CON_COMMAND_SHARED( script_help, "Output help for script functions, optionally w { if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } const char *pszArg1 = "*"; @@ -269,7 +269,7 @@ CON_COMMAND_SHARED( script_dump_all, "Dump the state of the VM to the console" ) { if ( !g_pScriptVM ) { - Warning( "Scripting disabled or no server running\n" ); + CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" ); return; } g_pScriptVM->DumpState(); diff --git a/sp/src/game/shared/weapon_parse.cpp b/sp/src/game/shared/weapon_parse.cpp index 7aa880a1..51dcff10 100644 --- a/sp/src/game/shared/weapon_parse.cpp +++ b/sp/src/game/shared/weapon_parse.cpp @@ -283,7 +283,11 @@ bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeapo FileWeaponInfo_t *pFileInfo = GetFileWeaponInfoFromHandle( *phandle ); Assert( pFileInfo ); +#ifdef MAPBASE + if ( pFileInfo->bParsedScript && !pFileInfo->bCustom ) +#else if ( pFileInfo->bParsedScript ) +#endif return true; char sz[128]; @@ -300,6 +304,9 @@ bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeapo if ( !pKV ) return false; +#ifdef MAPBASE + pFileInfo->bCustom = false; +#endif pFileInfo->Parse( pKV, szWeaponName ); pKV->deleteThis(); @@ -307,6 +314,49 @@ bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeapo return true; } +#ifdef MAPBASE +extern const char *g_MapName; + +bool ReadCustomWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeaponName, WEAPON_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey ) +{ + if ( !phandle ) + { + Assert( 0 ); + return false; + } + + *phandle = FindWeaponInfoSlot( szWeaponName ); + FileWeaponInfo_t *pFileInfo = GetFileWeaponInfoFromHandle( *phandle ); + Assert( pFileInfo ); + + // Just parse the custom script anyway even if it was already loaded. This is because after one is loaded, + // there's no way of distinguishing between maps with no custom scripts and maps with their own new custom scripts. + //if ( pFileInfo->bParsedScript && pFileInfo->bCustom ) + // return true; + + char sz[128]; + Q_snprintf( sz, sizeof( sz ), "maps/%s_%s", g_MapName, szWeaponName ); + + KeyValues *pKV = ReadEncryptedKVFile( filesystem, sz, pICEKey, +#if defined( DOD_DLL ) + true // Only read .ctx files! +#else + false +#endif + ); + + if ( !pKV ) + return false; + + pFileInfo->bCustom = true; + pFileInfo->Parse( pKV, szWeaponName ); + + pKV->deleteThis(); + + return true; +} +#endif + //----------------------------------------------------------------------------- // FileWeaponInfo_t implementation. diff --git a/sp/src/game/shared/weapon_parse.h b/sp/src/game/shared/weapon_parse.h index f1d4c924..56803dfa 100644 --- a/sp/src/game/shared/weapon_parse.h +++ b/sp/src/game/shared/weapon_parse.h @@ -77,6 +77,10 @@ public: public: bool bParsedScript; bool bLoadedHudElements; +#ifdef MAPBASE + // Indicates the currently loaded data is from a map-specific script and should be flushed. + bool bCustom; +#endif // SHARED char szClassName[MAX_WEAPON_STRING]; @@ -136,6 +140,12 @@ public: bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeaponName, WEAPON_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey = NULL ); +#ifdef MAPBASE +// For map-specific weapon data +bool ReadCustomWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeaponName, + WEAPON_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey = NULL ); +#endif + // If weapon info has been loaded for the specified class name, this returns it. WEAPON_FILE_INFO_HANDLE LookupWeaponInfoSlot( const char *name ); diff --git a/sp/src/materialsystem/stdshaders/SDK_lightmappedgeneric_ps20b.fxc b/sp/src/materialsystem/stdshaders/SDK_lightmappedgeneric_ps20b.fxc index 7cb1afb6..d49a33a6 100644 --- a/sp/src/materialsystem/stdshaders/SDK_lightmappedgeneric_ps20b.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_lightmappedgeneric_ps20b.fxc @@ -15,6 +15,7 @@ // STATIC: "FANCY_BLENDING" "0..1" // STATIC: "RELIEF_MAPPING" "0..0" [ps20b] // STATIC: "SEAMLESS" "0..1" +// STATIC: "BUMPMASK" "0..1" // STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] // STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] // STATIC: "NORMALMASK_DECODE_MODE" "0..0" [XBOX] @@ -22,7 +23,6 @@ // STATIC: "DETAIL_BLEND_MODE" "0..11" // STATIC: "FLASHLIGHT" "0..1" [ps20b] [XBOX] // STATIC: "BASETEXTURETRANSFORM2" "0..1" -// STATIC: "SWAP_VERTEX_BLEND" "0..1" // STATIC: "PARALLAXCORRECT" "0..1" // DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1" diff --git a/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc b/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc index 852002c9..5879a084 100644 --- a/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc @@ -16,6 +16,7 @@ // STATIC: "FASTPATH_NOBUMP" "0..1" // STATIC: "BLENDTINTBYBASEALPHA" "0..1" // STATIC: "PHONG_HALFLAMBERT" "0..1" +// STATIC: "ENVMAPMASK" "0..1" // DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" // DYNAMIC: "PIXELFOGTYPE" "0..1" @@ -47,6 +48,8 @@ // BlendTintByBaseAlpha and self illum and are opposing meanings for alpha channel // SKIP: ( $BLENDTINTBYBASEALPHA ) && ( $SELFILLUM ) +// SKIP: $ENVMAPMASK && !$CUBEMAP + // fastpath means: // no bumpmap // basealphaenvmapmask (not inverted) @@ -121,6 +124,10 @@ sampler DetailSampler : register( s13 ); // detail texture sampler SelfIllumMaskSampler : register( s14 ); // selfillummask +#if ENVMAPMASK +sampler EnvmapMaskSampler : register( s15 ); +#endif + struct PS_INPUT { @@ -146,6 +153,7 @@ float4 main( PS_INPUT i ) : COLOR bool bSelfIllum = SELFILLUM ? true : false; bool bDoRimLighting = RIMLIGHT ? true : false; bool bCubemap = CUBEMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; int nNumLights = NUM_LIGHTS; @@ -184,7 +192,13 @@ float4 main( PS_INPUT i ) : COLOR float3 vRimAmbientCubeColor = PixelShaderAmbientLight(vEyeDir, cAmbientCube); float3 worldSpaceNormal, tangentSpaceNormal; + +#if ENVMAPMASK + float3 fSpecMask = float3( 1.0f, 1.0f, 1.0f ); +#else float fSpecMask = 1.0f; +#endif + #if !DETAILTEXTURE // Blixibon - $bumpmap transform support float4 normalTexel = tex2D( NormalMapSampler, i.baseTexCoordDetailTexCoord.zw ); @@ -198,14 +212,27 @@ float4 main( PS_INPUT i ) : COLOR normalTexel = flTextureAmount * normalTexel + flWrinkleAmount * wrinkleNormal + flStretchAmount * stretchNormal; #endif -#if (FASTPATH_NOBUMP == 0 ) +#if (FASTPATH_NOBUMP == 0) tangentSpaceNormal = lerp( 2.0f * normalTexel.xyz - 1.0f, float3(0, 0, 1), g_fBaseMapAlphaPhongMask ); - fSpecMask = lerp( normalTexel.a, baseColor.a, g_fBaseMapAlphaPhongMask ); #else tangentSpaceNormal = float3(0, 0, 1); - fSpecMask = baseColor.a; #endif + #if ENVMAPMASK + { + float4 envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoordDetailTexCoord.xy ); + fSpecMask = lerp( envmapMaskTexel.xyz, baseColor.aaa, g_fBaseMapAlphaPhongMask ); + } + #else + { +#if (FASTPATH_NOBUMP == 0 ) + fSpecMask = lerp( normalTexel.a, baseColor.a, g_fBaseMapAlphaPhongMask ); +#else + fSpecMask = baseColor.a; +#endif + } + #endif + // We need a normal if we're doing any lighting worldSpaceNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); @@ -230,18 +257,30 @@ float4 main( PS_INPUT i ) : COLOR if( bCubemap ) { - // Mask is either normal map alpha or base map alpha + if ( bEnvmapMask ) + { + float3 fEnvMapMask = lerp( baseColor.aaa, fSpecMask, g_EnvmapTint_ShadowTweaks.w ); + envMapColor = (ENV_MAP_SCALE * + lerp(1, fFresnelRanges, g_EnvMapFresnel.x) * + lerp(fEnvMapMask, float3(1,1,1)-fEnvMapMask, g_fInvertPhongMask)) * + texCUBE( EnvmapSampler, vReflect ).xyz * + g_EnvmapTint_ShadowTweaks.xyz; + } + else + { + // Mask is either normal map alpha or base map alpha #if ( SELFILLUMFRESNEL == 1 ) // This is to match the 2.0 version of vertexlitgeneric - float fEnvMapMask = lerp( baseColor.a, g_fInvertPhongMask, g_EnvmapTint_ShadowTweaks.w ); + float fEnvMapMask = lerp( baseColor.a, g_fInvertPhongMask, g_EnvmapTint_ShadowTweaks.w ); #else - float fEnvMapMask = lerp( baseColor.a, fSpecMask, g_EnvmapTint_ShadowTweaks.w ); + float fEnvMapMask = lerp( baseColor.a, fSpecMask, g_EnvmapTint_ShadowTweaks.w ); #endif - envMapColor = (ENV_MAP_SCALE * - lerp(1, fFresnelRanges, g_EnvMapFresnel.x) * - lerp(fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask)) * - texCUBE( EnvmapSampler, vReflect ).xyz * - g_EnvmapTint_ShadowTweaks.xyz; + envMapColor = (ENV_MAP_SCALE * + lerp(1, fFresnelRanges, g_EnvMapFresnel.x) * + lerp(fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask)) * + texCUBE( EnvmapSampler, vReflect ).xyz * + g_EnvmapTint_ShadowTweaks.xyz; + } } } diff --git a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc index 7b1cfc68..90141399 100644 --- a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc @@ -14,6 +14,7 @@ // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] // STATIC: "BLENDTINTBYBASEALPHA" "0..1" +// STATIC: "ENVMAPMASK" "0..1" // DYNAMIC: "PIXELFOGTYPE" "0..1" [ps20] // DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" [ps20] @@ -61,6 +62,8 @@ // Meaningless combinations // SKIP: $NORMALMAPALPHAENVMAPMASK && !$CUBEMAP +// SKIP: $NORMALMAPALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $ENVMAPMASK && !$CUBEMAP #include "common_flashlight_fxc.h" #include "common_vertexlitgeneric_dx9.h" @@ -183,6 +186,7 @@ float4 main( PS_INPUT i ) : COLOR bool bAmbientLight = AMBIENT_LIGHT ? true : false; bool bDetailTexture = DETAILTEXTURE ? true : false; bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; int nNumLights = NUM_LIGHTS; #if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) @@ -202,7 +206,13 @@ float4 main( PS_INPUT i ) : COLOR baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); #endif +#if ENVMAPMASK + // Blixibon - $bumpmap + $envmapmask + float3 specularFactor = 1.0f; +#else float specularFactor = 1.0f; +#endif + #if !DETAILTEXTURE // Blixibon - $bumpmap transform support float4 normalTexel = tex2D( BumpmapSampler, i.detailTexCoord_atten3.xy ); @@ -212,7 +222,14 @@ float4 main( PS_INPUT i ) : COLOR float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; if ( bNormalMapAlphaEnvmapMask ) + { specularFactor = normalTexel.a; + } + else if( bEnvmapMask ) + { + float4 envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + specularFactor *= envmapMaskTexel.xyz; + } float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); diff --git a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc index ad37fd5d..332b2572 100644 --- a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc @@ -14,6 +14,7 @@ // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] // STATIC: "BLENDTINTBYBASEALPHA" "0..1" +// STATIC: "ENVMAPMASK" "0..1" // DYNAMIC: "PIXELFOGTYPE" "0..1" [ps20] // DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" [ps20] @@ -61,6 +62,8 @@ // Meaningless combinations // SKIP: $NORMALMAPALPHAENVMAPMASK && !$CUBEMAP +// SKIP: $NORMALMAPALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $ENVMAPMASK && !$CUBEMAP #include "common_flashlight_fxc.h" #include "common_vertexlitgeneric_dx9.h" @@ -180,6 +183,7 @@ float4 main( PS_INPUT i ) : COLOR bool bAmbientLight = AMBIENT_LIGHT ? true : false; bool bDetailTexture = DETAILTEXTURE ? true : false; bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; int nNumLights = NUM_LIGHTS; #if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) @@ -199,7 +203,13 @@ float4 main( PS_INPUT i ) : COLOR baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); #endif +#if ENVMAPMASK + // Blixibon - $bumpmap + $envmapmask + float3 specularFactor = 1.0f; +#else float specularFactor = 1.0f; +#endif + #if !DETAILTEXTURE // Blixibon - $bumpmap transform support float4 normalTexel = tex2D( BumpmapSampler, i.detailTexCoord_atten3.xy ); @@ -209,7 +219,14 @@ float4 main( PS_INPUT i ) : COLOR float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; if ( bNormalMapAlphaEnvmapMask ) + { specularFactor = normalTexel.a; + } + else if( bEnvmapMask ) + { + float4 envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + specularFactor *= envmapMaskTexel.xyz; + } float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps20b.inc index fa9e3d77..4acdc5be 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps20b.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps20b.inc @@ -358,6 +358,27 @@ public: m_bSEAMLESS = true; #endif } +private: + int m_nBUMPMASK; +#ifdef _DEBUG + bool m_bBUMPMASK; +#endif +public: + void SetBUMPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nBUMPMASK = i; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } + void SetBUMPMASK( bool i ) + { + m_nBUMPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } private: int m_nNORMAL_DECODE_MODE; #ifdef _DEBUG @@ -442,27 +463,6 @@ public: m_bBASETEXTURETRANSFORM2 = true; #endif } -private: - int m_nSWAP_VERTEX_BLEND; -#ifdef _DEBUG - bool m_bSWAP_VERTEX_BLEND; -#endif -public: - void SetSWAP_VERTEX_BLEND( int i ) - { - Assert( i >= 0 && i <= 1 ); - m_nSWAP_VERTEX_BLEND = i; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } - void SetSWAP_VERTEX_BLEND( bool i ) - { - m_nSWAP_VERTEX_BLEND = i ? 1 : 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } private: int m_nPARALLAXCORRECT; #ifdef _DEBUG @@ -555,6 +555,10 @@ public: m_bSEAMLESS = false; #endif // _DEBUG m_nSEAMLESS = 0; +#ifdef _DEBUG + m_bBUMPMASK = false; +#endif // _DEBUG + m_nBUMPMASK = 0; #ifdef _DEBUG m_bNORMAL_DECODE_MODE = false; #endif // _DEBUG @@ -571,10 +575,6 @@ public: m_bBASETEXTURETRANSFORM2 = false; #endif // _DEBUG m_nBASETEXTURETRANSFORM2 = 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = false; -#endif // _DEBUG - m_nSWAP_VERTEX_BLEND = 0; #ifdef _DEBUG m_bPARALLAXCORRECT = false; #endif // _DEBUG @@ -585,13 +585,13 @@ public: // 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_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bRELIEF_MAPPING && m_bSEAMLESS && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bSWAP_VERTEX_BLEND && m_bPARALLAXCORRECT; + bool bAllStaticVarsDefined = m_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bRELIEF_MAPPING && m_bSEAMLESS && m_bBUMPMASK && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bPARALLAXCORRECT; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nRELIEF_MAPPING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nNORMAL_DECODE_MODE ) + ( 9437184 * m_nNORMALMASK_DECODE_MODE ) + ( 9437184 * m_nDETAIL_BLEND_MODE ) + ( 113246208 * m_nBASETEXTURETRANSFORM2 ) + ( 226492416 * m_nSWAP_VERTEX_BLEND ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; + return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nRELIEF_MAPPING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nBUMPMASK ) + ( 18874368 * m_nNORMAL_DECODE_MODE ) + ( 18874368 * m_nNORMALMASK_DECODE_MODE ) + ( 18874368 * m_nDETAIL_BLEND_MODE ) + ( 226492416 * m_nBASETEXTURETRANSFORM2 ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; } }; -#define shaderStaticTest_sdk_lightmappedgeneric_ps20b psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_RELIEF_MAPPING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_SWAP_VERTEX_BLEND + psh_forgot_to_set_static_PARALLAXCORRECT + 0 +#define shaderStaticTest_sdk_lightmappedgeneric_ps20b psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_RELIEF_MAPPING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_BUMPMASK + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_PARALLAXCORRECT + 0 class sdk_lightmappedgeneric_ps20b_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps30.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps30.inc index f63dbca6..205c6bda 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps30.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_lightmappedgeneric_ps30.inc @@ -337,6 +337,27 @@ public: m_bSEAMLESS = true; #endif } +private: + int m_nBUMPMASK; +#ifdef _DEBUG + bool m_bBUMPMASK; +#endif +public: + void SetBUMPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nBUMPMASK = i; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } + void SetBUMPMASK( bool i ) + { + m_nBUMPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } private: int m_nNORMAL_DECODE_MODE; #ifdef _DEBUG @@ -421,27 +442,6 @@ public: m_bBASETEXTURETRANSFORM2 = true; #endif } -private: - int m_nSWAP_VERTEX_BLEND; -#ifdef _DEBUG - bool m_bSWAP_VERTEX_BLEND; -#endif -public: - void SetSWAP_VERTEX_BLEND( int i ) - { - Assert( i >= 0 && i <= 1 ); - m_nSWAP_VERTEX_BLEND = i; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } - void SetSWAP_VERTEX_BLEND( bool i ) - { - m_nSWAP_VERTEX_BLEND = i ? 1 : 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } private: int m_nPARALLAXCORRECT; #ifdef _DEBUG @@ -530,6 +530,10 @@ public: m_bSEAMLESS = false; #endif // _DEBUG m_nSEAMLESS = 0; +#ifdef _DEBUG + m_bBUMPMASK = false; +#endif // _DEBUG + m_nBUMPMASK = 0; #ifdef _DEBUG m_bNORMAL_DECODE_MODE = false; #endif // _DEBUG @@ -546,10 +550,6 @@ public: m_bBASETEXTURETRANSFORM2 = false; #endif // _DEBUG m_nBASETEXTURETRANSFORM2 = 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = false; -#endif // _DEBUG - m_nSWAP_VERTEX_BLEND = 0; #ifdef _DEBUG m_bPARALLAXCORRECT = false; #endif // _DEBUG @@ -560,13 +560,13 @@ public: // 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_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bSEAMLESS && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bSWAP_VERTEX_BLEND && m_bPARALLAXCORRECT; + bool bAllStaticVarsDefined = m_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bSEAMLESS && m_bBUMPMASK && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bPARALLAXCORRECT; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nNORMAL_DECODE_MODE ) + ( 9437184 * m_nNORMALMASK_DECODE_MODE ) + ( 9437184 * m_nDETAIL_BLEND_MODE ) + ( 113246208 * m_nBASETEXTURETRANSFORM2 ) + ( 226492416 * m_nSWAP_VERTEX_BLEND ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; + return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nBUMPMASK ) + ( 18874368 * m_nNORMAL_DECODE_MODE ) + ( 18874368 * m_nNORMALMASK_DECODE_MODE ) + ( 18874368 * m_nDETAIL_BLEND_MODE ) + ( 226492416 * m_nBASETEXTURETRANSFORM2 ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; } }; -#define shaderStaticTest_sdk_lightmappedgeneric_ps30 psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_SWAP_VERTEX_BLEND + psh_forgot_to_set_static_PARALLAXCORRECT + 0 +#define shaderStaticTest_sdk_lightmappedgeneric_ps30 psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_BUMPMASK + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_PARALLAXCORRECT + 0 class sdk_lightmappedgeneric_ps30_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps20b.inc index 6c1e5fea..15a41433 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps20b.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps20b.inc @@ -316,6 +316,27 @@ public: m_bPHONG_HALFLAMBERT = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_skin_ps20b_Static_Index( ) { @@ -379,19 +400,23 @@ public: m_bPHONG_HALFLAMBERT = false; #endif // _DEBUG m_nPHONG_HALFLAMBERT = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT; + bool bAllStaticVarsDefined = m_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + 0; + return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + ( 6881280 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_skin_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + 0 +#define shaderStaticTest_sdk_skin_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_skin_ps20b_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps30.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps30.inc index 2405f0b6..3c53e88b 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps30.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_skin_ps30.inc @@ -316,6 +316,27 @@ public: m_bPHONG_HALFLAMBERT = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_skin_ps30_Static_Index( ) { @@ -379,19 +400,23 @@ public: m_bPHONG_HALFLAMBERT = false; #endif // _DEBUG m_nPHONG_HALFLAMBERT = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT; + bool bAllStaticVarsDefined = m_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + 0; + return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + ( 6881280 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_skin_ps30 psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + 0 +#define shaderStaticTest_sdk_skin_ps30 psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_skin_ps30_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20.inc index a526e689..b6cbcf56 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20.inc @@ -232,6 +232,27 @@ public: m_bBLENDTINTBYBASEALPHA = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_vertexlit_and_unlit_generic_bump_ps20_Static_Index( ) { @@ -279,19 +300,23 @@ public: m_bBLENDTINTBYBASEALPHA = false; #endif // _DEBUG m_nBLENDTINTBYBASEALPHA = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bBLENDTINTBYBASEALPHA; + bool bAllStaticVarsDefined = m_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bBLENDTINTBYBASEALPHA && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 24 * m_nCUBEMAP ) + ( 48 * m_nDIFFUSELIGHTING ) + ( 96 * m_nLIGHTWARPTEXTURE ) + ( 192 * m_nSELFILLUM ) + ( 384 * m_nSELFILLUMFRESNEL ) + ( 768 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1536 * m_nHALFLAMBERT ) + ( 3072 * m_nFLASHLIGHT ) + ( 6144 * m_nDETAILTEXTURE ) + ( 12288 * m_nDETAIL_BLEND_MODE ) + ( 86016 * m_nBLENDTINTBYBASEALPHA ) + 0; + return ( 24 * m_nCUBEMAP ) + ( 48 * m_nDIFFUSELIGHTING ) + ( 96 * m_nLIGHTWARPTEXTURE ) + ( 192 * m_nSELFILLUM ) + ( 384 * m_nSELFILLUMFRESNEL ) + ( 768 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1536 * m_nHALFLAMBERT ) + ( 3072 * m_nFLASHLIGHT ) + ( 6144 * m_nDETAILTEXTURE ) + ( 12288 * m_nDETAIL_BLEND_MODE ) + ( 86016 * m_nBLENDTINTBYBASEALPHA ) + ( 172032 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + 0 +#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_vertexlit_and_unlit_generic_bump_ps20_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc index c6da2788..7c81e32f 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc @@ -253,6 +253,27 @@ public: m_bBLENDTINTBYBASEALPHA = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_vertexlit_and_unlit_generic_bump_ps20b_Static_Index( ) { @@ -304,19 +325,23 @@ public: m_bBLENDTINTBYBASEALPHA = false; #endif // _DEBUG m_nBLENDTINTBYBASEALPHA = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA; + bool bAllStaticVarsDefined = m_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + 0; + return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + ( 430080 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20b psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + 0 +#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20b psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_vertexlit_and_unlit_generic_bump_ps20b_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps30.inc b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps30.inc index 205a2809..1cb70971 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps30.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9/SDK_vertexlit_and_unlit_generic_bump_ps30.inc @@ -253,6 +253,27 @@ public: m_bBLENDTINTBYBASEALPHA = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_vertexlit_and_unlit_generic_bump_ps30_Static_Index( ) { @@ -304,19 +325,23 @@ public: m_bBLENDTINTBYBASEALPHA = false; #endif // _DEBUG m_nBLENDTINTBYBASEALPHA = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA; + bool bAllStaticVarsDefined = m_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + 0; + return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + ( 430080 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps30 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + 0 +#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps30 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_vertexlit_and_unlit_generic_bump_ps30_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps20b.inc index fa9e3d77..4acdc5be 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps20b.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps20b.inc @@ -358,6 +358,27 @@ public: m_bSEAMLESS = true; #endif } +private: + int m_nBUMPMASK; +#ifdef _DEBUG + bool m_bBUMPMASK; +#endif +public: + void SetBUMPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nBUMPMASK = i; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } + void SetBUMPMASK( bool i ) + { + m_nBUMPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } private: int m_nNORMAL_DECODE_MODE; #ifdef _DEBUG @@ -442,27 +463,6 @@ public: m_bBASETEXTURETRANSFORM2 = true; #endif } -private: - int m_nSWAP_VERTEX_BLEND; -#ifdef _DEBUG - bool m_bSWAP_VERTEX_BLEND; -#endif -public: - void SetSWAP_VERTEX_BLEND( int i ) - { - Assert( i >= 0 && i <= 1 ); - m_nSWAP_VERTEX_BLEND = i; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } - void SetSWAP_VERTEX_BLEND( bool i ) - { - m_nSWAP_VERTEX_BLEND = i ? 1 : 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } private: int m_nPARALLAXCORRECT; #ifdef _DEBUG @@ -555,6 +555,10 @@ public: m_bSEAMLESS = false; #endif // _DEBUG m_nSEAMLESS = 0; +#ifdef _DEBUG + m_bBUMPMASK = false; +#endif // _DEBUG + m_nBUMPMASK = 0; #ifdef _DEBUG m_bNORMAL_DECODE_MODE = false; #endif // _DEBUG @@ -571,10 +575,6 @@ public: m_bBASETEXTURETRANSFORM2 = false; #endif // _DEBUG m_nBASETEXTURETRANSFORM2 = 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = false; -#endif // _DEBUG - m_nSWAP_VERTEX_BLEND = 0; #ifdef _DEBUG m_bPARALLAXCORRECT = false; #endif // _DEBUG @@ -585,13 +585,13 @@ public: // 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_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bRELIEF_MAPPING && m_bSEAMLESS && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bSWAP_VERTEX_BLEND && m_bPARALLAXCORRECT; + bool bAllStaticVarsDefined = m_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bRELIEF_MAPPING && m_bSEAMLESS && m_bBUMPMASK && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bPARALLAXCORRECT; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nRELIEF_MAPPING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nNORMAL_DECODE_MODE ) + ( 9437184 * m_nNORMALMASK_DECODE_MODE ) + ( 9437184 * m_nDETAIL_BLEND_MODE ) + ( 113246208 * m_nBASETEXTURETRANSFORM2 ) + ( 226492416 * m_nSWAP_VERTEX_BLEND ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; + return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nRELIEF_MAPPING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nBUMPMASK ) + ( 18874368 * m_nNORMAL_DECODE_MODE ) + ( 18874368 * m_nNORMALMASK_DECODE_MODE ) + ( 18874368 * m_nDETAIL_BLEND_MODE ) + ( 226492416 * m_nBASETEXTURETRANSFORM2 ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; } }; -#define shaderStaticTest_sdk_lightmappedgeneric_ps20b psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_RELIEF_MAPPING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_SWAP_VERTEX_BLEND + psh_forgot_to_set_static_PARALLAXCORRECT + 0 +#define shaderStaticTest_sdk_lightmappedgeneric_ps20b psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_RELIEF_MAPPING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_BUMPMASK + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_PARALLAXCORRECT + 0 class sdk_lightmappedgeneric_ps20b_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps30.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps30.inc index f63dbca6..205c6bda 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps30.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_lightmappedgeneric_ps30.inc @@ -337,6 +337,27 @@ public: m_bSEAMLESS = true; #endif } +private: + int m_nBUMPMASK; +#ifdef _DEBUG + bool m_bBUMPMASK; +#endif +public: + void SetBUMPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nBUMPMASK = i; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } + void SetBUMPMASK( bool i ) + { + m_nBUMPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bBUMPMASK = true; +#endif + } private: int m_nNORMAL_DECODE_MODE; #ifdef _DEBUG @@ -421,27 +442,6 @@ public: m_bBASETEXTURETRANSFORM2 = true; #endif } -private: - int m_nSWAP_VERTEX_BLEND; -#ifdef _DEBUG - bool m_bSWAP_VERTEX_BLEND; -#endif -public: - void SetSWAP_VERTEX_BLEND( int i ) - { - Assert( i >= 0 && i <= 1 ); - m_nSWAP_VERTEX_BLEND = i; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } - void SetSWAP_VERTEX_BLEND( bool i ) - { - m_nSWAP_VERTEX_BLEND = i ? 1 : 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = true; -#endif - } private: int m_nPARALLAXCORRECT; #ifdef _DEBUG @@ -530,6 +530,10 @@ public: m_bSEAMLESS = false; #endif // _DEBUG m_nSEAMLESS = 0; +#ifdef _DEBUG + m_bBUMPMASK = false; +#endif // _DEBUG + m_nBUMPMASK = 0; #ifdef _DEBUG m_bNORMAL_DECODE_MODE = false; #endif // _DEBUG @@ -546,10 +550,6 @@ public: m_bBASETEXTURETRANSFORM2 = false; #endif // _DEBUG m_nBASETEXTURETRANSFORM2 = 0; -#ifdef _DEBUG - m_bSWAP_VERTEX_BLEND = false; -#endif // _DEBUG - m_nSWAP_VERTEX_BLEND = 0; #ifdef _DEBUG m_bPARALLAXCORRECT = false; #endif // _DEBUG @@ -560,13 +560,13 @@ public: // 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_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bSEAMLESS && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bSWAP_VERTEX_BLEND && m_bPARALLAXCORRECT; + bool bAllStaticVarsDefined = m_bMASKEDBLENDING && m_bBASETEXTURE2 && m_bDETAILTEXTURE && m_bBUMPMAP && m_bBUMPMAP2 && m_bCUBEMAP && m_bENVMAPMASK && m_bBASEALPHAENVMAPMASK && m_bSELFILLUM && m_bNORMALMAPALPHAENVMAPMASK && m_bDIFFUSEBUMPMAP && m_bBASETEXTURENOENVMAP && m_bBASETEXTURE2NOENVMAP && m_bWARPLIGHTING && m_bFANCY_BLENDING && m_bSEAMLESS && m_bBUMPMASK && m_bNORMAL_DECODE_MODE && m_bNORMALMASK_DECODE_MODE && m_bDETAIL_BLEND_MODE && m_bBASETEXTURETRANSFORM2 && m_bPARALLAXCORRECT; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nNORMAL_DECODE_MODE ) + ( 9437184 * m_nNORMALMASK_DECODE_MODE ) + ( 9437184 * m_nDETAIL_BLEND_MODE ) + ( 113246208 * m_nBASETEXTURETRANSFORM2 ) + ( 226492416 * m_nSWAP_VERTEX_BLEND ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; + return ( 96 * m_nMASKEDBLENDING ) + ( 192 * m_nBASETEXTURE2 ) + ( 384 * m_nDETAILTEXTURE ) + ( 768 * m_nBUMPMAP ) + ( 2304 * m_nBUMPMAP2 ) + ( 4608 * m_nCUBEMAP ) + ( 9216 * m_nENVMAPMASK ) + ( 18432 * m_nBASEALPHAENVMAPMASK ) + ( 36864 * m_nSELFILLUM ) + ( 73728 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 147456 * m_nDIFFUSEBUMPMAP ) + ( 294912 * m_nBASETEXTURENOENVMAP ) + ( 589824 * m_nBASETEXTURE2NOENVMAP ) + ( 1179648 * m_nWARPLIGHTING ) + ( 2359296 * m_nFANCY_BLENDING ) + ( 4718592 * m_nSEAMLESS ) + ( 9437184 * m_nBUMPMASK ) + ( 18874368 * m_nNORMAL_DECODE_MODE ) + ( 18874368 * m_nNORMALMASK_DECODE_MODE ) + ( 18874368 * m_nDETAIL_BLEND_MODE ) + ( 226492416 * m_nBASETEXTURETRANSFORM2 ) + ( 452984832 * m_nPARALLAXCORRECT ) + 0; } }; -#define shaderStaticTest_sdk_lightmappedgeneric_ps30 psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_SWAP_VERTEX_BLEND + psh_forgot_to_set_static_PARALLAXCORRECT + 0 +#define shaderStaticTest_sdk_lightmappedgeneric_ps30 psh_forgot_to_set_static_MASKEDBLENDING + psh_forgot_to_set_static_BASETEXTURE2 + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_BUMPMAP + psh_forgot_to_set_static_BUMPMAP2 + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_ENVMAPMASK + psh_forgot_to_set_static_BASEALPHAENVMAPMASK + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_DIFFUSEBUMPMAP + psh_forgot_to_set_static_BASETEXTURENOENVMAP + psh_forgot_to_set_static_BASETEXTURE2NOENVMAP + psh_forgot_to_set_static_WARPLIGHTING + psh_forgot_to_set_static_FANCY_BLENDING + psh_forgot_to_set_static_SEAMLESS + psh_forgot_to_set_static_BUMPMASK + psh_forgot_to_set_static_NORMAL_DECODE_MODE + psh_forgot_to_set_static_NORMALMASK_DECODE_MODE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BASETEXTURETRANSFORM2 + psh_forgot_to_set_static_PARALLAXCORRECT + 0 class sdk_lightmappedgeneric_ps30_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps20b.inc index 6c1e5fea..15a41433 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps20b.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps20b.inc @@ -316,6 +316,27 @@ public: m_bPHONG_HALFLAMBERT = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_skin_ps20b_Static_Index( ) { @@ -379,19 +400,23 @@ public: m_bPHONG_HALFLAMBERT = false; #endif // _DEBUG m_nPHONG_HALFLAMBERT = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT; + bool bAllStaticVarsDefined = m_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + 0; + return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + ( 6881280 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_skin_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + 0 +#define shaderStaticTest_sdk_skin_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_skin_ps20b_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps30.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps30.inc index 2405f0b6..3c53e88b 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps30.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_skin_ps30.inc @@ -316,6 +316,27 @@ public: m_bPHONG_HALFLAMBERT = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_skin_ps30_Static_Index( ) { @@ -379,19 +400,23 @@ public: m_bPHONG_HALFLAMBERT = false; #endif // _DEBUG m_nPHONG_HALFLAMBERT = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT; + bool bAllStaticVarsDefined = m_bCONVERT_TO_SRGB && m_bCUBEMAP && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bFLASHLIGHT && m_bLIGHTWARPTEXTURE && m_bPHONGWARPTEXTURE && m_bWRINKLEMAP && m_bDETAIL_BLEND_MODE && m_bDETAILTEXTURE && m_bRIMLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bFASTPATH_NOBUMP && m_bBLENDTINTBYBASEALPHA && m_bPHONG_HALFLAMBERT && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + 0; + return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nCUBEMAP ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nFLASHLIGHT ) + ( 1280 * m_nLIGHTWARPTEXTURE ) + ( 2560 * m_nPHONGWARPTEXTURE ) + ( 5120 * m_nWRINKLEMAP ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nDETAILTEXTURE ) + ( 143360 * m_nRIMLIGHT ) + ( 286720 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 860160 * m_nFASTPATH_NOBUMP ) + ( 1720320 * m_nBLENDTINTBYBASEALPHA ) + ( 3440640 * m_nPHONG_HALFLAMBERT ) + ( 6881280 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_skin_ps30 psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + 0 +#define shaderStaticTest_sdk_skin_ps30 psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_PHONGWARPTEXTURE + psh_forgot_to_set_static_WRINKLEMAP + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_RIMLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_FASTPATH_NOBUMP + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_PHONG_HALFLAMBERT + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_skin_ps30_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20.inc index a526e689..b6cbcf56 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20.inc @@ -232,6 +232,27 @@ public: m_bBLENDTINTBYBASEALPHA = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_vertexlit_and_unlit_generic_bump_ps20_Static_Index( ) { @@ -279,19 +300,23 @@ public: m_bBLENDTINTBYBASEALPHA = false; #endif // _DEBUG m_nBLENDTINTBYBASEALPHA = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bBLENDTINTBYBASEALPHA; + bool bAllStaticVarsDefined = m_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bBLENDTINTBYBASEALPHA && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 24 * m_nCUBEMAP ) + ( 48 * m_nDIFFUSELIGHTING ) + ( 96 * m_nLIGHTWARPTEXTURE ) + ( 192 * m_nSELFILLUM ) + ( 384 * m_nSELFILLUMFRESNEL ) + ( 768 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1536 * m_nHALFLAMBERT ) + ( 3072 * m_nFLASHLIGHT ) + ( 6144 * m_nDETAILTEXTURE ) + ( 12288 * m_nDETAIL_BLEND_MODE ) + ( 86016 * m_nBLENDTINTBYBASEALPHA ) + 0; + return ( 24 * m_nCUBEMAP ) + ( 48 * m_nDIFFUSELIGHTING ) + ( 96 * m_nLIGHTWARPTEXTURE ) + ( 192 * m_nSELFILLUM ) + ( 384 * m_nSELFILLUMFRESNEL ) + ( 768 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1536 * m_nHALFLAMBERT ) + ( 3072 * m_nFLASHLIGHT ) + ( 6144 * m_nDETAILTEXTURE ) + ( 12288 * m_nDETAIL_BLEND_MODE ) + ( 86016 * m_nBLENDTINTBYBASEALPHA ) + ( 172032 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + 0 +#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_vertexlit_and_unlit_generic_bump_ps20_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc index c6da2788..7c81e32f 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps20b.inc @@ -253,6 +253,27 @@ public: m_bBLENDTINTBYBASEALPHA = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_vertexlit_and_unlit_generic_bump_ps20b_Static_Index( ) { @@ -304,19 +325,23 @@ public: m_bBLENDTINTBYBASEALPHA = false; #endif // _DEBUG m_nBLENDTINTBYBASEALPHA = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA; + bool bAllStaticVarsDefined = m_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + 0; + return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + ( 430080 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20b psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + 0 +#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps20b psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_vertexlit_and_unlit_generic_bump_ps20b_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps30.inc b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps30.inc index 205a2809..1cb70971 100644 --- a/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps30.inc +++ b/sp/src/materialsystem/stdshaders/fxctmp9_tmp/SDK_vertexlit_and_unlit_generic_bump_ps30.inc @@ -253,6 +253,27 @@ public: m_bBLENDTINTBYBASEALPHA = true; #endif } +private: + int m_nENVMAPMASK; +#ifdef _DEBUG + bool m_bENVMAPMASK; +#endif +public: + void SetENVMAPMASK( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nENVMAPMASK = i; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } + void SetENVMAPMASK( bool i ) + { + m_nENVMAPMASK = i ? 1 : 0; +#ifdef _DEBUG + m_bENVMAPMASK = true; +#endif + } public: sdk_vertexlit_and_unlit_generic_bump_ps30_Static_Index( ) { @@ -304,19 +325,23 @@ public: m_bBLENDTINTBYBASEALPHA = false; #endif // _DEBUG m_nBLENDTINTBYBASEALPHA = 0; +#ifdef _DEBUG + m_bENVMAPMASK = false; +#endif // _DEBUG + m_nENVMAPMASK = 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_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA; + bool bAllStaticVarsDefined = m_bCUBEMAP && m_bDIFFUSELIGHTING && m_bLIGHTWARPTEXTURE && m_bSELFILLUM && m_bSELFILLUMFRESNEL && m_bNORMALMAPALPHAENVMAPMASK && m_bHALFLAMBERT && m_bFLASHLIGHT && m_bDETAILTEXTURE && m_bDETAIL_BLEND_MODE && m_bFLASHLIGHTDEPTHFILTERMODE && m_bBLENDTINTBYBASEALPHA && m_bENVMAPMASK; Assert( bAllStaticVarsDefined ); #endif // _DEBUG - return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + 0; + return ( 20 * m_nCUBEMAP ) + ( 40 * m_nDIFFUSELIGHTING ) + ( 80 * m_nLIGHTWARPTEXTURE ) + ( 160 * m_nSELFILLUM ) + ( 320 * m_nSELFILLUMFRESNEL ) + ( 640 * m_nNORMALMAPALPHAENVMAPMASK ) + ( 1280 * m_nHALFLAMBERT ) + ( 2560 * m_nFLASHLIGHT ) + ( 5120 * m_nDETAILTEXTURE ) + ( 10240 * m_nDETAIL_BLEND_MODE ) + ( 71680 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 215040 * m_nBLENDTINTBYBASEALPHA ) + ( 430080 * m_nENVMAPMASK ) + 0; } }; -#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps30 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + 0 +#define shaderStaticTest_sdk_vertexlit_and_unlit_generic_bump_ps30 psh_forgot_to_set_static_CUBEMAP + psh_forgot_to_set_static_DIFFUSELIGHTING + psh_forgot_to_set_static_LIGHTWARPTEXTURE + psh_forgot_to_set_static_SELFILLUM + psh_forgot_to_set_static_SELFILLUMFRESNEL + psh_forgot_to_set_static_NORMALMAPALPHAENVMAPMASK + psh_forgot_to_set_static_HALFLAMBERT + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_DETAILTEXTURE + psh_forgot_to_set_static_DETAIL_BLEND_MODE + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_BLENDTINTBYBASEALPHA + psh_forgot_to_set_static_ENVMAPMASK + 0 class sdk_vertexlit_and_unlit_generic_bump_ps30_Dynamic_Index { private: diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp index ab97626c..452a3433 100644 --- a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp @@ -879,18 +879,18 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** } } } - const bool hasBumpMask = false; //hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum && - //!hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0); + const bool hasBumpMask = hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum && + !hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0); int nNormalMaskDecodeMode = 0; - /*if ( hasBumpMask && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() ) + if ( hasBumpMask && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() ) { ITexture *pBumpMaskTex = params[info.m_nBumpMask]->GetTextureValue(); if ( pBumpMaskTex ) { nNormalMaskDecodeMode = pBumpMaskTex->GetNormalDecodeMode(); } - }*/ + } const bool bHasOutline = false; //IsBoolSet( info.m_nOutline, params ); pContextData->m_bPixelShaderForceFastPathBecauseOutline = bHasOutline; @@ -1141,7 +1141,7 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); - //SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); @@ -1165,12 +1165,6 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** #endif #ifdef MAPBASE SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURETRANSFORM2, hasBaseTextureTransform2 ); - // Hammer apparently has a bug that causes the vertex blend to get swapped. - // Hammer uses a special internal shader to nullify this, but it doesn't work with custom shaders. - // Downfall got around this by swapping around the base textures in the DLL code when drawn by the editor. - // Doing it here in the shader itself allows us to retain other properties, like FANCY_BLENDING. - // TODO: Could we do this here in the DLL and swap the alpha before it's passed to the shader? - SET_STATIC_PIXEL_SHADER_COMBO( SWAP_VERTEX_BLEND, hasBaseTexture2 && pShader->UsingEditor(params) ); #endif #ifdef PARALLAX_CORRECTED_CUBEMAPS // Parallax cubemaps enabled for 2_0b and onwards @@ -1187,7 +1181,7 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); - //SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); @@ -1211,8 +1205,6 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** #endif #ifdef MAPBASE SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURETRANSFORM2, hasBaseTextureTransform2 ); - // See the comment in the 3.0 shader block for more info on this. - SET_STATIC_PIXEL_SHADER_COMBO( SWAP_VERTEX_BLEND, hasBaseTexture2 && pShader->UsingEditor(params) ); #endif #ifdef PARALLAX_CORRECTED_CUBEMAPS // Parallax cubemaps enabled for 2_0b and onwards @@ -1362,6 +1354,10 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue(); bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); +#ifdef MAPBASE + bool bEditorBlend = (hasBaseTexture2 && pShader->UsingEditor( params )); // Mapbase - For fixing editor blending +#endif + pContextData->m_bPixelShaderFastPath = true; bool bUsingContrast = hasEnvmap && ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) && (envmapSaturation != 1.0f); bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f); @@ -1538,7 +1534,12 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** // Parallax cubemaps if (hasParallaxCorrection) { - pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 21, params[info.m_nEnvmapOrigin]->GetVecValue() ); + float envMapOrigin[4] = {0,0,0,0}; + params[info.m_nEnvmapOrigin]->GetVecValue( envMapOrigin, 3 ); +#ifdef MAPBASE + envMapOrigin[4] = bEditorBlend ? 1.0f : 0.0f; +#endif + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 21, envMapOrigin ); float* vecs[3]; vecs[0] = const_cast(params[info.m_nEnvmapParallaxObb1]->GetVecValue()); @@ -1558,6 +1559,29 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** } #endif +#ifdef MAPBASE + // Hammer apparently has a bug that causes the vertex blend to get swapped. + // Hammer uses a special internal shader to nullify this, but it doesn't work with custom shaders. + // Downfall got around this by swapping around the base textures in the DLL code when drawn by the editor. + // Doing it here in the shader itself allows us to retain other properties, like FANCY_BLENDING. + else + { + // m_SemiStaticCmdsOut wasn't being sent correctly, so we have to assign this to the API directly + float editorBlend = bEditorBlend ? 1.0f : 0.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 21, &editorBlend, 1 ); + /* + if (bEditorBlend) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 35, 1.0f ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 35, 0.0f ); + } + */ + } +#endif + pContextData->m_SemiStaticCmdsOut.End(); } } diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h index 94478434..ff4a296e 100644 --- a/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h @@ -10,6 +10,7 @@ // SKIP: !$FASTPATH && $FASTPATHENVMAPTINT // SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP // SKIP: !$BUMPMAP && $BUMPMAP2 +// SKIP: !$BUMPMAP2 && $BUMPMASK // SKIP: $ENVMAPMASK && $BUMPMAP2 // SKIP: $BASETEXTURENOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) // SKIP: $BASETEXTURE2NOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) @@ -35,6 +36,8 @@ // SKIP: $SWAP_VERTEX_BLEND && !$BASETEXTURE2 +// SKIP: !$FANCY_BLENDING && $MASKEDBLENDING + // debug crap: // NOSKIP: $DETAILTEXTURE // NOSKIP: $CUBEMAP @@ -114,8 +117,16 @@ const float4 g_ShadowTweaks : register( c19 ); #if PARALLAXCORRECT // Parallax cubemaps -const float3 cubemapPos : register(c21); +const float4 cubemapPos : register(c21); const float4x4 obbMatrix : register(c22); //through c25 +#define g_BlendInverted cubemapPos.w +#else +// Blixibon - Hammer apparently has a bug that causes the vertex blend to get swapped. +// Hammer uses a special internal shader to nullify this, but it doesn't work with custom shaders. +// Downfall got around this by swapping around the base textures in the DLL code when drawn by the editor. +// Doing it here in the shader itself allows us to retain other properties, like FANCY_BLENDING. +// TODO: This may be inefficent usage of a constant +const HALF g_BlendInverted : register(c21); #endif @@ -349,15 +360,13 @@ HALF4 main( PS_INPUT i ) : COLOR float blendfactor=0.5; #else -#if SWAP_VERTEX_BLEND - // Blixibon - Hammer apparently has a bug that causes the vertex blend to get swapped. - // Hammer uses a special internal shader to nullify this, but it doesn't work with custom shaders. - // Downfall got around this by swapping around the base textures in the DLL code when drawn by the editor. - // Doing it here in the shader itself allows us to retain other properties, like FANCY_BLENDING. - float blendfactor=1.0f-i.vertexBlendX_fogFactorW.r; -#else float blendfactor=i.vertexBlendX_fogFactorW.r; -#endif + + // See g_BlendInverted's declaration for more info on this + if (g_BlendInverted > 0.0) + { + blendfactor=1.0f-blendfactor; + } #endif diff --git a/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp index 7a59c9d8..93e2beba 100644 --- a/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp +++ b/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp @@ -211,6 +211,19 @@ void InitSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, VertexLitGener pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); } +#ifdef MAPBASE + // This is crashing for currently unknown reasons. + // As a result, $envmapmask support is not yet functional. + /* + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + */ +#endif + if ( bHasSelfIllumMask ) { pShader->LoadTexture( info.m_nSelfIllumMask ); @@ -258,6 +271,10 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad bool bHasPhongWarp = (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsTexture(); bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); +#ifdef MAPBASE + bool bHasEnvmapMask = (!bHasFlashlight || IsX360()) && info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsTexture(); +#endif + #if !defined( _X360 ) bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); #endif @@ -431,6 +448,13 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); } +#ifdef MAPBASE + if ( bHasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } +#endif + if( bHasVertexColor || bHasVertexAlpha ) { flags |= VERTEX_COLOR; @@ -484,6 +508,7 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); #ifdef MAPBASE SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); #endif SET_STATIC_PIXEL_SHADER( sdk_skin_ps20b ); } @@ -517,6 +542,7 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); #ifdef MAPBASE SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); #endif SET_STATIC_PIXEL_SHADER( sdk_skin_ps30 ); } @@ -616,6 +642,13 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad } } +#ifdef MAPBASE + if ( bHasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER15, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } +#endif + if ( hasDetailTexture ) { pShader->BindTexture( SHADER_SAMPLER13, info.m_nDetail, info.m_nDetailFrame ); diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp index e2977dd7..21202a4e 100644 --- a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp @@ -193,6 +193,7 @@ void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** para CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); } +#ifndef MAPBASE if ( IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ) && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && !hasNormalMapAlphaEnvmapMask ) { @@ -209,6 +210,7 @@ void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** para params[info.m_nEnvmap]->SetUndefined(); } } +#endif // If mat_specular 0, then get rid of envmap if ( !g_pConfig->UseSpecular() && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) @@ -707,6 +709,7 @@ static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterial SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); SET_STATIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_bump_ps20b ); //} //else // ps_2_0 @@ -755,6 +758,7 @@ static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterial SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); SET_STATIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_bump_ps30 ); } #endif diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition.cpp b/sp/src/materialsystem/stdshaders/worldvertextransition.cpp index 0b4b2202..d8671ddd 100644 --- a/sp/src/materialsystem/stdshaders/worldvertextransition.cpp +++ b/sp/src/materialsystem/stdshaders/worldvertextransition.cpp @@ -12,10 +12,6 @@ //#include "worldvertextransition_dx8_helper.h" #include "lightmappedgeneric_dx9_helper.h" -static LightmappedGeneric_DX9_Vars_t s_info; - -//static LightmappedGeneric_DX9_Vars_t s_info_editor; - DEFINE_FALLBACK_SHADER( SDK_WorldVertexTransition, SDK_WorldVertexTransition_DX9 ) @@ -156,43 +152,27 @@ BEGIN_VS_SHADER( SDK_WorldVertexTransition_DX9, "Help for SDK_WorldVertexTransit return 0; } + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. SHADER_INIT_PARAMS() { - SetupVars( s_info ); - InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); - //SetupVars( s_info_editor ); - //SwapLayers( s_info_editor ); + LightmappedGeneric_DX9_Vars_t info; + SetupVars( info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, info ); } SHADER_INIT { - SetupVars( s_info ); - InitLightmappedGeneric_DX9( this, params, s_info ); + LightmappedGeneric_DX9_Vars_t info; + SetupVars( info ); + InitLightmappedGeneric_DX9( this, params, info ); } SHADER_DRAW { - //if ( UsingEditor( params ) ) - // DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info_editor, pContextDataPtr ); - //else - DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + LightmappedGeneric_DX9_Vars_t info; + SetupVars( info ); + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, info, pContextDataPtr ); } -private: - // This hack is from Half-Life 2: Downfall in order to support WorldVertexTransition in Hammer. - // We get around this through a different hack in the shader code itself now. - // Original comment: - // "Hack to make hammer display WVT in non-inverted way. - // It worked ok in standard WVT because of special editor-only shader. - // Why Valve just didn't inverted vertex alpha directly in hammer code? oO" - //static FORCEINLINE void SwapLayers( LightmappedGeneric_DX9_Vars_t &info ) - //{ - // V_swap( info.m_nBaseTexture, info.m_nBaseTexture2 ); - // V_swap( info.m_nBaseTextureFrame, info.m_nBaseTexture2Frame ); - // V_swap( info.m_nBaseTextureNoEnvmap, info.m_nBaseTexture2NoEnvmap ); - // V_swap( info.m_nBumpmap, info.m_nBumpmap2 ); - // V_swap( info.m_nBumpFrame, info.m_nBumpFrame2 ); - // V_swap( info.m_nBumpTransform, info.m_nBumpTransform2 ); - //} END_SHADER diff --git a/sp/src/public/tier1/mapbase_con_groups.h b/sp/src/public/tier1/mapbase_con_groups.h new file mode 100644 index 00000000..d21e0740 --- /dev/null +++ b/sp/src/public/tier1/mapbase_con_groups.h @@ -0,0 +1,37 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: See tier1/mapbase_con_groups.cpp for more information +// +// $NoKeywords: $ +//============================================================================= + +#ifndef CON_VERBOSE_COLORS_H +#define CON_VERBOSE_COLORS_H +#ifdef _WIN32 +#pragma once +#endif + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//static const Color CON_COLOR_DEV_VERBOSE( 192, 128, 192, 255 ); + +// General +#define CON_GROUP_MAPBASE_MISC "Mapbase Misc." +#define CON_GROUP_PHYSICS "Physics" + +// Server +#define CON_GROUP_IO_SYSTEM "I/O System" +#define CON_GROUP_NPC_SCRIPTS "NPC Scripts" +#define CON_GROUP_CHOREO "Choreo" + +// VScript +#define CON_GROUP_VSCRIPT "VScript" +#define CON_GROUP_VSCRIPT_PRINT "VScript Print" + +// Mapbase console group message. +void CGMsg( int level, const char *pszGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 ); + +#define CGWarning CGMsg + +#endif diff --git a/sp/src/public/vscript/ivscript.h b/sp/src/public/vscript/ivscript.h index bf8a0de9..d5c8ba82 100644 --- a/sp/src/public/vscript/ivscript.h +++ b/sp/src/public/vscript/ivscript.h @@ -128,6 +128,13 @@ class CUtlBuffer; //----------------------------------------------------------------------------- class IScriptVM; +#ifdef MAPBASE_VSCRIPT +class KeyValues; + +// This has been moved up a bit for IScriptManager +DECLARE_POINTER_HANDLE( HSCRIPT ); +#define INVALID_HSCRIPT ((HSCRIPT)-1) +#endif enum ScriptLanguage_t { @@ -145,20 +152,25 @@ class IScriptManager : public IAppSystem public: virtual IScriptVM *CreateVM( ScriptLanguage_t language = SL_DEFAULT ) = 0; virtual void DestroyVM( IScriptVM * ) = 0; + +#ifdef MAPBASE_VSCRIPT + virtual HSCRIPT CreateScriptKeyValues( IScriptVM *pVM, KeyValues *pKV, bool bAllowDestruct ) = 0; + virtual KeyValues *GetKeyValuesFromScriptKV( IScriptVM *pVM, HSCRIPT hSKV ) = 0; +#endif }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- -DECLARE_POINTER_HANDLE( HSCRIPT ); -#define INVALID_HSCRIPT ((HSCRIPT)-1) - #ifdef MAPBASE_VSCRIPT template T *HScriptToClass( HSCRIPT hObj ) { return (hObj) ? (T*)g_pScriptVM->GetInstanceValue( hObj, GetScriptDesc( (T*)NULL ) ) : NULL; } +#else +DECLARE_POINTER_HANDLE( HSCRIPT ); +#define INVALID_HSCRIPT ((HSCRIPT)-1) #endif //----------------------------------------------------------------------------- @@ -305,6 +317,10 @@ public: //--------------------------------------------------------- +#ifdef MAPBASE_VSCRIPT +struct ScriptHook_t; +#endif + struct ScriptClassDesc_t { ScriptClassDesc_t() : m_pszScriptName( 0 ), m_pszClassname( 0 ), m_pszDescription( 0 ), m_pBaseDesc( 0 ), m_pfnConstruct( 0 ), m_pfnDestruct( 0 ), pHelper(NULL) @@ -320,6 +336,10 @@ struct ScriptClassDesc_t ScriptClassDesc_t * m_pBaseDesc; CUtlVector m_FunctionBindings; +#ifdef MAPBASE_VSCRIPT + CUtlVector m_Hooks; +#endif + void *(*m_pfnConstruct)(); void (*m_pfnDestruct)( void *); IScriptInstanceHelper * pHelper; // optional helper @@ -607,6 +627,12 @@ struct ScriptEnumDesc_t #define ScriptRegisterConstant( pVM, constant, description ) ScriptRegisterConstantNamed( pVM, constant, #constant, description ) #define ScriptRegisterConstantNamed( pVM, constant, scriptName, description ) do { static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = constant; pVM->RegisterConstant( &binding ); } while (0) +// Could probably use a better name. +// This is used for registering variants (particularly vectors) not tied to existing variables. +// The principal difference is that m_data is initted with bCopy set to true. +#define ScriptRegisterConstantFromTemp( pVM, constant, description ) ScriptRegisterConstantFromTempNamed( pVM, constant, #constant, description ) +#define ScriptRegisterConstantFromTempNamed( pVM, constant, scriptName, description ) do { static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = ScriptVariant_t( constant, true ); pVM->RegisterConstant( &binding ); } while (0) + //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- @@ -697,6 +723,29 @@ struct ScriptEnumDesc_t #define DEFINE_SCRIPT_CONSTRUCTOR() ScriptAddConstructorToClassDesc( pDesc, _className ); #define DEFINE_SCRIPT_INSTANCE_HELPER( p ) pDesc->pHelper = (p); +#ifdef MAPBASE_VSCRIPT +// Use this for hooks which have no parameters +#define DEFINE_SIMPLE_SCRIPTHOOK( hook, hookName, returnType, description ) \ + if (!hook.m_bDefined) \ + { \ + ScriptHook_t *pHook = &hook; \ + pHook->m_desc.m_pszScriptName = hookName; pHook->m_desc.m_pszFunction = #hook; pHook->m_desc.m_ReturnType = returnType; pHook->m_desc.m_pszDescription = description; \ + pDesc->m_Hooks.AddToTail(pHook); \ + } + +#define BEGIN_SCRIPTHOOK( hook, hookName, returnType, description ) \ + if (!hook.m_bDefined) \ + { \ + ScriptHook_t *pHook = &hook; \ + pHook->m_desc.m_pszScriptName = hookName; pHook->m_desc.m_pszFunction = #hook; pHook->m_desc.m_ReturnType = returnType; pHook->m_desc.m_pszDescription = description; + +#define DEFINE_SCRIPTHOOK_PARAM( paramName, type ) pHook->AddParameter( paramName, type ); + +#define END_SCRIPTHOOK() \ + pDesc->m_Hooks.AddToTail(pHook); \ + } +#endif + template ScriptClassDesc_t *GetScriptDesc(T *); struct ScriptNoBase_t; @@ -1468,6 +1517,100 @@ typedef CScriptScopeT<> CScriptScope; #define VScriptAddEnumToRoot( enumVal ) g_pScriptVM->SetValue( #enumVal, (int)enumVal ) +#ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// Function bindings allow script functions to run C++ functions. +// Hooks allow C++ functions to run script functions. +// +// This was previously done with raw function lookups, but Mapbase adds more and +// it's hard to keep track of them without proper standards or documentation. +// +// At the moment, this simply plugs hook documentation into VScript and maintains +// the same function lookup method on the inside, but it's intended to be open for +// more complex hook mechanisms with proper parameters in the future. +// +// For example: +// +// if (m_hFunc) +// { +// g_pScriptVM->ExecuteFunction( m_Func, pArgs, m_desc.m_Parameters.Count(), pReturn, m_ScriptScope, true ); +// } +//----------------------------------------------------------------------------- +struct ScriptHook_t +{ + ScriptFuncDescriptor_t m_desc; + CUtlVector m_pszParameterNames; + bool m_bDefined; + + void AddParameter( const char *pszName, ScriptDataType_t type ) + { + int iCur = m_desc.m_Parameters.Count(); + m_desc.m_Parameters.SetGrowSize( 1 ); m_desc.m_Parameters.EnsureCapacity( iCur + 1 ); m_desc.m_Parameters.AddToTail( type ); + m_pszParameterNames.SetGrowSize( 1 ); m_pszParameterNames.EnsureCapacity( iCur + 1 ); m_pszParameterNames.AddToTail( pszName ); + } + + // ----------------------------------------------------------------- + + // Cached for when CanRunInScope() is called before Call() + HSCRIPT m_hFunc; + + // Checks if there's a function of this name which would run in this scope + HSCRIPT CanRunInScope( HSCRIPT hScope ) + { + extern IScriptVM *g_pScriptVM; + m_hFunc = g_pScriptVM->LookupFunction( m_desc.m_pszScriptName, hScope ); + return m_hFunc; + } + + // Checks if an existing func can be used + bool CheckFuncValid( HSCRIPT hFunc ) + { + // TODO: Better crtieria for this? + if (hFunc) + { + m_hFunc = hFunc; + return true; + } + return false; + } + + // Call the function + bool Call( HSCRIPT hScope, ScriptVariant_t *pReturn, ScriptVariant_t *pArgs, bool bRelease = true ) + { + extern IScriptVM *g_pScriptVM; + + Assert( ARRAYSIZE(pArgs) == m_desc.m_Parameters.Count() ); + + // Make sure we have a function in this scope + if (!m_hFunc && !CanRunInScope(hScope)) + return false; + else + { + for (int i = 0; i < m_desc.m_Parameters.Count(); i++) + { + g_pScriptVM->SetValue( m_pszParameterNames[i], pArgs[i] ); + } + + g_pScriptVM->ExecuteFunction( m_hFunc, NULL, 0, pReturn, hScope, true ); + + if (bRelease) + g_pScriptVM->ReleaseFunction( m_hFunc ); + + m_hFunc = NULL; + + for (int i = 0; i < m_desc.m_Parameters.Count(); i++) + { + g_pScriptVM->ClearValue( m_pszParameterNames[i] ); + } + + return true; + } + + return false; + } +}; +#endif + //----------------------------------------------------------------------------- // Script function proxy support //----------------------------------------------------------------------------- diff --git a/sp/src/tier1/mapbase_con_groups.cpp b/sp/src/tier1/mapbase_con_groups.cpp new file mode 100644 index 00000000..028bb67e --- /dev/null +++ b/sp/src/tier1/mapbase_con_groups.cpp @@ -0,0 +1,177 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: Mapbase classifies certain types of console messages into groups with specific colors. +// +// This is inspired by similar groups seen in CS:GO and Source 2 games. +// +// $NoKeywords: $ +//============================================================================= + +#include +#include +#include +#include "basetypes.h" +#include "tier1/tier1.h" +#include "tier1/utldict.h" +#include "Color.h" +#include "tier1/mapbase_con_groups.h" + +void CV_ColorChanged( IConVar *pConVar, const char *pOldString, float flOldValue ); + +struct ConGroup_t +{ + ConGroup_t( const char *_pszName, ConVar *pCvar ) + { + pszName = _pszName; + cvar = pCvar; + } + + const Color &GetColor() + { + if (_clr.a() == 0) + { + // Read the cvar + int clr[3]; + sscanf( cvar->GetString(), "%i %i %i", &clr[0], &clr[1], &clr[2] ); + _clr.SetColor( clr[0], clr[1], clr[2], 255 ); + } + return _clr; + } + + const char *pszName; + Color _clr; + ConVar *cvar; + + //bool bDisabled; +}; + +//----------------------------------------------------------------------------- +// To define a console group, +//----------------------------------------------------------------------------- + +#define DEFINE_CON_GROUP_CVAR(name, def, desc) static ConVar con_group_##name##_color( "con_group_" #name "_color", def, FCVAR_ARCHIVE, desc, CV_ColorChanged ) + +DEFINE_CON_GROUP_CVAR( mapbase_misc, "192 128 224", "Messages from misc. Mapbase functions, like map-specific files." ); +DEFINE_CON_GROUP_CVAR( physics, "159 209 159", "Messages from physics-related events." ); + +DEFINE_CON_GROUP_CVAR( inputoutput, "220 170 220", "Messages from I/O events. (these display in developer 2)" ); +DEFINE_CON_GROUP_CVAR( npc_scripts, "255 115 215", "Messages from scripted_sequence, etc. (these display in developer 2)" ); +DEFINE_CON_GROUP_CVAR( choreo, "240 224 180", "Messages from choreographed scenes. (these display in developer 1, 2, etc.)" ); + +DEFINE_CON_GROUP_CVAR( vscript, "192 224 240", "Internal messages from VScript not produced by the user's scripts." ); +DEFINE_CON_GROUP_CVAR( vscript_print, "80 186 255", "Messages from VScript's 'print' function." ); + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +#define DEFINE_CON_GROUP(name, codename) { name, &con_group_##codename##_color } + +ConGroup_t g_ConGroups[] = { + + // General + DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, mapbase_misc ), + DEFINE_CON_GROUP( CON_GROUP_PHYSICS, physics ), + + // Server + DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, inputoutput ), + DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, npc_scripts ), + DEFINE_CON_GROUP( CON_GROUP_CHOREO, choreo ), + + // VScript + DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, vscript ), + DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, vscript_print ), + +}; + +void CV_ColorChanged( IConVar *pConVar, const char *pOldString, float flOldValue ) +{ + for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++) + { + // Reset the alpha to indicate it needs to be refreshed + g_ConGroups[i]._clr[3] = 0; + } +} + +ConGroup_t *FindConGroup( const char *pszGroup ) +{ + for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++) + { + if (V_strcmp(pszGroup, g_ConGroups[i].pszName) == 0) + return &g_ConGroups[i]; + } + + return NULL; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +ConVar con_group_include_name( "con_group_include_name", "0", FCVAR_NONE, "Includes groups when printing." ); + +CON_COMMAND( con_group_list, "Prints a list of all console groups." ) +{ + Msg( "============================================================\n" ); + for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++) + { + Msg( " # " ); + ConColorMsg( g_ConGroups[i].GetColor(), "%s", g_ConGroups[i].pszName ); + Msg( " - %s ", g_ConGroups[i].cvar->GetHelpText() ); + + //if (g_ConGroups[i].bDisabled) + // Msg("(DISABLED)"); + + Msg("\n"); + } + Msg( "============================================================\n" ); +} + +// TODO: Figure out how this can be done without server/client disparity issues +/* +CON_COMMAND( con_group_toggle, "Toggles a console group." ) +{ + const char *pszGroup = args.Arg( 1 ); + for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++) + { + if (V_stricmp(pszGroup, g_ConGroups[i].pszName) == 0) + { + Msg( "%s is now %s\n", g_ConGroups[i].pszName, g_ConGroups[i].bDisabled ? "enabled" : "disabled" ); + g_ConGroups[i].bDisabled = !g_ConGroups[i].bDisabled; + return; + } + } + + Msg( "No group named \"%s\"\n", pszGroup ); +} +*/ + +void CGMsg( int level, const char *pszGroup, const tchar* pMsg, ... ) +{ + // Return early if we're not at this level + if (!IsSpewActive("console", level)) + return; + + char string[ 2048 ]; + va_list argptr; + va_start( argptr, pMsg ); + Q_vsnprintf( string, sizeof(string), pMsg, argptr ); + va_end( argptr ); + + ConGroup_t *pGroup = FindConGroup( pszGroup ); + if (pGroup) + { + /*if (pGroup->bDisabled) + { + // Do nothing + } + else*/ if (con_group_include_name.GetBool()) + { + ConColorMsg( level, pGroup->GetColor(), "[%s] %s", pGroup->pszName, string ); + } + else + { + ConColorMsg( level, pGroup->GetColor(), string ); + } + } + else + DevMsg( level, string ); +} diff --git a/sp/src/tier1/tier1.vpc b/sp/src/tier1/tier1.vpc index 0387dac2..d7012f3e 100644 --- a/sp/src/tier1/tier1.vpc +++ b/sp/src/tier1/tier1.vpc @@ -76,6 +76,7 @@ $Project "tier1" $File "snappy.cpp" $File "snappy-sinksource.cpp" $File "snappy-stubs-internal.cpp" + $File "mapbase_con_groups.cpp" [$MAPBASE] } $Folder "Header Files" @@ -147,6 +148,7 @@ $Project "tier1" $File "$SRCDIR\public\tier1\utlsymbol.h" $File "$SRCDIR\public\tier1\utlsymbollarge.h" $File "$SRCDIR\public\tier1\utlvector.h" + $File "$SRCDIR\public\tier1\mapbase_con_groups.h" [$MAPBASE] $File "$SRCDIR\common\xbox\xboxstubs.h" [$WINDOWS] } } diff --git a/sp/src/utils/vbsp/map.cpp b/sp/src/utils/vbsp/map.cpp index 4e73ebc7..bd3604f3 100644 --- a/sp/src/utils/vbsp/map.cpp +++ b/sp/src/utils/vbsp/map.cpp @@ -18,6 +18,9 @@ #ifdef PARALLAX_CORRECTED_CUBEMAPS #include "matrixinvert.h" #endif +#ifdef MAPBASE_VSCRIPT +#include "vscript_vbsp.h" +#endif #ifdef VSVMFIO #include "VmfImport.h" @@ -53,6 +56,9 @@ extern qboolean onlyents; extern entity_t *g_ManifestWorldSpawn; char g_MainMapPath[ MAX_PATH ]; + +// This is done for the instancing fix +bool g_pParallaxObbsDone[MAX_MAP_CUBEMAPSAMPLES]; #endif @@ -2568,6 +2574,32 @@ void CMapFile::MergeEntities( entity_t *pInstanceEntity, CMapFile *Instance, Vec Q_snprintf( temp, sizeof( temp ), "%f", vOutNormal.z ); SetKeyValue( entity, "normal.z", temp );*/ } + +#ifdef MAPBASE + else if ( !strcmp( pEntity, "func_instance" ) ) + { + int iNumReplaces = 0; + for ( epair_t *epSubInstance = entity->epairs; epSubInstance != NULL; epSubInstance = epSubInstance->next ) + { + if ( strnicmp( epSubInstance->key, INSTANCE_VARIABLE_KEY, strlen( INSTANCE_VARIABLE_KEY ) ) == 0 ) + { + iNumReplaces++; + } + } + + // Merge this instance's keys + for ( epair_t *epInstance = pInstanceEntity->epairs; epInstance != NULL; epInstance = epInstance->next ) + { + if ( strnicmp( epInstance->key, INSTANCE_VARIABLE_KEY, strlen( INSTANCE_VARIABLE_KEY ) ) == 0 ) + { + iNumReplaces++; + char szKey[32]; + Q_snprintf(szKey, sizeof(szKey), "replace%i", iNumReplaces); + SetKeyValue( entity, szKey, epInstance->value ); + } + } + } +#endif } #ifdef MERGE_INSTANCE_DEBUG_INFO @@ -2766,6 +2798,23 @@ bool LoadMapFile( const char *pszFileName ) if ((eResult == ChunkFile_Ok) || (eResult == ChunkFile_EOF)) { +#ifdef MAPBASE_VSCRIPT + if ( g_pScriptVM ) + { + HSCRIPT hFunc = g_pScriptVM->LookupFunction( "OnMapLoaded" ); + if ( hFunc ) + { + // Use GetLoadingMap() + //g_pScriptVM->SetValue( "map", g_LoadingMap->GetScriptInstance() ); + + g_pScriptVM->Call( hFunc ); + g_pScriptVM->ReleaseFunction( hFunc ); + + //g_pScriptVM->ClearValue( "map" ); + } + } +#endif + // Update the overlay/side list(s). Overlay_UpdateSideLists( g_LoadingMap->m_StartMapOverlays ); OverlayTransition_UpdateSideLists( g_LoadingMap->m_StartMapWaterOverlays ); @@ -2781,31 +2830,31 @@ bool LoadMapFile( const char *pszFileName ) // 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++) + for (int i = 0; i < g_nCubemapSamples; i++) { - if (g_pParallaxObbStrs[i][0] != '\0') + if (g_pParallaxObbStrs[i][0] != '\0' && g_pParallaxObbsDone[i] == false) { Warning( "Testing OBB string %s\n", g_pParallaxObbStrs[i] ); + entity_t* obbEnt = NULL; 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) + if (stricmp( ValueForKey( &g_LoadingMap->entities[i2], "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'; - } + obbEnt = &g_LoadingMap->entities[i2]; + g_pParallaxObbStrs[i] = ValueForKey(obbEnt, "transformationmatrix"); + Warning( "Using OBB transformation matrix \"%s\"\n", g_pParallaxObbStrs[i] ); + g_pParallaxObbsDone[i] = true; break; } + + if (!obbEnt) + { + Warning( "Cannot find parallax obb \"%s\" (num_entities is %i)\n", g_pParallaxObbStrs[i], g_LoadingMap->num_entities ); + //g_pParallaxObbStrs[i][0] = '\0'; + } } } @@ -3320,6 +3369,133 @@ ChunkFileResult_t LoadSolidKeyCallback(const char *szKey, const char *szValue, m } +#ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +HSCRIPT CMapFile::GetScriptInstance() +{ + if (!m_hScriptInstance) + m_hScriptInstance = g_pScriptVM->RegisterInstance( this ); + + return m_hScriptInstance; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapFile::ScriptGetEntityKeyValues( int idx, HSCRIPT hKeyTable, HSCRIPT hValTable ) +{ + epair_t *curPair = entities[idx].epairs; + while (curPair) + { + g_pScriptVM->ArrayAppend( hKeyTable, curPair->key ); + g_pScriptVM->ArrayAppend( hValTable, curPair->value ); + + curPair = curPair->next; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CMapFile::ScriptAddSimpleEntityKV( HSCRIPT hKV ) +{ + if (num_entities == MAX_MAP_ENTITIES) + { + // Exits. + g_MapError.ReportError ("num_entities == MAX_MAP_ENTITIES"); + return -1; + } + + entity_t *mapent = NULL; + if (::num_entities > 0) + { + // We're not loading maps anymore. Add this to the central BSP + mapent = &::entities[num_entities]; + ::num_entities++; + } + else + { + mapent = &entities[num_entities]; + num_entities++; + } + + memset(mapent, 0, sizeof(*mapent)); + mapent->firstbrush = nummapbrushes; + mapent->numbrushes = 0; + //mapent->portalareas[0] = -1; + //mapent->portalareas[1] = -1; + + LoadEntity_t LoadEntity; + LoadEntity.pEntity = mapent; + + // No default flags/contents + LoadEntity.nBaseFlags = 0; + LoadEntity.nBaseContents = 0; + + int nIterator = -1; + ScriptVariant_t varKey, varValue; + char szValue[256]; + while ((nIterator = g_pScriptVM->GetKeyValue( hKV, nIterator, &varKey, &varValue )) != -1) + { + switch (varValue.m_type) + { + case FIELD_CSTRING: Q_strncpy( szValue, varValue.m_pszString, sizeof(szValue) ); break; + case FIELD_INTEGER: Q_snprintf( szValue, sizeof(szValue), "%i", varValue.m_int ); break; + case FIELD_FLOAT: Q_snprintf( szValue, sizeof(szValue), "%f", varValue.m_float ); break; + case FIELD_CHARACTER: Q_snprintf( szValue, sizeof( szValue ), "%c", varValue.m_char ); break; + case FIELD_BOOLEAN: Q_snprintf( szValue, sizeof(szValue), "%d", varValue.m_bool ); break; + case FIELD_VECTOR: Q_snprintf( szValue, sizeof(szValue), "%f %f %f", (*varValue.m_pVector).x, (*varValue.m_pVector).y, (*varValue.m_pVector).z ); break; + default: szValue[0] = '\0'; break; + } + + LoadEntityKeyCallback( varKey, szValue, &LoadEntity ); + + g_pScriptVM->ReleaseValue( varKey ); + g_pScriptVM->ReleaseValue( varValue ); + } + + return num_entities - 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CMapFile::ScriptAddInstance( const char *pszVMF, const Vector& vecOrigin, const QAngle& angAngles ) +{ + if (num_entities == MAX_MAP_ENTITIES) + { + // Exits. + g_MapError.ReportError ("num_entities == MAX_MAP_ENTITIES"); + return -1; + } + + entity_t *mapent = &entities[num_entities]; + num_entities++; + memset(mapent, 0, sizeof(*mapent)); + mapent->firstbrush = nummapbrushes; + mapent->numbrushes = 0; + //mapent->portalareas[0] = -1; + //mapent->portalareas[1] = -1; + + SetKeyValue( mapent, "classname", "func_instance" ); + + SetKeyValue( mapent, "file", pszVMF ); + SetKeyValue( mapent, "fixup_style", "2" ); // No fixup + + char szValue[256]; + Q_snprintf( szValue, sizeof(szValue), "%f %f %f", vecOrigin.x, vecOrigin.y, vecOrigin.z ); + SetKeyValue( mapent, "origin", szValue ); + + Q_snprintf( szValue, sizeof(szValue), "%f %f %f", angAngles.x, angAngles.y, angAngles.z ); + SetKeyValue( mapent, "angles", szValue ); + + return num_entities - 1; +} +#endif + + /* ================ TestExpandBrushes diff --git a/sp/src/utils/vbsp/vbsp.cpp b/sp/src/utils/vbsp/vbsp.cpp index 7afde5e0..11e1547c 100644 --- a/sp/src/utils/vbsp/vbsp.cpp +++ b/sp/src/utils/vbsp/vbsp.cpp @@ -20,6 +20,11 @@ #include "byteswap.h" #include "worldvertextransitionfixup.h" +#ifdef MAPBASE_VSCRIPT +#include "vscript/ivscript.h" +#include "vscript_vbsp.h" +#endif + extern float g_maxLightmapDimension; char source[1024]; @@ -66,6 +71,9 @@ bool g_bNoDefaultCubemaps = true; bool g_bSkyboxCubemaps = false; int g_iDefaultCubemapSize = 32; #endif +#ifdef MAPBASE_VSCRIPT +ScriptLanguage_t g_iScripting = SL_NONE; +#endif float g_defaultLuxelSize = DEFAULT_LUXEL_SIZE; float g_luxelScale = 1.0f; @@ -1185,6 +1193,72 @@ int RunVBSP( int argc, char **argv ) Msg( "Default cubemap size = %i\n", g_iDefaultCubemapSize ); i++; } +#endif +#ifdef MAPBASE_VSCRIPT + else if ( !Q_stricmp( argv[i], "-scripting" ) ) + { + const char *pszScriptLanguage = argv[i + 1]; + if( pszScriptLanguage[0] == '-') + { + // It's another command. Just use default + g_iScripting = SL_DEFAULT; + } + else + { + // Use a specific language + if( !Q_stricmp(pszScriptLanguage, "gamemonkey") ) + { + g_iScripting = SL_GAMEMONKEY; + } + else if( !Q_stricmp(pszScriptLanguage, "squirrel") ) + { + g_iScripting = SL_SQUIRREL; + } + else if( !Q_stricmp(pszScriptLanguage, "python") ) + { + g_iScripting = SL_PYTHON; + } + else if( !Q_stricmp(pszScriptLanguage, "lua") ) + { + g_iScripting = SL_LUA; + } + else + { + DevWarning("-server_script does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage ); + g_iScripting = SL_NONE; + } + i++; + } + } + else if ( !Q_stricmp( argv[i], "-doc" ) ) + { + // Only print the documentation + + if (g_iScripting) + { + scriptmanager = (IScriptManager*)Sys_GetFactoryThis()(VSCRIPT_INTERFACE_VERSION, NULL); + VScriptVBSPInit(); + + const char *pszArg1 = argv[i + 1]; + if (pszArg1[0] == '-') + { + // It's another command. Just use * + pszArg1 = "*"; + } + + char szCommand[512]; + _snprintf( szCommand, sizeof( szCommand ), "PrintHelp( \"%s\" );", pszArg1 ); + g_pScriptVM->Run( szCommand ); + } + else + { + Warning("Cannot print documentation without scripting enabled!\n"); + } + + DeleteCmdLine( argc, argv ); + CmdLib_Cleanup(); + CmdLib_Exit( 1 ); + } #endif else if (argv[i][0] == '-') { @@ -1319,6 +1393,15 @@ int RunVBSP( int argc, char **argv ) sprintf( materialPath, "%smaterials", gamedir ); InitMaterialSystem( materialPath, CmdLib_GetFileSystemFactory() ); Msg( "materialPath: %s\n", materialPath ); + +#ifdef MAPBASE_VSCRIPT + if (g_iScripting) + { + scriptmanager = (IScriptManager*)Sys_GetFactoryThis()(VSCRIPT_INTERFACE_VERSION, NULL); + + VScriptVBSPInit(); + } +#endif // delete portal and line files sprintf (path, "%s.prt", source); @@ -1442,6 +1525,9 @@ int RunVBSP( int argc, char **argv ) ReleasePakFileLumps(); DeleteMaterialReplacementKeys(); ShutdownMaterialSystem(); +#ifdef MAPBASE_VSCRIPT + VScriptVBSPTerm(); +#endif CmdLib_Cleanup(); return 0; } diff --git a/sp/src/utils/vbsp/vbsp.h b/sp/src/utils/vbsp/vbsp.h index e9a05611..3e9f44c0 100644 --- a/sp/src/utils/vbsp/vbsp.h +++ b/sp/src/utils/vbsp/vbsp.h @@ -19,6 +19,9 @@ #include "qfiles.h" #include "utilmatlib.h" #include "ChunkFile.h" +#ifdef MAPBASE_VSCRIPT +#include "vscript/ivscript.h" +#endif #ifdef WIN32 #pragma warning( disable: 4706 ) @@ -340,6 +343,32 @@ public: int m_StartMapOverlays; int m_StartMapWaterOverlays; + +#ifdef MAPBASE_VSCRIPT + HSCRIPT GetScriptInstance(); + + // VScript functions + ALLOW_SCRIPT_ACCESS(); +private: + + const Vector& GetMins() { return map_mins; } + const Vector& GetMaxs() { return map_maxs; } + + int GetNumMapBrushes() { return nummapbrushes; } + + const Vector& GetEntityOrigin(int idx) { return (idx < num_entities && idx >= 0) ? entities[idx].origin : vec3_origin; } + int GetEntityFirstBrush(int idx) { return (idx < num_entities && idx >= 0) ? entities[idx].firstbrush : 0; } + int GetEntityNumBrushes(int idx) { return (idx < num_entities && idx >= 0) ? entities[idx].numbrushes : 0; } + + void ScriptGetEntityKeyValues(int idx, HSCRIPT hKeyTable, HSCRIPT hValTable); + + int ScriptAddSimpleEntityKV(HSCRIPT hKV/*, const Vector& vecOrigin, int iFirstBrush, int iNumBrushes*/); + int ScriptAddInstance(const char *pszVMF, const Vector& vecOrigin, const QAngle& angAngles); + + int GetNumEntities() { return num_entities; } + + HSCRIPT m_hScriptInstance; +#endif }; extern CMapFile *g_MainMap; diff --git a/sp/src/utils/vbsp/vbsp.vpc b/sp/src/utils/vbsp/vbsp.vpc index d5a0c10e..ff52752c 100644 --- a/sp/src/utils/vbsp/vbsp.vpc +++ b/sp/src/utils/vbsp/vbsp.vpc @@ -16,6 +16,8 @@ $Configuration { $AdditionalIncludeDirectories "$BASE,..\common,..\vmpi" $PreprocessorDefinitions "$BASE;MACRO_MATHLIB;PROTECTED_THINGS_DISABLE" + + $PreprocessorDefinitions "$BASE;MAPBASE_VSCRIPT" [$MAPBASE_VSCRIPT] } $Linker @@ -66,6 +68,14 @@ $Project "Vbsp" $File "worldvertextransitionfixup.cpp" $File "writebsp.cpp" $File "$SRCDIR\public\zip_utils.cpp" + + $File "vscript_vbsp.cpp" [$MAPBASE_VSCRIPT] + $File "vscript_vbsp.h" [$MAPBASE_VSCRIPT] + $File "vscript_vbsp.nut" [$MAPBASE_VSCRIPT] + $File "vscript_funcs_vmfs.cpp" [$MAPBASE_VSCRIPT] + $File "vscript_funcs_vmfs.h" [$MAPBASE_VSCRIPT] + $File "vscript_funcs_vis.cpp" [$MAPBASE_VSCRIPT] + $File "vscript_funcs_vis.h" [$MAPBASE_VSCRIPT] $Folder "Common Files" { @@ -179,6 +189,7 @@ $Project "Vbsp" $Lib mathlib $Lib tier2 $Lib vtf + $Lib vscript [$MAPBASE_VSCRIPT] } $File "notes.txt" diff --git a/sp/src/utils/vbsp/vscript_funcs_vis.cpp b/sp/src/utils/vbsp/vscript_funcs_vis.cpp new file mode 100644 index 00000000..7a5fbfb6 --- /dev/null +++ b/sp/src/utils/vbsp/vscript_funcs_vis.cpp @@ -0,0 +1,29 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "tier1/KeyValues.h" +#include "tier1/fmtstr.h" + +#include "vbsp.h" +#include "map.h" +#include "fgdlib/fgdlib.h" + +#include "vscript_vbsp.h" +#include "vscript_funcs_vis.h" + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +// There are currently no vis-related functions, but it would be nice to have them in the future. + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void RegisterVisScriptFunctions() +{ + //ScriptRegisterFunction( g_pScriptVM, VMFKV_CreateBlank, "Creates a CScriptKeyValues instance with VMF formatting." ); +} diff --git a/sp/src/utils/vbsp/vscript_funcs_vis.h b/sp/src/utils/vbsp/vscript_funcs_vis.h new file mode 100644 index 00000000..906b7d7a --- /dev/null +++ b/sp/src/utils/vbsp/vscript_funcs_vis.h @@ -0,0 +1,16 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VSCRIPT_FUNCS_VIS +#define VSCRIPT_FUNCS_VIS +#ifdef _WIN32 +#pragma once +#endif + +void RegisterVisScriptFunctions(); + +#endif diff --git a/sp/src/utils/vbsp/vscript_funcs_vmfs.cpp b/sp/src/utils/vbsp/vscript_funcs_vmfs.cpp new file mode 100644 index 00000000..3894ddf3 --- /dev/null +++ b/sp/src/utils/vbsp/vscript_funcs_vmfs.cpp @@ -0,0 +1,156 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "tier1/KeyValues.h" +#include "tier1/fmtstr.h" + +#include "vbsp.h" +#include "map.h" +#include "fgdlib/fgdlib.h" + +#include "vscript_vbsp.h" +#include "vscript_funcs_vmfs.h" + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +static HSCRIPT VMFKV_CreateBlank() +{ + KeyValues *pKV = new KeyValues("VMF"); + + KeyValues *pWorld = pKV->FindKey( "world", true ); + if (pWorld) + { + pWorld->SetString( "classname", "worldspawn" ); + } + + return scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV, true ); +} + +static bool VMFKV_SaveToFile( const char *szFile, HSCRIPT hKV ) +{ + Warning( "Getting keyvalues from thing\n" ); + + KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV ); + if (!pKV) + return false; + + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + for (KeyValues *pSubKey = pKV->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey()) + { + pSubKey->RecursiveSaveToFile( buf, 0 ); + } + + char pszFullName[MAX_PATH]; + Q_ExtractFilePath( source, pszFullName, sizeof(pszFullName) ); + V_snprintf( pszFullName, sizeof(pszFullName), "%s/vscript_io/%s", pszFullName, szFile ); + + if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) + { + Warning( "Invalid file location : %s\n", szFile ); + buf.Purge(); + return false; + } + + int nSize = V_strlen(pszFullName) + 1; + char *pszDir = (char*)stackalloc(nSize); + V_memcpy( pszDir, pszFullName, nSize ); + V_StripFilename( pszDir ); + + //g_pFullFileSystem->RelativePathToFullPath( szFile, NULL, pszFullName, sizeof( pszFullName ) ); + Warning( "Full path is %s!\n", pszFullName ); + g_pFullFileSystem->CreateDirHierarchy( pszDir, NULL ); + bool res = g_pFullFileSystem->WriteFile( pszFullName, NULL, buf ); + buf.Purge(); + return res; +} + +static HSCRIPT VMFKV_LoadFromFile( const char *szFile ) +{ + char pszFullName[MAX_PATH]; + V_snprintf( pszFullName, sizeof(pszFullName), NULL, szFile ); + + if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) ) + { + DevWarning( 2, "Invalid file location : %s\n", szFile ); + return NULL; + } + + KeyValues *pKV = new KeyValues( szFile ); + if ( !pKV->LoadFromFile( g_pFullFileSystem, pszFullName, NULL ) ) + { + return NULL; + } + + HSCRIPT hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV, true ); // bAllowDestruct is supposed to automatically remove the involved KV + + return hScript; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +inline void ScriptVarsToKV( ScriptVariant_t &varKey, ScriptVariant_t &varValue, KeyValues *pKV ) +{ + switch (varValue.m_type) + { + case FIELD_CSTRING: pKV->SetString( varKey.m_pszString, varValue.m_pszString ); break; + case FIELD_INTEGER: pKV->SetInt( varKey.m_pszString, varValue.m_int ); break; + case FIELD_FLOAT: pKV->SetFloat( varKey.m_pszString, varValue.m_float ); break; + case FIELD_BOOLEAN: pKV->SetBool( varKey.m_pszString, varValue.m_bool ); break; + case FIELD_VECTOR: pKV->SetString( varKey.m_pszString, CFmtStr( "%f %f %f", varValue.m_pVector->x, varValue.m_pVector->y, varValue.m_pVector->z ) ); break; + } +} + +static HSCRIPT VMFKV_AddEntityFromTables( HSCRIPT hVMF, HSCRIPT hKV, HSCRIPT hIO ) +{ + KeyValues *pVMF = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hVMF ); + if (!pVMF) + return false; + + KeyValues *pEnt = pVMF->CreateNewKey(); + if (!pEnt) + return false; + + pEnt->SetName( "entity" ); + + int nIterator = -1; + ScriptVariant_t varKey, varValue; + while ((nIterator = g_pScriptVM->GetKeyValue( hKV, nIterator, &varKey, &varValue )) != -1) + { + ScriptVarsToKV( varKey, varValue, pEnt ); + + g_pScriptVM->ReleaseValue( varKey ); + g_pScriptVM->ReleaseValue( varValue ); + } + + KeyValues *pConnections = pEnt->FindKey( "connections", true ); + if (hIO && pConnections) + { + nIterator = -1; + while ((nIterator = g_pScriptVM->GetKeyValue( hIO, nIterator, &varKey, &varValue )) != -1) + { + ScriptVarsToKV( varKey, varValue, pEnt ); + + g_pScriptVM->ReleaseValue( varKey ); + g_pScriptVM->ReleaseValue( varValue ); + } + } + + return scriptmanager->CreateScriptKeyValues( g_pScriptVM, pEnt, false ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void RegisterVMFScriptFunctions() +{ + ScriptRegisterFunction( g_pScriptVM, VMFKV_CreateBlank, "Creates a CScriptKeyValues instance with VMF formatting." ); + ScriptRegisterFunction( g_pScriptVM, VMFKV_SaveToFile, "Saves a CScriptKeyValues instance with VMF formatting." ); + ScriptRegisterFunction( g_pScriptVM, VMFKV_LoadFromFile, "Loads a VMF as a CScriptKeyValues instance with VMF formatting." ); + ScriptRegisterFunction( g_pScriptVM, VMFKV_AddEntityFromTables, "Adds a VMF-formatted entity to a CScriptKeyValues instance." ); +} diff --git a/sp/src/utils/vbsp/vscript_funcs_vmfs.h b/sp/src/utils/vbsp/vscript_funcs_vmfs.h new file mode 100644 index 00000000..0b3237a7 --- /dev/null +++ b/sp/src/utils/vbsp/vscript_funcs_vmfs.h @@ -0,0 +1,16 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VSCRIPT_FUNCS_VMFS +#define VSCRIPT_FUNCS_VMFS +#ifdef _WIN32 +#pragma once +#endif + +void RegisterVMFScriptFunctions(); + +#endif diff --git a/sp/src/utils/vbsp/vscript_vbsp.cpp b/sp/src/utils/vbsp/vscript_vbsp.cpp new file mode 100644 index 00000000..91fa41f6 --- /dev/null +++ b/sp/src/utils/vbsp/vscript_vbsp.cpp @@ -0,0 +1,333 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: Mapbase's implementation of VScript in VBSP, allowing users to modify map compilation behavior with scripts. +// +// $NoKeywords: $ +//=============================================================================// + +#include "tier1/KeyValues.h" +#include "tier1/fmtstr.h" + +#include "vbsp.h" +#include "map.h" +#include "fgdlib/fgdlib.h" + +#include "vscript_vbsp.h" +#include "vscript_vbsp.nut" +#include "vscript_funcs_vmfs.h" +#include "vscript_funcs_vis.h" + +IScriptVM *g_pScriptVM; +IScriptManager *scriptmanager = NULL; + +extern ScriptLanguage_t g_iScripting; + +extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * ); + +// #define VMPROFILE 1 + +#ifdef VMPROFILE + +#define VMPROF_START float debugStartTime = Plat_FloatTime(); +#define VMPROF_SHOW( funcname, funcdesc ) DevMsg("***VSCRIPT PROFILE***: %s %s: %6.4f milliseconds\n", (##funcname), (##funcdesc), (Plat_FloatTime() - debugStartTime)*1000.0 ); + +#else // !VMPROFILE + +#define VMPROF_START +#define VMPROF_SHOW + +#endif // VMPROFILE + +// This is to ensure a dependency exists between the vscript library and the game DLLs +extern int vscript_token; +int vscript_token_hack = vscript_token; + +HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing ) +{ + if ( !g_pScriptVM ) + { + return NULL; + } + + static const char *pszExtensions[] = + { + "", // SL_NONE + ".gm", // SL_GAMEMONKEY + ".nut", // SL_SQUIRREL + ".lua", // SL_LUA + ".py", // SL_PYTHON + }; + + const char *pszVMExtension = pszExtensions[g_pScriptVM->GetLanguage()]; + const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' ); + if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 ) + { + Warning( "Script file type does not match VM type\n" ); + return NULL; + } + + CFmtStr scriptPath; + if ( pszIncomingExtension ) + { + scriptPath = pszScriptName; + } + else + { + scriptPath.sprintf( "%s%s", pszScriptName, pszVMExtension ); + } + + const char *pBase; + CUtlBuffer bufferScript; + + if ( g_pScriptVM->GetLanguage() == SL_PYTHON ) + { + // python auto-loads raw or precompiled modules - don't load data here + pBase = NULL; + } + else + { + /* + FileFindHandle_t handle = NULL; + const char *file = g_pFullFileSystem->FindFirst( "*", &handle ); + while (file) + { + Msg( "File in this directory: %s\n", file ); + file = g_pFullFileSystem->FindNext(handle); + } + + Msg( "File exists: %d\n", g_pFullFileSystem->FileExists( scriptPath ) ); + */ + + + bool bResult = g_pFullFileSystem->ReadFile( scriptPath, NULL, bufferScript ); + + if ( !bResult && bWarnMissing ) + { + Warning( "Script not found (%s) \n", scriptPath.operator const char *() ); + Assert( "Error running script" ); + } + + pBase = (const char *) bufferScript.Base(); + + if ( !pBase || !*pBase ) + { + return NULL; + } + } + + + const char *pszFilename = V_strrchr( scriptPath, '\\' ); + pszFilename++; + HSCRIPT hScript = g_pScriptVM->CompileScript( pBase, pszFilename ); + if ( !hScript ) + { + Warning( "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() ); + Assert( "Error running script" ); + } + return hScript; +} + +static int g_ScriptVBSPRunScriptDepth; + +bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing ) +{ + if ( !g_pScriptVM ) + { + return false; + } + + if ( !pszScriptName || !*pszScriptName ) + { + Warning( "Cannot run script: NULL script name\n" ); + return false; + } + + // Prevent infinite recursion in VM + if ( g_ScriptVBSPRunScriptDepth > 16 ) + { + Warning( "IncludeScript stack overflow\n" ); + return false; + } + + g_ScriptVBSPRunScriptDepth++; + HSCRIPT hScript = VScriptCompileScript( pszScriptName, bWarnMissing ); + bool bSuccess = false; + if ( hScript ) + { + bSuccess = ( g_pScriptVM->Run( hScript, hScope ) != SCRIPT_ERROR ); + if ( !bSuccess ) + { + Warning( "Error running script named %s\n", pszScriptName ); + Assert( "Error running script" ); + } + } + g_ScriptVBSPRunScriptDepth--; + return bSuccess; +} + +BEGIN_SCRIPTDESC_ROOT( CMapFile, "Map file" ) + + DEFINE_SCRIPTFUNC( GetMins, "Get the map's mins." ) + DEFINE_SCRIPTFUNC( GetMaxs, "Get the map's maxs." ) + + DEFINE_SCRIPTFUNC( GetEntityOrigin, "Get the origin of the entity with the specified index." ) + DEFINE_SCRIPTFUNC( GetEntityFirstBrush, "Get the first brush ID of the entity with the specified index." ) + DEFINE_SCRIPTFUNC( GetEntityNumBrushes, "Get the number of brushes in the entity with the specified index." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetEntityKeyValues, "GetEntityKeyValues", "Export an entity's keyvalues to two arrays." ) + + DEFINE_SCRIPTFUNC_NAMED( ScriptAddSimpleEntityKV, "AddSimpleEntityKV", "Add a simple entity from a keyvalue table." ) + DEFINE_SCRIPTFUNC_NAMED( ScriptAddInstance, "AddInstance", "Add an instance to the map." ) + + DEFINE_SCRIPTFUNC( GetNumEntities, "Get the number of entities in the map." ) + +END_SCRIPTDESC(); + +static const char *GetSource() +{ + return source; +} + +static const char *GetMapBase() +{ + return mapbase; +} + +static HSCRIPT GetMainMap() +{ + return g_MainMap ? g_MainMap->GetScriptInstance() : NULL; +} + +static HSCRIPT GetLoadingMap() +{ + return g_LoadingMap ? g_LoadingMap->GetScriptInstance() : NULL; +} + +static const char *DoUniqueString( const char *pszBase ) +{ + static char szBuf[512]; + g_pScriptVM->GenerateUniqueKey( pszBase, szBuf, ARRAYSIZE(szBuf) ); + return szBuf; +} + +bool DoIncludeScript( const char *pszScript, HSCRIPT hScope ) +{ + if ( !VScriptRunScript( pszScript, hScope, true ) ) + { + g_pScriptVM->RaiseException( CFmtStr( "Failed to include script \"%s\"", ( pszScript ) ? pszScript : "unknown" ) ); + return false; + } + return true; +} + +extern qboolean glview; +extern qboolean onlyents; +extern bool onlyprops; +extern qboolean noleaktest; +extern qboolean verboseentities; +extern qboolean g_bLowPriority; +extern bool g_bKeepStaleZip; +extern bool g_bNoDefaultCubemaps; +extern bool g_bSkyboxCubemaps; +extern int g_iDefaultCubemapSize; + +bool VScriptVBSPInit() +{ + VMPROF_START + + if( g_iScripting != SL_NONE && scriptmanager != NULL ) + { + if ( g_pScriptVM == NULL ) + g_pScriptVM = scriptmanager->CreateVM( g_iScripting ); + + if( g_pScriptVM ) + { + Log( "VSCRIPT VBSP: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() ); + + ScriptRegisterFunction( g_pScriptVM, GetSource, "Gets the base directory of the first map loaded." ); + ScriptRegisterFunction( g_pScriptVM, GetMapBase, "Gets the base name of the first map loaded." ); + ScriptRegisterFunction( g_pScriptVM, GetMainMap, "Gets the first map loaded." ); + ScriptRegisterFunction( g_pScriptVM, GetLoadingMap, "Gets the map which is currently loading (e.g. an instance)." ); + + ScriptRegisterFunction( g_pScriptVM, DoUniqueString, SCRIPT_ALIAS( "UniqueString", "Generate a string guaranteed to be unique across the life of the script VM, with an optional root string. Useful for adding data to tables when not sure what keys are already in use in that table." ) ); + ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" ); + + ScriptRegisterConstantNamed( g_pScriptVM, GameData::NAME_FIXUP_PREFIX, "NAME_FIXUP_PREFIX", "Prefix name fixup" ); + ScriptRegisterConstantNamed( g_pScriptVM, GameData::NAME_FIXUP_POSTFIX, "NAME_FIXUP_PREFIX", "Postfix name fixup" ); + ScriptRegisterConstantNamed( g_pScriptVM, GameData::NAME_FIXUP_NONE, "NAME_FIXUP_NONE", "No name fixup" ); + + ScriptRegisterConstant( g_pScriptVM, microvolume, "" ); + ScriptRegisterConstant( g_pScriptVM, noprune, "" ); + ScriptRegisterConstant( g_pScriptVM, glview, "" ); + ScriptRegisterConstant( g_pScriptVM, nodetail, "" ); + ScriptRegisterConstant( g_pScriptVM, fulldetail, "" ); + ScriptRegisterConstant( g_pScriptVM, onlyents, "" ); + ScriptRegisterConstant( g_pScriptVM, onlyprops, "" ); + ScriptRegisterConstant( g_pScriptVM, nomerge, "" ); + ScriptRegisterConstant( g_pScriptVM, nomergewater, "" ); + ScriptRegisterConstant( g_pScriptVM, nowater, "" ); + ScriptRegisterConstant( g_pScriptVM, nocsg, "" ); + ScriptRegisterConstant( g_pScriptVM, noweld, "" ); + ScriptRegisterConstant( g_pScriptVM, noshare, "" ); + ScriptRegisterConstant( g_pScriptVM, nosubdiv, "" ); + ScriptRegisterConstant( g_pScriptVM, notjunc, "" ); + ScriptRegisterConstant( g_pScriptVM, noopt, "" ); + ScriptRegisterConstant( g_pScriptVM, noleaktest, "" ); + ScriptRegisterConstant( g_pScriptVM, verboseentities, "" ); + ScriptRegisterConstant( g_pScriptVM, dumpcollide, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bLowPriority, "" ); + ScriptRegisterConstant( g_pScriptVM, g_DumpStaticProps, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bSkyVis, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bLightIfMissing, "" ); + ScriptRegisterConstant( g_pScriptVM, g_snapAxialPlanes, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bKeepStaleZip, "" ); + ScriptRegisterConstant( g_pScriptVM, g_NodrawTriggers, "" ); + ScriptRegisterConstant( g_pScriptVM, g_DisableWaterLighting, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bAllowDetailCracks, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bNoVirtualMesh, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bNoHiddenManifestMaps, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bNoDefaultCubemaps, "" ); + ScriptRegisterConstant( g_pScriptVM, g_bSkyboxCubemaps, "" ); + ScriptRegisterConstant( g_pScriptVM, g_iDefaultCubemapSize, "" ); + + if (g_iScripting == SL_SQUIRREL) + { + g_pScriptVM->Run( g_Script_vscript_vbsp ); + } + + RegisterVMFScriptFunctions(); + + // Run the map's script + char script[96]; + Q_snprintf( script, sizeof(script), "%s_vbsp", source ); + //Msg("VBSP script: \"%s\"\n", script); + VScriptRunScript( script, true ); + + VMPROF_SHOW( g_iScripting, "virtual machine startup" ); + + return true; + } + else + { + DevWarning("VM Did not start!\n"); + } + } + else + { + Log( "\nVSCRIPT: Scripting is disabled.\n" ); + } + g_pScriptVM = NULL; + return false; +} + +void VScriptVBSPTerm() +{ + if( g_pScriptVM != NULL ) + { + if( g_pScriptVM ) + { + scriptmanager->DestroyVM( g_pScriptVM ); + g_pScriptVM = NULL; + } + } +} diff --git a/sp/src/utils/vbsp/vscript_vbsp.h b/sp/src/utils/vbsp/vscript_vbsp.h new file mode 100644 index 00000000..1a6e390a --- /dev/null +++ b/sp/src/utils/vbsp/vscript_vbsp.h @@ -0,0 +1,27 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: Mapbase's implementation of VScript in VBSP, allowing users to modify map compilation behavior with scripts. +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VSCRIPT_VBSP_H +#define VSCRIPT_VBSP_H + +#include "vscript/ivscript.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +extern IScriptVM *g_pScriptVM; +extern IScriptManager *scriptmanager; + +HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing = false ); +bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing = false ); +inline bool VScriptRunScript( const char *pszScriptName, bool bWarnMissing = false ) { return VScriptRunScript( pszScriptName, NULL, bWarnMissing ); } + +bool VScriptVBSPInit(); +void VScriptVBSPTerm(); + +#endif // VSCRIPT_SERVER_H diff --git a/sp/src/utils/vbsp/vscript_vbsp.nut b/sp/src/utils/vbsp/vscript_vbsp.nut new file mode 100644 index 00000000..2aa99060 --- /dev/null +++ b/sp/src/utils/vbsp/vscript_vbsp.nut @@ -0,0 +1,52 @@ +static char g_Script_vscript_vbsp[] = R"vscript( +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +//=============================================================================// + +function UniqueString( string = "" ) +{ + return ::DoUniqueString( string.tostring() ); +} + +function __ReplaceClosures( script, scope ) +{ + if ( !scope ) + { + scope = getroottable(); + } + + local tempParent = { getroottable = function() { return null; } }; + local temp = { runscript = script }; + temp.set_delegate(tempParent); + + temp.runscript() + foreach( key,val in temp ) + { + if ( typeof(val) == "function" && key != "runscript" ) + { + printl( " Replacing " + key ); + scope[key] <- val; + } + } +} + +function IncludeScript( name, scope = null ) +{ + if ( !scope ) + { + scope = this; + } + return ::DoIncludeScript( name, scope ); +} + +// VBSP logs don't support ConColorMsg() +print <- Msg + +function printdoc( text ) +{ + return ::print(text + "\n"); +} + +)vscript"; \ No newline at end of file diff --git a/sp/src/vscript/vscript.cpp b/sp/src/vscript/vscript.cpp index 3d275009..af1570ad 100644 --- a/sp/src/vscript/vscript.cpp +++ b/sp/src/vscript/vscript.cpp @@ -10,6 +10,8 @@ #include "vscript/ivscript.h" +#include "vscript_bindings_base.h" + #include "tier1/tier1.h" IScriptVM* makeSquirrelVM(); @@ -41,7 +43,10 @@ public: delete pScriptVM; return nullptr; } - + + // Register base bindings for all VMs + RegisterBaseBindings( pScriptVM ); + return pScriptVM; } @@ -53,6 +58,25 @@ public: delete pScriptVM; } } + + // Mapbase moves CScriptKeyValues into the library so it could be used elsewhere + virtual HSCRIPT CreateScriptKeyValues( IScriptVM *pVM, KeyValues *pKV, bool bAllowDestruct ) override + { + CScriptKeyValues *pSKV = new CScriptKeyValues( pKV ); + HSCRIPT hSKV = pVM->RegisterInstance( pSKV, bAllowDestruct ); + return hSKV; + } + + virtual KeyValues *GetKeyValuesFromScriptKV( IScriptVM *pVM, HSCRIPT hSKV ) override + { + CScriptKeyValues *pSKV = (hSKV ? (CScriptKeyValues*)pVM->GetInstanceValue( hSKV, GetScriptDesc( (CScriptKeyValues*)NULL ) ) : nullptr); + if (pSKV) + { + return pSKV->m_pKeyValues; + } + + return nullptr; + } }; EXPOSE_SINGLE_INTERFACE(CScriptManager, IScriptManager, VSCRIPT_INTERFACE_VERSION); \ No newline at end of file diff --git a/sp/src/vscript/vscript.vpc b/sp/src/vscript/vscript.vpc index 36d3208e..425afb8a 100644 --- a/sp/src/vscript/vscript.vpc +++ b/sp/src/vscript/vscript.vpc @@ -24,6 +24,12 @@ $Project "VScript" $File "vscript.cpp" $File "vscript_squirrel.cpp" + $File "vscript_squirrel.nut" + + $File "vscript_bindings_base.cpp" + $File "vscript_bindings_base.h" + $File "vscript_bindings_math.cpp" + $File "vscript_bindings_math.h" $Folder "squirrel" { diff --git a/sp/src/vscript/vscript_bindings_base.cpp b/sp/src/vscript/vscript_bindings_base.cpp new file mode 100644 index 00000000..16d37606 --- /dev/null +++ b/sp/src/vscript/vscript_bindings_base.cpp @@ -0,0 +1,537 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: VScript functions, constants, etc. registered within the library itself. +// +// This is for things which don't have to depend on server/client and can be accessed +// from anywhere. +// +// $NoKeywords: $ +//=============================================================================// + +#include "vscript/ivscript.h" + +#include "tier1/tier1.h" +#include "tier1/fmtstr.h" + +#include +#include "icommandline.h" +#include "worldsize.h" +#include "bspflags.h" + +#include + +#include "vscript_bindings_base.h" +#include "vscript_bindings_math.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//============================================================================= +// +// Prints +// +//============================================================================= +static void ScriptMsg( const char *msg ) +{ + Msg( "%s", msg ); +} + +static void ScriptColorPrint( int r, int g, int b, const char *pszMsg ) +{ + const Color clr(r, g, b, 255); + ConColorMsg( clr, "%s", pszMsg ); +} + +static void ScriptColorPrintL( int r, int g, int b, const char *pszMsg ) +{ + const Color clr(r, g, b, 255); + ConColorMsg( clr, "%s\n", pszMsg ); +} + +//============================================================================= +// +// Convar Lookup +// +//============================================================================= +class CScriptConvarLookup +{ +public: + + float GetFloat( const char *pszConVar ) + { + ConVarRef cvar( pszConVar ); + return cvar.GetFloat(); + } + + int GetInt( const char *pszConVar ) + { + ConVarRef cvar( pszConVar ); + return cvar.GetInt(); + } + + bool GetBool( const char *pszConVar ) + { + ConVarRef cvar( pszConVar ); + return cvar.GetBool(); + } + + const char *GetStr( const char *pszConVar ) + { + ConVarRef cvar( pszConVar ); + return cvar.GetString(); + } + + const char *GetDefaultValue( const char *pszConVar ) + { + ConVarRef cvar( pszConVar ); + return cvar.GetDefault(); + } + + bool IsFlagSet( const char *pszConVar, int nFlags ) + { + ConVarRef cvar( pszConVar ); + return cvar.IsFlagSet( nFlags ); + } + + void SetFloat( const char *pszConVar, float value ) + { + SetValue( pszConVar, value ); + } + + void SetInt( const char *pszConVar, int value ) + { + SetValue( pszConVar, value ); + } + + void SetBool( const char *pszConVar, bool value ) + { + SetValue( pszConVar, value ); + } + + void SetStr( const char *pszConVar, const char *value ) + { + SetValue( pszConVar, value ); + } + + template + void SetValue( const char *pszConVar, T value ) + { + ConVarRef cvar( pszConVar ); + if (!cvar.IsValid()) + return; + + // FCVAR_NOT_CONNECTED can be used to protect specific convars from nefarious interference + if (cvar.IsFlagSet(FCVAR_NOT_CONNECTED)) + return; + + cvar.SetValue( value ); + } + +private: +} g_ScriptConvarLookup; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarLookup, "CConvars", SCRIPT_SINGLETON "Provides an interface for getting and setting convars." ) + DEFINE_SCRIPTFUNC( GetFloat, "Returns the convar as a float. May return null if no such convar." ) + DEFINE_SCRIPTFUNC( GetInt, "Returns the convar as an int. May return null if no such convar." ) + DEFINE_SCRIPTFUNC( GetBool, "Returns the convar as a bool. May return null if no such convar." ) + DEFINE_SCRIPTFUNC( GetStr, "Returns the convar as a string. May return null if no such convar." ) + DEFINE_SCRIPTFUNC( GetDefaultValue, "Returns the convar's default value as a string. May return null if no such convar." ) + DEFINE_SCRIPTFUNC( IsFlagSet, "Returns the convar's flags. May return null if no such convar." ) + DEFINE_SCRIPTFUNC( SetFloat, "Sets the value of the convar as a float." ) + DEFINE_SCRIPTFUNC( SetInt, "Sets the value of the convar as an int." ) + DEFINE_SCRIPTFUNC( SetBool, "Sets the value of the convar as a bool." ) + DEFINE_SCRIPTFUNC( SetStr, "Sets the value of the convar as a string." ) +END_SCRIPTDESC(); + +//============================================================================= +// +// Command Line +// +//============================================================================= +class CGlobalSys +{ +public: + const char* ScriptGetCommandLine() + { + return CommandLine()->GetCmdLine(); + } + + bool CommandLineCheck(const char* name) + { + return !!CommandLine()->FindParm(name); + } + + const char* CommandLineCheckStr(const char* name) + { + return CommandLine()->ParmValue(name); + } + + float CommandLineCheckFloat(const char* name) + { + return CommandLine()->ParmValue(name, 0); + } + + int CommandLineCheckInt(const char* name) + { + return CommandLine()->ParmValue(name, 0); + } +} g_ScriptGlobalSys; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CGlobalSys, "CGlobalSys", SCRIPT_SINGLETON "GlobalSys" ) + DEFINE_SCRIPTFUNC_NAMED( ScriptGetCommandLine, "GetCommandLine", "returns the command line" ) + DEFINE_SCRIPTFUNC( CommandLineCheck, "returns true if the command line param was used, otherwise false." ) + DEFINE_SCRIPTFUNC( CommandLineCheckStr, "returns the command line param as a string." ) + DEFINE_SCRIPTFUNC( CommandLineCheckFloat, "returns the command line param as a float." ) + DEFINE_SCRIPTFUNC( CommandLineCheckInt, "returns the command line param as an int." ) +END_SCRIPTDESC(); + +// ---------------------------------------------------------------------------- +// KeyValues access - CBaseEntity::ScriptGetKeyFromModel returns root KeyValues +// ---------------------------------------------------------------------------- +BEGIN_SCRIPTDESC_ROOT( CScriptKeyValues, "Wrapper class over KeyValues instance" ) + DEFINE_SCRIPT_CONSTRUCTOR() + DEFINE_SCRIPTFUNC_NAMED( ScriptFindKey, "FindKey", "Given a KeyValues object and a key name, find a KeyValues object associated with the key name" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetFirstSubKey, "GetFirstSubKey", "Given a KeyValues object, return the first sub key object" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetNextKey, "GetNextKey", "Given a KeyValues object, return the next key object in a sub key group" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueInt, "GetKeyInt", "Given a KeyValues object and a key name, return associated integer value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueFloat, "GetKeyFloat", "Given a KeyValues object and a key name, return associated float value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueBool, "GetKeyBool", "Given a KeyValues object and a key name, return associated bool value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueString, "GetKeyString", "Given a KeyValues object and a key name, return associated string value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptIsKeyValueEmpty, "IsKeyEmpty", "Given a KeyValues object and a key name, return true if key name has no value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptReleaseKeyValues, "ReleaseKeyValues", "Given a root KeyValues object, release its contents" ); + + DEFINE_SCRIPTFUNC( TableToSubKeys, "Converts a script table to KeyValues." ); + + DEFINE_SCRIPTFUNC_NAMED( ScriptGetName, "GetName", "Given a KeyValues object, return its name" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetInt, "GetInt", "Given a KeyValues object, return its own associated integer value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetFloat, "GetFloat", "Given a KeyValues object, return its own associated float value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetString, "GetString", "Given a KeyValues object, return its own associated string value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptGetBool, "GetBool", "Given a KeyValues object, return its own associated bool value" ); + + DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueInt, "SetKeyInt", "Given a KeyValues object and a key name, set associated integer value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueFloat, "SetKeyFloat", "Given a KeyValues object and a key name, set associated float value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueBool, "SetKeyBool", "Given a KeyValues object and a key name, set associated bool value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueString, "SetKeyString", "Given a KeyValues object and a key name, set associated string value" ); + + DEFINE_SCRIPTFUNC_NAMED( ScriptSetName, "SetName", "Given a KeyValues object, set its name" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetInt, "SetInt", "Given a KeyValues object, set its own associated integer value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetFloat, "SetFloat", "Given a KeyValues object, set its own associated float value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetBool, "SetBool", "Given a KeyValues object, set its own associated bool value" ); + DEFINE_SCRIPTFUNC_NAMED( ScriptSetString, "SetString", "Given a KeyValues object, set its own associated string value" ); +END_SCRIPTDESC(); + +HSCRIPT CScriptKeyValues::ScriptFindKey( const char *pszName ) +{ + KeyValues *pKeyValues = m_pKeyValues->FindKey(pszName); + if ( pKeyValues == NULL ) + return NULL; + + CScriptKeyValues *pScriptKey = new CScriptKeyValues( pKeyValues ); + + // UNDONE: who calls ReleaseInstance on this?? + HSCRIPT hScriptInstance = g_pScriptVM->RegisterInstance( pScriptKey ); + return hScriptInstance; +} + +HSCRIPT CScriptKeyValues::ScriptGetFirstSubKey( void ) +{ + KeyValues *pKeyValues = m_pKeyValues->GetFirstSubKey(); + if ( pKeyValues == NULL ) + return NULL; + + CScriptKeyValues *pScriptKey = new CScriptKeyValues( pKeyValues ); + + // UNDONE: who calls ReleaseInstance on this?? + HSCRIPT hScriptInstance = g_pScriptVM->RegisterInstance( pScriptKey ); + return hScriptInstance; +} + +HSCRIPT CScriptKeyValues::ScriptGetNextKey( void ) +{ + KeyValues *pKeyValues = m_pKeyValues->GetNextKey(); + if ( pKeyValues == NULL ) + return NULL; + + CScriptKeyValues *pScriptKey = new CScriptKeyValues( pKeyValues ); + + // UNDONE: who calls ReleaseInstance on this?? + HSCRIPT hScriptInstance = g_pScriptVM->RegisterInstance( pScriptKey ); + return hScriptInstance; +} + +int CScriptKeyValues::ScriptGetKeyValueInt( const char *pszName ) +{ + int i = m_pKeyValues->GetInt( pszName ); + return i; +} + +float CScriptKeyValues::ScriptGetKeyValueFloat( const char *pszName ) +{ + float f = m_pKeyValues->GetFloat( pszName ); + return f; +} + +const char *CScriptKeyValues::ScriptGetKeyValueString( const char *pszName ) +{ + const char *psz = m_pKeyValues->GetString( pszName ); + return psz; +} + +bool CScriptKeyValues::ScriptIsKeyValueEmpty( const char *pszName ) +{ + bool b = m_pKeyValues->IsEmpty( pszName ); + return b; +} + +bool CScriptKeyValues::ScriptGetKeyValueBool( const char *pszName ) +{ + bool b = m_pKeyValues->GetBool( pszName ); + return b; +} + +void CScriptKeyValues::ScriptReleaseKeyValues( ) +{ + m_pKeyValues->deleteThis(); + m_pKeyValues = NULL; +} + +void CScriptKeyValues::TableToSubKeys( HSCRIPT hTable ) +{ + int nIterator = -1; + ScriptVariant_t varKey, varValue; + while ((nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &varKey, &varValue )) != -1) + { + switch (varValue.m_type) + { + case FIELD_CSTRING: m_pKeyValues->SetString( varKey.m_pszString, varValue.m_pszString ); break; + case FIELD_INTEGER: m_pKeyValues->SetInt( varKey.m_pszString, varValue.m_int ); break; + case FIELD_FLOAT: m_pKeyValues->SetFloat( varKey.m_pszString, varValue.m_float ); break; + case FIELD_BOOLEAN: m_pKeyValues->SetBool( varKey.m_pszString, varValue.m_bool ); break; + case FIELD_VECTOR: m_pKeyValues->SetString( varKey.m_pszString, CFmtStr( "%f %f %f", varValue.m_pVector->x, varValue.m_pVector->y, varValue.m_pVector->z ) ); break; + } + + g_pScriptVM->ReleaseValue( varKey ); + g_pScriptVM->ReleaseValue( varValue ); + } +} + +const char *CScriptKeyValues::ScriptGetName() +{ + const char *psz = m_pKeyValues->GetName(); + return psz; +} + +int CScriptKeyValues::ScriptGetInt() +{ + int i = m_pKeyValues->GetInt(); + return i; +} + +float CScriptKeyValues::ScriptGetFloat() +{ + float f = m_pKeyValues->GetFloat(); + return f; +} + +const char *CScriptKeyValues::ScriptGetString() +{ + const char *psz = m_pKeyValues->GetString(); + return psz; +} + +bool CScriptKeyValues::ScriptGetBool() +{ + bool b = m_pKeyValues->GetBool(); + return b; +} + + +void CScriptKeyValues::ScriptSetKeyValueInt( const char *pszName, int iValue ) +{ + m_pKeyValues->SetInt( pszName, iValue ); +} + +void CScriptKeyValues::ScriptSetKeyValueFloat( const char *pszName, float flValue ) +{ + m_pKeyValues->SetFloat( pszName, flValue ); +} + +void CScriptKeyValues::ScriptSetKeyValueString( const char *pszName, const char *pszValue ) +{ + m_pKeyValues->SetString( pszName, pszValue ); +} + +void CScriptKeyValues::ScriptSetKeyValueBool( const char *pszName, bool bValue ) +{ + m_pKeyValues->SetBool( pszName, bValue ); +} + +void CScriptKeyValues::ScriptSetName( const char *pszValue ) +{ + m_pKeyValues->SetName( pszValue ); +} + +void CScriptKeyValues::ScriptSetInt( int iValue ) +{ + m_pKeyValues->SetInt( NULL, iValue ); +} + +void CScriptKeyValues::ScriptSetFloat( float flValue ) +{ + m_pKeyValues->SetFloat( NULL, flValue ); +} + +void CScriptKeyValues::ScriptSetString( const char *pszValue ) +{ + m_pKeyValues->SetString( NULL, pszValue ); +} + +void CScriptKeyValues::ScriptSetBool( bool bValue ) +{ + m_pKeyValues->SetBool( NULL, bValue ); +} + + +// constructors +CScriptKeyValues::CScriptKeyValues( KeyValues *pKeyValues = NULL ) +{ + if (pKeyValues == NULL) + { + m_pKeyValues = new KeyValues(""); + } + else + { + m_pKeyValues = pKeyValues; + } +} + +// destructor +CScriptKeyValues::~CScriptKeyValues( ) +{ + if (m_pKeyValues) + { + m_pKeyValues->deleteThis(); + } + m_pKeyValues = NULL; +} + +//============================================================================= +//============================================================================= + +void RegisterBaseBindings( IScriptVM *pVM ) +{ + ScriptRegisterFunctionNamed( pVM, ScriptMsg, "Msg", "" ); + ScriptRegisterFunctionNamed( pVM, ScriptColorPrint, "printc", "Version of print() which takes a color before the message." ); + ScriptRegisterFunctionNamed( pVM, ScriptColorPrintL, "printcl", "Version of printl() which takes a color before the message." ); + + ScriptRegisterFunction( pVM, GetCPUUsage, "Get CPU usage percentage." ); + + //----------------------------------------------------------------------------- + + pVM->RegisterInstance( &g_ScriptConvarLookup, "Convars" ); + pVM->RegisterInstance( &g_ScriptGlobalSys, "GlobalSys" ); + + //----------------------------------------------------------------------------- + + pVM->RegisterClass( GetScriptDescForClass( CScriptKeyValues ) ); + + //----------------------------------------------------------------------------- + + // + // Math/world + // + ScriptRegisterConstant( pVM, MAX_COORD_FLOAT, "Maximum float coordinate." ); + ScriptRegisterConstant( pVM, MAX_TRACE_LENGTH, "Maximum traceable distance (assumes cubic world and trace from one corner to opposite)." ); + + // + // Trace Contents/Masks + // + ScriptRegisterConstant( pVM, CONTENTS_EMPTY, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_SOLID, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_WINDOW, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_AUX, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_GRATE, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_SLIME, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_WATER, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_BLOCKLOS, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_OPAQUE, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_TESTFOGVOLUME, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_TEAM1, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_TEAM2, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_IGNORE_NODRAW_OPAQUE, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_MOVEABLE, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_AREAPORTAL, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_PLAYERCLIP, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_MONSTERCLIP, "Spatial content flags." ); + + ScriptRegisterConstant( pVM, CONTENTS_CURRENT_0, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_CURRENT_90, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_CURRENT_180, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_CURRENT_270, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_CURRENT_UP, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_CURRENT_DOWN, "Spatial content flags." ); + + ScriptRegisterConstant( pVM, CONTENTS_ORIGIN, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_MONSTER, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_DEBRIS, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_DETAIL, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_TRANSLUCENT, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_LADDER, "Spatial content flags." ); + ScriptRegisterConstant( pVM, CONTENTS_HITBOX, "Spatial content flags." ); + + ScriptRegisterConstant( pVM, LAST_VISIBLE_CONTENTS, "Contains last visible spatial content flags." ); + ScriptRegisterConstant( pVM, ALL_VISIBLE_CONTENTS, "Contains all visible spatial content flags." ); + + ScriptRegisterConstant( pVM, MASK_SOLID, "Spatial content mask representing solid objects (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_PLAYERSOLID, "Spatial content mask representing objects solid to the player, including player clips (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_NPCSOLID, "Spatial content mask representing objects solid to NPCs, including NPC clips (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_WATER, "Spatial content mask representing water and slime solids (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME)" ); + ScriptRegisterConstant( pVM, MASK_OPAQUE, "Spatial content mask representing objects which block lighting (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE)" ); + ScriptRegisterConstant( pVM, MASK_OPAQUE_AND_NPCS, "Spatial content mask equivalent to MASK_OPAQUE, but also including NPCs (MASK_OPAQUE|CONTENTS_MONSTER)" ); + ScriptRegisterConstant( pVM, MASK_BLOCKLOS, "Spatial content mask representing objects which block LOS for AI (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_BLOCKLOS)" ); + ScriptRegisterConstant( pVM, MASK_BLOCKLOS_AND_NPCS, "Spatial content mask equivalent to MASK_BLOCKLOS, but also including NPCs (MASK_BLOCKLOS|CONTENTS_MONSTER)" ); + ScriptRegisterConstant( pVM, MASK_VISIBLE, "Spatial content mask representing objects which block LOS for players (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE)" ); + ScriptRegisterConstant( pVM, MASK_VISIBLE_AND_NPCS, "Spatial content mask equivalent to MASK_VISIBLE, but also including NPCs (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE)" ); + ScriptRegisterConstant( pVM, MASK_SHOT, "Spatial content mask representing objects solid to bullets (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX)" ); + ScriptRegisterConstant( pVM, MASK_SHOT_HULL, "Spatial content mask representing objects solid to non-raycasted weapons, including grates (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_SHOT_PORTAL, "Spatial content mask equivalent to MASK_SHOT, but excluding debris and not using expensive hitbox calculations (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER)" ); + ScriptRegisterConstant( pVM, MASK_SOLID_BRUSHONLY, "Spatial content mask equivalent to MASK_SOLID, but without NPCs (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_PLAYERSOLID_BRUSHONLY, "Spatial content mask equivalent to MASK_PLAYERSOLID, but without NPCs (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_NPCSOLID_BRUSHONLY, "Spatial content mask equivalent to MASK_NPCSOLID, but without NPCs (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_NPCWORLDSTATIC, "Spatial content mask representing objects static to NPCs, used for nodegraph rebuilding (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)" ); + ScriptRegisterConstant( pVM, MASK_SPLITAREAPORTAL, "Spatial content mask representing objects which can split areaportals (CONTENTS_WATER|CONTENTS_SLIME)" ); + + // + // Misc. General + // + ScriptRegisterConstant( pVM, FCVAR_NONE, "Empty convar flag." ); + ScriptRegisterConstant( pVM, FCVAR_UNREGISTERED, "If this convar flag is set, it isn't added to linked list, etc." ); + ScriptRegisterConstant( pVM, FCVAR_DEVELOPMENTONLY, "If this convar flag is set, it's hidden in \"retail\" DLLs." ); + ScriptRegisterConstant( pVM, FCVAR_GAMEDLL, "This convar flag is defined in server DLL convars." ); + ScriptRegisterConstant( pVM, FCVAR_CLIENTDLL, "This convar flag is defined in client DLL convars." ); + ScriptRegisterConstant( pVM, FCVAR_HIDDEN, "If this convar flag is set, it doesn't appear in the console or any searching tools, but it can still be set." ); + ScriptRegisterConstant( pVM, FCVAR_PROTECTED, "This convar flag prevents convars with secure data (e.g. passwords) from sending full data to clients, only sending 1 if non-zero and 0 otherwise." ); + ScriptRegisterConstant( pVM, FCVAR_SPONLY, "If this convar flag is set, it can't be changed by clients connected to a multiplayer server." ); + ScriptRegisterConstant( pVM, FCVAR_ARCHIVE, "If this convar flag is set, its value will be saved when the game is exited." ); + ScriptRegisterConstant( pVM, FCVAR_NOTIFY, "If this convar flag is set, it will notify players when it is changed." ); + ScriptRegisterConstant( pVM, FCVAR_USERINFO, "If this convar flag is set, it will be marked as info which plays a part in how the server identifies a client." ); + ScriptRegisterConstant( pVM, FCVAR_PRINTABLEONLY, "If this convar flag is set, it cannot contain unprintable characters. Used for player name cvars, etc." ); + ScriptRegisterConstant( pVM, FCVAR_UNLOGGED, "If this convar flag is set, it will not log its changes if a log is being created." ); + ScriptRegisterConstant( pVM, FCVAR_NEVER_AS_STRING, "If this convar flag is set, it will never be printed as a string." ); + ScriptRegisterConstant( pVM, FCVAR_REPLICATED, "If this convar flag is set, it will enforce a serverside value on any clientside counterparts. (also known as FCAR_SERVER)" ); + ScriptRegisterConstant( pVM, FCVAR_DEMO, "If this convar flag is set, it will be recorded when starting a demo file." ); + ScriptRegisterConstant( pVM, FCVAR_DONTRECORD, "If this convar flag is set, it will NOT be recorded when starting a demo file." ); + ScriptRegisterConstant( pVM, FCVAR_RELOAD_MATERIALS, "If this convar flag is set, it will force a material reload when it changes." ); + ScriptRegisterConstant( pVM, FCVAR_RELOAD_TEXTURES, "If this convar flag is set, it will force a texture reload when it changes." ); + ScriptRegisterConstant( pVM, FCVAR_NOT_CONNECTED, "If this convar flag is set, it cannot be changed by a client connected to the server." ); + ScriptRegisterConstant( pVM, FCVAR_MATERIAL_SYSTEM_THREAD, "This convar flag indicates it's read from the material system thread." ); + ScriptRegisterConstant( pVM, FCVAR_ARCHIVE_XBOX, "If this convar flag is set, it will be archived on the Xbox config." ); + ScriptRegisterConstant( pVM, FCVAR_ACCESSIBLE_FROM_THREADS, "If this convar flag is set, it will be accessible from the material system thread." ); + ScriptRegisterConstant( pVM, FCVAR_SERVER_CAN_EXECUTE, "If this convar flag is set, the server will be allowed to execute it as a client command." ); + ScriptRegisterConstant( pVM, FCVAR_SERVER_CANNOT_QUERY, "If this convar flag is set, the server will not be allowed to query its value." ); + ScriptRegisterConstant( pVM, FCVAR_CLIENTCMD_CAN_EXECUTE, "If this convar flag is set, any client will be allowed to execute this command." ); + + //----------------------------------------------------------------------------- + + RegisterMathBaseBindings( pVM ); +} diff --git a/sp/src/vscript/vscript_bindings_base.h b/sp/src/vscript/vscript_bindings_base.h new file mode 100644 index 00000000..8496ac69 --- /dev/null +++ b/sp/src/vscript/vscript_bindings_base.h @@ -0,0 +1,62 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ================= +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VSCRIPT_BINDINGS_BASE +#define VSCRIPT_BINDINGS_BASE +#ifdef _WIN32 +#pragma once +#endif + +#include "vscript/ivscript.h" +#include "tier1/KeyValues.h" + +// ---------------------------------------------------------------------------- +// KeyValues access +// ---------------------------------------------------------------------------- +class CScriptKeyValues +{ +public: + CScriptKeyValues( KeyValues *pKeyValues ); + ~CScriptKeyValues( ); + + HSCRIPT ScriptFindKey( const char *pszName ); + HSCRIPT ScriptGetFirstSubKey( void ); + HSCRIPT ScriptGetNextKey( void ); + int ScriptGetKeyValueInt( const char *pszName ); + float ScriptGetKeyValueFloat( const char *pszName ); + const char *ScriptGetKeyValueString( const char *pszName ); + bool ScriptIsKeyValueEmpty( const char *pszName ); + bool ScriptGetKeyValueBool( const char *pszName ); + void ScriptReleaseKeyValues( ); + + // Functions below are new with Mapbase + void TableToSubKeys( HSCRIPT hTable ); + + const char *ScriptGetName(); + int ScriptGetInt(); + float ScriptGetFloat(); + const char *ScriptGetString(); + bool ScriptGetBool(); + + void ScriptSetKeyValueInt( const char *pszName, int iValue ); + void ScriptSetKeyValueFloat( const char *pszName, float flValue ); + void ScriptSetKeyValueString( const char *pszName, const char *pszValue ); + void ScriptSetKeyValueBool( const char *pszName, bool bValue ); + void ScriptSetName( const char *pszValue ); + void ScriptSetInt( int iValue ); + void ScriptSetFloat( float flValue ); + void ScriptSetString( const char *pszValue ); + void ScriptSetBool( bool bValue ); + + KeyValues *GetKeyValues() { return m_pKeyValues; } + + KeyValues *m_pKeyValues; // actual KeyValue entity +}; + +void RegisterBaseBindings( IScriptVM *pVM ); + +#endif diff --git a/sp/src/game/shared/mapbase/vscript_funcs_math.cpp b/sp/src/vscript/vscript_bindings_math.cpp similarity index 61% rename from sp/src/game/shared/mapbase/vscript_funcs_math.cpp rename to sp/src/vscript/vscript_bindings_math.cpp index d214a301..312e053d 100644 --- a/sp/src/game/shared/mapbase/vscript_funcs_math.cpp +++ b/sp/src/vscript/vscript_bindings_math.cpp @@ -1,13 +1,23 @@ //========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// // -// Purpose: Shared VScript math functions. +// Purpose: VScript functions, constants, etc. registered within the library itself. +// +// This is for things which don't have to depend on server/client and can be accessed +// from anywhere. // // $NoKeywords: $ //=============================================================================// -#include "cbase.h" +#include "vscript/ivscript.h" -#include "vscript_funcs_math.h" +#include "tier1/tier1.h" + +#include +#include "worldsize.h" + +#include + +#include "vscript_bindings_math.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -221,7 +231,6 @@ bool CScriptQuaternionInstanceHelper::Set( void *p, const char *pszKey, ScriptVa ScriptVariant_t *CScriptQuaternionInstanceHelper::Add( void *p, ScriptVariant_t &variant ) { Quaternion *pQuat = ((Quaternion *)p); - DevMsg("Adding %i is an interesting choice\n", variant.m_int); float flAdd; variant.AssignTo( &flAdd ); @@ -376,77 +385,67 @@ float ScriptCalcDistanceToLineSegment( const Vector &point, const Vector &vLineA return CalcDistanceToLineSegment( point, vLineA, vLineB ); } -#ifndef CLIENT_DLL -const Vector& ScriptPredictedPosition( HSCRIPT hTarget, float flTimeDelta ) +void RegisterMathBaseBindings( IScriptVM *pVM ) { - static Vector predicted; - UTIL_PredictedPosition( ToEnt(hTarget), flTimeDelta, &predicted ); - return predicted; -} -#endif + ScriptRegisterConstantNamed( pVM, ((float)(180.f / M_PI_F)), "RAD2DEG", "" ); + ScriptRegisterConstantNamed( pVM, ((float)(M_PI_F / 180.f)), "DEG2RAD", "" ); -void RegisterMathScriptFunctions() -{ - ScriptRegisterFunction( g_pScriptVM, RandomFloat, "Generate a random floating point number within a range, inclusive." ); - ScriptRegisterFunction( g_pScriptVM, RandomInt, "Generate a random integer within a range, inclusive." ); - //ScriptRegisterFunction( g_pScriptVM, Approach, "Returns a value which approaches the target value from the input value with the specified speed." ); - ScriptRegisterFunction( g_pScriptVM, ApproachAngle, "Returns an angle which approaches the target angle from the input angle with the specified speed." ); - ScriptRegisterFunction( g_pScriptVM, AngleDiff, "Returns the degrees difference between two yaw angles." ); - //ScriptRegisterFunction( g_pScriptVM, AngleDistance, "Returns the distance between two angles." ); - ScriptRegisterFunction( g_pScriptVM, AngleNormalize, "Clamps an angle to be in between -360 and 360." ); - ScriptRegisterFunction( g_pScriptVM, AngleNormalizePositive, "Clamps an angle to be in between 0 and 360." ); - ScriptRegisterFunction( g_pScriptVM, AnglesAreEqual, "Checks if two angles are equal based on a given tolerance value." ); + ScriptRegisterFunction( pVM, RandomFloat, "Generate a random floating point number within a range, inclusive." ); + ScriptRegisterFunction( pVM, RandomInt, "Generate a random integer within a range, inclusive." ); + //ScriptRegisterFunction( pVM, Approach, "Returns a value which approaches the target value from the input value with the specified speed." ); + ScriptRegisterFunction( pVM, ApproachAngle, "Returns an angle which approaches the target angle from the input angle with the specified speed." ); + ScriptRegisterFunction( pVM, AngleDiff, "Returns the degrees difference between two yaw angles." ); + //ScriptRegisterFunction( pVM, AngleDistance, "Returns the distance between two angles." ); + ScriptRegisterFunction( pVM, AngleNormalize, "Clamps an angle to be in between -360 and 360." ); + ScriptRegisterFunction( pVM, AngleNormalizePositive, "Clamps an angle to be in between 0 and 360." ); + ScriptRegisterFunction( pVM, AnglesAreEqual, "Checks if two angles are equal based on a given tolerance value." ); // // matrix3x4_t // - g_pScriptVM->RegisterClass( GetScriptDescForClass( matrix3x4_t ) ); + pVM->RegisterClass( GetScriptDescForClass( matrix3x4_t ) ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptFreeMatrixInstance, "FreeMatrixInstance", "Frees an allocated matrix instance." ); + ScriptRegisterFunctionNamed( pVM, ScriptFreeMatrixInstance, "FreeMatrixInstance", "Frees an allocated matrix instance." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptConcatTransforms, "ConcatTransforms", "Concatenates two transformation matrices into another matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatrixCopy, "MatrixCopy", "Copies a matrix to another matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatrixInvert, "MatrixInvert", "Inverts a matrix and copies the result to another matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatricesAreEqual, "MatricesAreEqual", "Checks if two matrices are equal." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatrixGetColumn, "MatrixGetColumn", "Gets the column of a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatrixSetColumn, "MatrixSetColumn", "Sets the column of a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatrixAngles, "MatrixAngles", "Gets the angles and position of a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptAngleMatrix, "AngleMatrix", "Sets the angles and position of a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptAngleIMatrix, "AngleIMatrix", "Sets the inverted angles and position of a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptSetIdentityMatrix, "SetIdentityMatrix", "Turns a matrix into an identity matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptSetScaleMatrix, "SetScaleMatrix", "Scales a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptConcatTransforms, "ConcatTransforms", "Concatenates two transformation matrices into another matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatrixCopy, "MatrixCopy", "Copies a matrix to another matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatrixInvert, "MatrixInvert", "Inverts a matrix and copies the result to another matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatricesAreEqual, "MatricesAreEqual", "Checks if two matrices are equal." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatrixGetColumn, "MatrixGetColumn", "Gets the column of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatrixSetColumn, "MatrixSetColumn", "Sets the column of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatrixAngles, "MatrixAngles", "Gets the angles and position of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptAngleMatrix, "AngleMatrix", "Sets the angles and position of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptAngleIMatrix, "AngleIMatrix", "Sets the inverted angles and position of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptSetIdentityMatrix, "SetIdentityMatrix", "Turns a matrix into an identity matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptSetScaleMatrix, "SetScaleMatrix", "Scales a matrix." ); // // Quaternion // - g_pScriptVM->RegisterClass( GetScriptDescForClass( Quaternion ) ); + pVM->RegisterClass( GetScriptDescForClass( Quaternion ) ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptFreeQuaternionInstance, "FreeQuaternionInstance", "Frees an allocated quaternion instance." ); + ScriptRegisterFunctionNamed( pVM, ScriptFreeQuaternionInstance, "FreeQuaternionInstance", "Frees an allocated quaternion instance." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptQuaternionAdd, "QuaternionAdd", "Adds two quaternions together into another quaternion." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptMatrixQuaternion, "MatrixQuaternion", "Converts a matrix to a quaternion." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptQuaternionMatrix, "QuaternionMatrix", "Converts a quaternion to a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptQuaternionAngles, "QuaternionAngles", "Converts a quaternion to angles." ); + ScriptRegisterFunctionNamed( pVM, ScriptQuaternionAdd, "QuaternionAdd", "Adds two quaternions together into another quaternion." ); + ScriptRegisterFunctionNamed( pVM, ScriptMatrixQuaternion, "MatrixQuaternion", "Converts a matrix to a quaternion." ); + ScriptRegisterFunctionNamed( pVM, ScriptQuaternionMatrix, "QuaternionMatrix", "Converts a quaternion to a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptQuaternionAngles, "QuaternionAngles", "Converts a quaternion to angles." ); // // Misc. Vector/QAngle functions // - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptAngleVectors, "AngleVectors", "Turns an angle into a direction vector." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptVectorAngles, "VectorAngles", "Turns a direction vector into an angle." ); + ScriptRegisterFunctionNamed( pVM, ScriptAngleVectors, "AngleVectors", "Turns an angle into a direction vector." ); + ScriptRegisterFunctionNamed( pVM, ScriptVectorAngles, "VectorAngles", "Turns a direction vector into an angle." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptVectorRotate, "VectorRotate", "Rotates a vector with a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptVectorIRotate, "VectorIRotate", "Rotates a vector with the inverse of a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptVectorTransform, "VectorTransform", "Transforms a vector with a matrix." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptVectorITransform, "VectorITransform", "Transforms a vector with the inverse of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptVectorRotate, "VectorRotate", "Rotates a vector with a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptVectorIRotate, "VectorIRotate", "Rotates a vector with the inverse of a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptVectorTransform, "VectorTransform", "Transforms a vector with a matrix." ); + ScriptRegisterFunctionNamed( pVM, ScriptVectorITransform, "VectorITransform", "Transforms a vector with the inverse of a matrix." ); - ScriptRegisterFunction( g_pScriptVM, CalcSqrDistanceToAABB, "Returns the squared distance to a bounding box." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalcClosestPointOnAABB, "CalcClosestPointOnAABB", "Returns the closest point on a bounding box." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalcDistanceToLine, "CalcDistanceToLine", "Returns the distance to a line." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalcClosestPointOnLine, "CalcClosestPointOnLine", "Returns the closest point on a line." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalcDistanceToLineSegment, "CalcDistanceToLineSegment", "Returns the distance to a line segment." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalcClosestPointOnLineSegment, "CalcClosestPointOnLineSegment", "Returns the closest point on a line segment." ); - -#ifndef CLIENT_DLL - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPredictedPosition, "PredictedPosition", "Predicts what an entity's position will be in a given amount of time." ); -#endif + ScriptRegisterFunction( pVM, CalcSqrDistanceToAABB, "Returns the squared distance to a bounding box." ); + ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnAABB, "CalcClosestPointOnAABB", "Returns the closest point on a bounding box." ); + ScriptRegisterFunctionNamed( pVM, ScriptCalcDistanceToLine, "CalcDistanceToLine", "Returns the distance to a line." ); + ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnLine, "CalcClosestPointOnLine", "Returns the closest point on a line." ); + ScriptRegisterFunctionNamed( pVM, ScriptCalcDistanceToLineSegment, "CalcDistanceToLineSegment", "Returns the distance to a line segment." ); + ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnLineSegment, "CalcClosestPointOnLineSegment", "Returns the closest point on a line segment." ); } diff --git a/sp/src/game/shared/mapbase/vscript_funcs_math.h b/sp/src/vscript/vscript_bindings_math.h similarity index 85% rename from sp/src/game/shared/mapbase/vscript_funcs_math.h rename to sp/src/vscript/vscript_bindings_math.h index 3d02ce75..c2d960b5 100644 --- a/sp/src/game/shared/mapbase/vscript_funcs_math.h +++ b/sp/src/vscript/vscript_bindings_math.h @@ -5,22 +5,22 @@ // $NoKeywords: $ //============================================================================= -#ifndef VSCRIPT_FUNCS_MATH -#define VSCRIPT_FUNCS_MATH +#ifndef VSCRIPT_BINDINGS_MATH +#define VSCRIPT_BINDINGS_MATH #ifdef _WIN32 #pragma once #endif +void RegisterMathBaseBindings( IScriptVM *pVM ); + +// Some base bindings require VM functions +extern IScriptVM *g_pScriptVM; + //----------------------------------------------------------------------------- // Exposes matrix3x4_t to VScript //----------------------------------------------------------------------------- inline matrix3x4_t *ToMatrix3x4( HSCRIPT hMat ) { return HScriptToClass( hMat ); } -static HSCRIPT ScriptCreateMatrixInstance( matrix3x4_t &matrix ) -{ - return g_pScriptVM->RegisterInstance( &matrix ); -} - static void ScriptFreeMatrixInstance( HSCRIPT hMat ) { matrix3x4_t *smatrix = HScriptToClass( hMat ); @@ -49,11 +49,6 @@ class CScriptQuaternionInstanceHelper : public IScriptInstanceHelper inline Quaternion *ToQuaternion( HSCRIPT hQuat ) { return HScriptToClass( hQuat ); } -static HSCRIPT ScriptCreateQuaternionInstance( Quaternion &quat ) -{ - return g_pScriptVM->RegisterInstance( &quat ); -} - static void ScriptFreeQuaternionInstance( HSCRIPT hQuat ) { Quaternion *squat = HScriptToClass( hQuat ); diff --git a/sp/src/vscript/vscript_squirrel.cpp b/sp/src/vscript/vscript_squirrel.cpp index 7e1d0d5d..9acf3b01 100644 --- a/sp/src/vscript/vscript_squirrel.cpp +++ b/sp/src/vscript/vscript_squirrel.cpp @@ -33,6 +33,9 @@ #include "color.h" #include "tier1/utlbuffer.h" +#include "tier1/mapbase_con_groups.h" + +#include "vscript_squirrel.nut" #include @@ -1365,8 +1368,6 @@ struct SquirrelSafeCheck }; -#define CON_COLOR_VSCRIPT 80,186,255,255 - void printfunc(HSQUIRRELVM SQ_UNUSED_ARG(v), const SQChar* format, ...) { va_list args; @@ -1374,7 +1375,7 @@ void printfunc(HSQUIRRELVM SQ_UNUSED_ARG(v), const SQChar* format, ...) va_start(args, format); V_vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); - ConColorMsg(Color(CON_COLOR_VSCRIPT), "%s", buffer); + CGMsg(0, CON_GROUP_VSCRIPT_PRINT, "%s", buffer); } void errorfunc(HSQUIRRELVM SQ_UNUSED_ARG(v), const SQChar* format, ...) @@ -1399,6 +1400,7 @@ const char * ScriptDataTypeToName(ScriptDataType_t datatype) case FIELD_BOOLEAN: return "bool"; case FIELD_CHARACTER: return "char"; case FIELD_HSCRIPT: return "handle"; + case FIELD_VARIANT: return "variant"; default: return ""; } } @@ -1528,6 +1530,53 @@ void RegisterConstantDocumentation( HSQUIRRELVM vm, const ScriptConstantBinding_ sq_pop(vm, 1); } +void RegisterHookDocumentation(HSQUIRRELVM vm, const ScriptHook_t* pHook, const ScriptFuncDescriptor_t& pFuncDesc, ScriptClassDesc_t* pClassDesc = nullptr) +{ + SquirrelSafeCheck safeCheck(vm); + + if (pFuncDesc.m_pszDescription && pFuncDesc.m_pszDescription[0] == SCRIPT_HIDE[0]) + return; + + char name[256] = ""; + + if (pClassDesc) + { + V_strcat_safe(name, pClassDesc->m_pszScriptName); + V_strcat_safe(name, " -> "); + } + + V_strcat_safe(name, pFuncDesc.m_pszScriptName); + + + char signature[256] = ""; + V_snprintf(signature, sizeof(signature), "%s %s(", ScriptDataTypeToName(pFuncDesc.m_ReturnType), name); + + for (int i = 0; i < pFuncDesc.m_Parameters.Count(); ++i) + { + if (i != 0) + V_strcat_safe(signature, ", "); + + V_strcat_safe(signature, ScriptDataTypeToName(pFuncDesc.m_Parameters[i])); + V_strcat_safe(signature, " ["); + V_strcat_safe(signature, pHook->m_pszParameterNames[i]); + V_strcat_safe(signature, "]"); + } + + V_strcat_safe(signature, ")"); + + // RegisterHookHelp(name, signature, description) + sq_pushroottable(vm); + sq_pushstring(vm, "RegisterHookHelp", -1); + sq_get(vm, -2); + sq_remove(vm, -2); + sq_pushroottable(vm); + sq_pushstring(vm, name, -1); + sq_pushstring(vm, signature, -1); + sq_pushstring(vm, pFuncDesc.m_pszDescription ? pFuncDesc.m_pszDescription : "", -1); + sq_call(vm, 4, SQFalse, SQFalse); + sq_pop(vm, 1); +} + bool SquirrelVM::Init() { @@ -1598,269 +1647,7 @@ bool SquirrelVM::Init() sq_pop(vm_, 1); } - if (Run( - R"script( - Warning <- error; - - function clamp(val,min,max) - { - if ( max < min ) - return max; - else if( val < min ) - return min; - else if( val > max ) - return max; - else - return val; - } - - function max(a,b) return a > b ? a : b - - function min(a,b) return a < b ? a : b - - function RemapVal(val, A, B, C, D) - { - if ( A == B ) - return val >= B ? D : C; - return C + (D - C) * (val - A) / (B - A); - } - - function RemapValClamped(val, A, B, C, D) - { - if ( A == B ) - return val >= B ? D : C; - local cVal = (val - A) / (B - A); - cVal = (cVal < 0.0) ? 0.0 : (1.0 < cVal) ? 1.0 : cVal; - return C + (D - C) * cVal; - } - - function Approach( target, value, speed ) - { - local delta = target - value - - if( delta > speed ) - value += speed - else if( delta < (-speed) ) - value -= speed - else - value = target - - return value - } - - function AngleDistance( next, cur ) - { - local delta = next - cur - - if ( delta < (-180.0) ) - delta += 360.0 - else if ( delta > 180.0 ) - delta -= 360.0 - - return delta - } - - function printl( text ) - { - return ::print(text + "\n"); - } - - class CSimpleCallChainer - { - constructor(prefixString, scopeForThis, exactMatch) - { - prefix = prefixString; - scope = scopeForThis; - chain = []; - scope["Dispatch" + prefixString] <- Call.bindenv(this); - } - - function PostScriptExecute() - { - local func; - try { - func = scope[prefix]; - } catch(e) { - return; - } - if (typeof(func) != "function") - return; - chain.push(func); - } - - function Call() - { - foreach (func in chain) - { - func.pcall(scope); - } - } - - prefix = null; - scope = null; - chain = null; - } - - DocumentedFuncs <- {} - DocumentedClasses <- {} - DocumentedEnums <- {} - DocumentedConsts <- {} - - function ModForAlias(name, signature, description) - { - // This is an alias function, could use split() if we could guarantee - // that ':' would not occur elsewhere in the description and Squirrel had - // a convience join() function -- It has split() - local colon = description.find(":"); - if (colon == null) - colon = description.len(); - local alias = description.slice(1, colon); - description = description.slice(colon + 1); - name = alias; - signature = null; - } - - function RegisterHelp(name, signature, description) - { - if (description.len() && description[0] == '#') - { - ModForAlias(name, signature, description) - } - DocumentedFuncs[name] <- [signature, description]; - } - - function RegisterClassHelp(name, baseclass, description) - { - DocumentedClasses[name] <- [baseclass, description]; - } - - function RegisterEnumHelp(name, description) - { - DocumentedEnums[name] <- description; - } - - function RegisterConstHelp(name, signature, description) - { - if (description.len() && description[0] == '#') - { - ModForAlias(name, signature, description) - } - DocumentedConsts[name] <- [signature, description]; - } - - function PrintClass(name, doc) - { - printl("====================================="); - printl("Class: " + name); - printl("Base: " + doc[0]); - if (doc[1].len()) - printl("Description: " + doc[1]); - printl("====================================="); - print("\n"); - } - - function PrintFunc(name, doc) - { - printl("Function: " + name); - if (doc[0] == null) - { - // Is an aliased function - print("Signature: function " + name + "("); - foreach(k,v in this[name].getinfos().parameters) - { - if (k == 0 && v == "this") continue; - if (k > 1) print(", "); - print(v); - } - printl(")"); - } - else - { - printl("Signature: " + doc[0]); - } - if (doc[1].len()) - printl("Description: " + doc[1]); - print("\n"); - } - - function PrintEnum(name, doc) - { - printl("====================================="); - printl("Enum: " + name); - if (doc.len()) - printl("Description: " + doc); - printl("====================================="); - print("\n"); - } - - function PrintConst(name, doc) - { - printl("Constant: " + name); - if (doc[0] == null) - { - // Is an aliased function - print("Signature: function " + name + "("); - foreach(k,v in this[name].getinfos().parameters) - { - if (k == 0 && v == "this") continue; - if (k > 1) print(", "); - print(v); - } - printl(")"); - } - else - { - printl("Value: " + doc[0]); - } - if (doc[1].len()) - printl("Description: " + doc[1]); - print("\n"); - } - - function PrintHelp(pattern = "*") - { - local foundMatches = false; - foreach(name, doc in DocumentedClasses) - { - if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) - { - foundMatches = true; - PrintClass(name, doc) - } - } - - foreach(name, doc in DocumentedFuncs) - { - if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) - { - foundMatches = true; - PrintFunc(name, doc) - } - } - - foreach(name, doc in DocumentedEnums) - { - if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) - { - foundMatches = true; - PrintEnum(name, doc) - } - } - - foreach(name, doc in DocumentedConsts) - { - if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) - { - foundMatches = true; - PrintConst(name, doc) - } - } - - if (!foundMatches) - printl("Pattern " + pattern + " not found"); - } - - )script") != SCRIPT_DONE) + if (Run(g_Script_vscript_squirrel) != SCRIPT_DONE) { this->Shutdown(); return false; @@ -2297,6 +2084,13 @@ bool SquirrelVM::RegisterClass(ScriptClassDesc_t* pClassDesc) RegisterDocumentation(vm_, scriptFunction.m_desc, pClassDesc); } + for (int i = 0; i < pClassDesc->m_Hooks.Count(); ++i) + { + auto& scriptHook = pClassDesc->m_Hooks[i]; + + RegisterHookDocumentation(vm_, scriptHook, scriptHook->m_desc, pClassDesc); + } + sq_pushstring(vm_, pClassDesc->m_pszScriptName, -1); sq_push(vm_, -2); diff --git a/sp/src/vscript/vscript_squirrel.nut b/sp/src/vscript/vscript_squirrel.nut new file mode 100644 index 00000000..e140f4d5 --- /dev/null +++ b/sp/src/vscript/vscript_squirrel.nut @@ -0,0 +1,325 @@ +static char g_Script_vscript_squirrel[] = R"vscript( +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +//=============================================================================// + +Warning <- error; + +function clamp(val,min,max) +{ + if ( max < min ) + return max; + else if( val < min ) + return min; + else if( val > max ) + return max; + else + return val; +} + +function max(a,b) return a > b ? a : b + +function min(a,b) return a < b ? a : b + +function RemapVal(val, A, B, C, D) +{ + if ( A == B ) + return val >= B ? D : C; + return C + (D - C) * (val - A) / (B - A); +} + +function RemapValClamped(val, A, B, C, D) +{ + if ( A == B ) + return val >= B ? D : C; + local cVal = (val - A) / (B - A); + cVal = (cVal < 0.0) ? 0.0 : (1.0 < cVal) ? 1.0 : cVal; + return C + (D - C) * cVal; +} + +function Approach( target, value, speed ) +{ + local delta = target - value + + if( delta > speed ) + value += speed + else if( delta < (-speed) ) + value -= speed + else + value = target + + return value +} + +function AngleDistance( next, cur ) +{ + local delta = next - cur + + if ( delta < (-180.0) ) + delta += 360.0 + else if ( delta > 180.0 ) + delta -= 360.0 + + return delta +} + +function printl( text ) +{ + return ::print(text + "\n"); +} + +class CSimpleCallChainer +{ + constructor(prefixString, scopeForThis, exactMatch) + { + prefix = prefixString; + scope = scopeForThis; + chain = []; + scope["Dispatch" + prefixString] <- Call.bindenv(this); + } + + function PostScriptExecute() + { + local func; + try { + func = scope[prefix]; + } catch(e) { + return; + } + if (typeof(func) != "function") + return; + chain.push(func); + } + + function Call() + { + foreach (func in chain) + { + func.pcall(scope); + } + } + + prefix = null; + scope = null; + chain = null; +} + +DocumentedFuncs <- {} +DocumentedClasses <- {} +DocumentedEnums <- {} +DocumentedConsts <- {} +DocumentedHooks <- {} + +function AddAliasedToTable(name, signature, description, table) +{ + // This is an alias function, could use split() if we could guarantee + // that ':' would not occur elsewhere in the description and Squirrel had + // a convience join() function -- It has split() + local colon = description.find(":"); + if (colon == null) + colon = description.len(); + local alias = description.slice(1, colon); + description = description.slice(colon + 1); + name = alias; + signature = null; + + table[name] <- [signature, description]; +} + +function RegisterHelp(name, signature, description) +{ + if (description.len() && description[0] == '#') + { + AddAliasedToTable(name, signature, description, DocumentedFuncs) + } + else + { + DocumentedFuncs[name] <- [signature, description]; + } +} + +function RegisterClassHelp(name, baseclass, description) +{ + DocumentedClasses[name] <- [baseclass, description]; +} + +function RegisterEnumHelp(name, description) +{ + DocumentedEnums[name] <- description; +} + +function RegisterConstHelp(name, signature, description) +{ + if (description.len() && description[0] == '#') + { + AddAliasedToTable(name, signature, description, DocumentedConsts) + } + else + { + DocumentedConsts[name] <- [signature, description]; + } +} + +function RegisterHookHelp(name, signature, description) +{ + DocumentedHooks[name] <- [signature, description]; +} + +function printdoc( text ) +{ + return ::printc(200,224,255,text); +} + +function printdocl( text ) +{ + return printdoc(text + "\n"); +} + +function PrintClass(name, doc) +{ + printdocl("====================================="); + printdocl("Class: " + name); + printdocl("Base: " + doc[0]); + if (doc[1].len()) + printdocl("Description: " + doc[1]); + printdocl("====================================="); + print("\n"); +} + +function PrintFunc(name, doc) +{ + printdocl("Function: " + name); + if (doc[0] == null) + { + // Is an aliased function + printdoc("Signature: function " + name + "("); + foreach(k,v in this[name].getinfos().parameters) + { + if (k == 0 && v == "this") continue; + if (k > 1) printdoc(", "); + printdoc(v); + } + printdocl(")"); + } + else + { + printdocl("Signature: " + doc[0]); + } + if (doc[1].len()) + printdocl("Description: " + doc[1]); + print("\n"); +} + +function PrintEnum(name, doc) +{ + printdocl("====================================="); + printdocl("Enum: " + name); + if (doc.len()) + printdocl("Description: " + doc); + printdocl("====================================="); + print("\n"); +} + +function PrintConst(name, doc) +{ + printdocl("Constant: " + name); + if (doc[0] == null) + { + // Is an aliased function + printdoc("Signature: function " + name + "("); + foreach(k,v in this[name].getinfos().parameters) + { + if (k == 0 && v == "this") continue; + if (k > 1) printdoc(", "); + printdoc(v); + } + printdocl(")"); + } + else + { + printdocl("Value: " + doc[0]); + } + if (doc[1].len()) + printdocl("Description: " + doc[1]); + print("\n"); +} + +function PrintHook(name, doc) +{ + printdocl("Hook: " + name); + if (doc[0] == null) + { + // Is an aliased function + printdoc("Signature: function " + name + "("); + foreach(k,v in this[name].getinfos().parameters) + { + if (k == 0 && v == "this") continue; + if (k > 1) printdoc(", "); + printdoc(v); + } + printdocl(")"); + } + else + { + printdocl("Signature: " + doc[0]); + } + if (doc[1].len()) + printdocl("Description: " + doc[1]); + print("\n"); +} + +function PrintHelp(pattern = "*") +{ + local foundMatches = false; + foreach(name, doc in DocumentedClasses) + { + if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) + { + foundMatches = true; + PrintClass(name, doc) + } + } + + foreach(name, doc in DocumentedFuncs) + { + if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) + { + foundMatches = true; + PrintFunc(name, doc) + } + } + + foreach(name, doc in DocumentedEnums) + { + if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) + { + foundMatches = true; + PrintEnum(name, doc) + } + } + + foreach(name, doc in DocumentedConsts) + { + if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) + { + foundMatches = true; + PrintConst(name, doc) + } + } + + foreach(name, doc in DocumentedHooks) + { + if (pattern == "*" || name.tolower().find(pattern.tolower()) != null) + { + foundMatches = true; + PrintHook(name, doc) + } + } + + if (!foundMatches) + printdocl("Pattern " + pattern + " not found"); +} + +)vscript"; \ No newline at end of file