From de8447dfc710f21cafa7c4a0a89b90f37366d0ce Mon Sep 17 00:00:00 2001 From: Kirill GPRB <41549137+undnull@users.noreply.github.com> Date: Thu, 27 Jan 2022 01:26:07 +0500 Subject: [PATCH 01/65] HexEdit particles.lib Avoid _hypot being defined twice by renaming it to _STUB1 Taken from my own code at undnull/refraction#14 --- sp/src/lib/public/particles.lib | Bin 11349362 -> 11349362 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sp/src/lib/public/particles.lib b/sp/src/lib/public/particles.lib index adcab9f4fa58871b9eb95d9497bd4a72291b965c..bbc27c63c43a980eff68f23e91898b821104f07c 100644 GIT binary patch delta 1007 zcmZwESx}8(9LMqLaOlM$dxb1TNTpLLvgG8*mb8+xoG3@xA{7TM^t@TJ^OiPbuc;ZD zo(oqla@%zClF^;1D>qFpGrl?ROqy}=nR(_v&-42~&+{Mr)?pq*S%=5hbaP5-nk`K2 zOZR{Y<1ij(Ou$6hm+l!M z8oV$aGcXggFdK6)7v3^H!Y3%u2rSO@sjC?cY*V|2eBg_Dn2!bU!$K^=Vl06_0>@j1pYHMYwPYmvIH9C_}ll4^&w5j2<3slOwfQ zzq}y%J?ZL)cBA_D8*Qd*s?Agh0TorajvKg%Td2lu+`(Pk!+ku!Lp;J`XsAIgo}do( zXplBjV`-?nvHTp?s5bv|386O%y-Da#h5k(F&xPJB^cO;ZDfCxDe=YPkLVw$-zw1me d&WwyfGKQq8(GXv)sVCS|&1r3sIjyah@;@&4#rpsN delta 1007 zcmZwETTqN)9LMn~mR?zMu8>0!QfVti4%sB9q-aSwY?M`~NC%+A}HTphdpO3wPO6PBPO@8{~os#8V+edQOnbf4HsW4(1 zro#s_FcY&d8*?xh^WZC!qWnUF^}y0hzov$OaQjx9br+ULDC@k2q|=Mr^`n#A6H0NWfMkVjGgM9XqfSyRci1Q~(C_o{K za86on=UaaKKl4{|am%>O#KB@Uaqt34P>M2?<02|>372sNm8e3sOdPB+<>@^Cw~uc>CwS_r79!*$%iP255~ZsQK_;vVkf0UqKJ9>b0XG~x-G z(2N#o_H&8O-?X9j*FEz*6E_0ktWAz_eRoAWn From 697b92ea35a9355c50439b5681833949cbd0864a Mon Sep 17 00:00:00 2001 From: Arbab Ahmed Date: Mon, 25 Jul 2022 13:07:43 +1000 Subject: [PATCH 02/65] add info_particle_system_coordinate, plus infinite cooldown functionality for prop_interactable similar to that of func_button --- sp/src/game/client/c_particle_system.cpp | 210 +++++++++-------- sp/src/game/server/particle_system.cpp | 274 ++++++++++++----------- sp/src/game/server/particle_system.h | 51 +++-- sp/src/game/server/props.cpp | 34 +-- 4 files changed, 312 insertions(+), 257 deletions(-) diff --git a/sp/src/game/client/c_particle_system.cpp b/sp/src/game/client/c_particle_system.cpp index 27bafe0e..4986bccd 100644 --- a/sp/src/game/client/c_particle_system.cpp +++ b/sp/src/game/client/c_particle_system.cpp @@ -19,15 +19,15 @@ //----------------------------------------------------------------------------- class C_ParticleSystem : public C_BaseEntity { - DECLARE_CLASS( C_ParticleSystem, C_BaseEntity ); + DECLARE_CLASS(C_ParticleSystem, C_BaseEntity); public: DECLARE_CLIENTCLASS(); C_ParticleSystem(); - void PreDataUpdate( DataUpdateType_t updateType ); - void PostDataUpdate( DataUpdateType_t updateType ); - void ClientThink( void ); + void PreDataUpdate(DataUpdateType_t updateType); + void PostDataUpdate(DataUpdateType_t updateType); + void ClientThink(void); protected: int m_iEffectIndex; @@ -40,8 +40,9 @@ protected: enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me - + EHANDLE m_hControlPointEnts[kMAXCONTROLPOINTS]; + Vector m_vControlPointVecs[kMAXCONTROLPOINTS]; // SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), unsigned char m_iControlPointParents[kMAXCONTROLPOINTS]; @@ -50,23 +51,24 @@ protected: IMPLEMENT_CLIENTCLASS(C_ParticleSystem, DT_ParticleSystem, CParticleSystem); -BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem ) - RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ), - RecvPropEHandle( RECVINFO(m_hOwnerEntity) ), - RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ), - RecvPropInt( RECVINFO( m_iParentAttachment ) ), - RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ), +BEGIN_RECV_TABLE_NOBASE(C_ParticleSystem, DT_ParticleSystem) +RecvPropVector(RECVINFO_NAME(m_vecNetworkOrigin, m_vecOrigin)), +RecvPropEHandle(RECVINFO(m_hOwnerEntity)), +RecvPropInt(RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent), +RecvPropInt(RECVINFO(m_iParentAttachment)), +RecvPropQAngles(RECVINFO_NAME(m_angNetworkAngles, m_angRotation)), - RecvPropInt( RECVINFO( m_iEffectIndex ) ), - RecvPropBool( RECVINFO( m_bActive ) ), +RecvPropInt(RECVINFO(m_iEffectIndex)), +RecvPropBool(RECVINFO(m_bActive)), #ifdef MAPBASE - RecvPropBool( RECVINFO( m_bDestroyImmediately ) ), +RecvPropBool(RECVINFO(m_bDestroyImmediately)), #endif - RecvPropFloat( RECVINFO( m_flStartTime ) ), +RecvPropFloat(RECVINFO(m_flStartTime)), - RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ), - RecvPropArray3( RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt( RECVINFO(m_iControlPointParents[0]))), - RecvPropBool( RECVINFO( m_bWeatherEffect ) ), +RecvPropArray3(RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle(RECVINFO(m_hControlPointEnts[0]))), +RecvPropArray3(RECVINFO_ARRAY(m_vControlPointVecs), RecvPropVector(RECVINFO(m_vControlPointVecs[0]))), +RecvPropArray3(RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt(RECVINFO(m_iControlPointParents[0]))), +RecvPropBool(RECVINFO(m_bWeatherEffect)), END_RECV_TABLE(); //----------------------------------------------------------------------------- @@ -80,38 +82,38 @@ C_ParticleSystem::C_ParticleSystem() //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::PreDataUpdate( DataUpdateType_t updateType ) +void C_ParticleSystem::PreDataUpdate(DataUpdateType_t updateType) { m_bOldActive = m_bActive; - BaseClass::PreDataUpdate( updateType ); + BaseClass::PreDataUpdate(updateType); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) +void C_ParticleSystem::PostDataUpdate(DataUpdateType_t updateType) { - BaseClass::PostDataUpdate( updateType ); + BaseClass::PostDataUpdate(updateType); // Always restart if just created and updated // FIXME: Does this play fairly with PVS? - if ( updateType == DATA_UPDATE_CREATED ) + if (updateType == DATA_UPDATE_CREATED) { - if ( m_bActive ) + if (m_bActive) { // Delayed here so that we don't get invalid abs queries on level init with active particle systems - SetNextClientThink( gpGlobals->curtime ); + SetNextClientThink(gpGlobals->curtime); } } else { - if ( m_bOldActive != m_bActive ) + if (m_bOldActive != m_bActive) { - if ( m_bActive ) + if (m_bActive) { // Delayed here so that we don't get invalid abs queries on level init with active particle systems - SetNextClientThink( gpGlobals->curtime ); + SetNextClientThink(gpGlobals->curtime); } else #ifdef MAPBASE @@ -123,8 +125,8 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) } #else { - ParticleProp()->StopEmission(); - } + ParticleProp()->StopEmission(); + } #endif } } @@ -133,38 +135,54 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::ClientThink( void ) +void C_ParticleSystem::ClientThink(void) { - if ( m_bActive ) + if (m_bActive) { - const char *pszName = GetParticleSystemNameFromIndex( m_iEffectIndex ); - if ( pszName && pszName[0] ) + const char *pszName = GetParticleSystemNameFromIndex(m_iEffectIndex); + if (pszName && pszName[0]) { - if ( !GameRules()->AllowMapParticleEffect( pszName ) ) + if (!GameRules()->AllowMapParticleEffect(pszName)) return; - if ( m_bWeatherEffect && !GameRules()->AllowWeatherParticles() ) + if (m_bWeatherEffect && !GameRules()->AllowWeatherParticles()) return; - CNewParticleEffect *pEffect = ParticleProp()->Create( pszName, PATTACH_ABSORIGIN_FOLLOW ); - AssertMsg1( pEffect, "Particle system couldn't make %s", pszName ); + CNewParticleEffect *pEffect = ParticleProp()->Create(pszName, PATTACH_ABSORIGIN_FOLLOW); + AssertMsg1(pEffect, "Particle system couldn't make %s", pszName); if (pEffect) { - for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i ) - { - CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get(); - if ( pOnEntity ) + if (m_vControlPointVecs[0] != GetAbsOrigin() && m_hControlPointEnts[0] == NULL){ + // we are using info_particle_system_coordinate + for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { - ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW ); + ParticleProp()->AddControlPoint(pEffect, i + 1, this, PATTACH_WORLDORIGIN, 0, m_vControlPointVecs[i] - GetAbsOrigin()); + AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS, + "Particle system specified bogus control point parent (%d) for point %d.", + m_iControlPointParents[i], i); + + if (m_iControlPointParents[i] != 0) + { + pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]); + } } - - AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS , - "Particle system specified bogus control point parent (%d) for point %d.", - m_iControlPointParents[i], i ); - - if (m_iControlPointParents[i] != 0) + } + else{ + for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { - pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]); + CBaseEntity* pOnEntity = m_hControlPointEnts[i].Get(); + if (pOnEntity) + { + ParticleProp()->AddControlPoint(pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW); + } + AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS, + "Particle system specified bogus control point parent (%d) for point %d.", + m_iControlPointParents[i], i); + + if (m_iControlPointParents[i] != 0) + { + pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]); + } } } @@ -172,14 +190,14 @@ void C_ParticleSystem::ClientThink( void ) // already past the end of it, denoting that we're finished. In that case, just destroy us and be done. -- jdw // TODO: This can go when the SkipToTime code below goes - ParticleProp()->OnParticleSystemUpdated( pEffect, 0.0f ); + ParticleProp()->OnParticleSystemUpdated(pEffect, 0.0f); // Skip the effect ahead if we're restarting it float flTimeDelta = gpGlobals->curtime - m_flStartTime; - if ( flTimeDelta > 0.01f ) + if (flTimeDelta > 0.01f) { - VPROF_BUDGET( "C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation" ); - pEffect->SkipToTime( flTimeDelta ); + VPROF_BUDGET("C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation"); + pEffect->SkipToTime(flTimeDelta); } } } @@ -193,79 +211,79 @@ void C_ParticleSystem::ClientThink( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void ParticleEffectCallback( const CEffectData &data ) +void ParticleEffectCallback(const CEffectData &data) { - if ( SuppressingParticleEffects() ) + if (SuppressingParticleEffects()) return; // this needs to be before using data.m_nHitBox, since that may be a serialized value that's past the end of the current particle system string table - const char *pszName = GetParticleSystemNameFromIndex( data.m_nHitBox ); + const char *pszName = GetParticleSystemNameFromIndex(data.m_nHitBox); CSmartPtr pEffect = NULL; - if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) + if (data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY) { - if ( data.m_hEntity.Get() ) + if (data.m_hEntity.Get()) { - C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); - if ( pEnt && !pEnt->IsDormant() ) + C_BaseEntity *pEnt = C_BaseEntity::Instance(data.m_hEntity); + if (pEnt && !pEnt->IsDormant()) { - if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES ) + if (data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES) { pEnt->ParticleProp()->StopEmission(); } - pEffect = pEnt->ParticleProp()->Create( pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex ); - AssertMsg2( pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", - C_BaseEntity::Instance( data.m_hEntity )->GetDebugName(), pszName ); - if ( pEffect.IsValid() && pEffect->IsValid() ) + pEffect = pEnt->ParticleProp()->Create(pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex); + AssertMsg2(pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", + C_BaseEntity::Instance(data.m_hEntity)->GetDebugName(), pszName); + if (pEffect.IsValid() && pEffect->IsValid()) { - if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN ) + if ((ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN) { - pEffect->SetSortOrigin( data.m_vOrigin ); - pEffect->SetControlPoint( 0, data.m_vOrigin ); - pEffect->SetControlPoint( 1, data.m_vStart ); + pEffect->SetSortOrigin(data.m_vOrigin); + pEffect->SetControlPoint(0, data.m_vOrigin); + pEffect->SetControlPoint(1, data.m_vStart); Vector vecForward, vecRight, vecUp; - AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); - pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); + AngleVectors(data.m_vAngles, &vecForward, &vecRight, &vecUp); + pEffect->SetControlPointOrientation(0, vecForward, vecRight, vecUp); } } } } - } + } else { - if ( GameRules() ) + if (GameRules()) { - pszName = GameRules()->TranslateEffectForVisionFilter( "particles", pszName ); + pszName = GameRules()->TranslateEffectForVisionFilter("particles", pszName); } - pEffect = CNewParticleEffect::Create( NULL, pszName ); - if ( pEffect->IsValid() ) + pEffect = CNewParticleEffect::Create(NULL, pszName); + if (pEffect->IsValid()) { - pEffect->SetSortOrigin( data.m_vOrigin ); - pEffect->SetControlPoint( 0, data.m_vOrigin ); - pEffect->SetControlPoint( 1, data.m_vStart ); + pEffect->SetSortOrigin(data.m_vOrigin); + pEffect->SetControlPoint(0, data.m_vOrigin); + pEffect->SetControlPoint(1, data.m_vStart); Vector vecForward, vecRight, vecUp; - AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); - pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); + AngleVectors(data.m_vAngles, &vecForward, &vecRight, &vecUp); + pEffect->SetControlPointOrientation(0, vecForward, vecRight, vecUp); } } - if ( pEffect.IsValid() && pEffect->IsValid() ) + if (pEffect.IsValid() && pEffect->IsValid()) { - if ( data.m_bCustomColors ) + if (data.m_bCustomColors) { - pEffect->SetControlPoint( CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1 ); - pEffect->SetControlPoint( CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2 ); + pEffect->SetControlPoint(CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1); + pEffect->SetControlPoint(CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2); } - if ( data.m_bControlPoint1 ) + if (data.m_bControlPoint1) { - pEffect->SetControlPoint( 1, data.m_ControlPoint1.m_vecOffset ); + pEffect->SetControlPoint(1, data.m_ControlPoint1.m_vecOffset); } } } -DECLARE_CLIENT_EFFECT( "ParticleEffect", ParticleEffectCallback ); +DECLARE_CLIENT_EFFECT("ParticleEffect", ParticleEffectCallback); //====================================================================================================================== @@ -274,16 +292,16 @@ DECLARE_CLIENT_EFFECT( "ParticleEffect", ParticleEffectCallback ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void ParticleEffectStopCallback( const CEffectData &data ) +void ParticleEffectStopCallback(const CEffectData &data) { - if ( data.m_hEntity.Get() ) + if (data.m_hEntity.Get()) { - C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); - if ( pEnt ) + C_BaseEntity *pEnt = C_BaseEntity::Instance(data.m_hEntity); + if (pEnt) { - pEnt->ParticleProp()->StopEmission(); - } + pEnt->ParticleProp()->StopEmission(); } } +} -DECLARE_CLIENT_EFFECT( "ParticleEffectStop", ParticleEffectStopCallback ); +DECLARE_CLIENT_EFFECT("ParticleEffectStop", ParticleEffectStopCallback); diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index 6ec0cb96..ca1caf4f 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -12,125 +12,128 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +extern void SendProxy_Origin(const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); +extern void SendProxy_Angles(const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); // Stripped down CBaseEntity send table IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleSystem, DT_ParticleSystem) - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), - SendPropEHandle (SENDINFO(m_hOwnerEntity)), - SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), - SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), - SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), +SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin), +SendPropEHandle(SENDINFO(m_hOwnerEntity)), +SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent)), +SendPropInt(SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), +SendPropQAngles(SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles), - SendPropInt( SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED ), - SendPropBool( SENDINFO(m_bActive) ), +SendPropInt(SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED), +SendPropBool(SENDINFO(m_bActive)), #ifdef MAPBASE - SendPropBool( SENDINFO(m_bDestroyImmediately) ), +SendPropBool(SENDINFO(m_bDestroyImmediately)), #endif - SendPropFloat( SENDINFO(m_flStartTime) ), +SendPropFloat(SENDINFO(m_flStartTime)), - SendPropArray3( SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle( SENDINFO_ARRAY(m_hControlPointEnts) ) ), - SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), - SendPropBool( SENDINFO(m_bWeatherEffect) ), +SendPropArray3(SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle(SENDINFO_ARRAY(m_hControlPointEnts))), +SendPropArray3(SENDINFO_ARRAY3(m_vControlPointVecs), SendPropVector(SENDINFO_ARRAY(m_vControlPointVecs))), +SendPropArray3(SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt(SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED)), +SendPropBool(SENDINFO(m_bWeatherEffect)), END_SEND_TABLE() -BEGIN_DATADESC( CParticleSystem ) - DEFINE_KEYFIELD( m_bStartActive, FIELD_BOOLEAN, "start_active" ), - DEFINE_KEYFIELD( m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather" ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), +BEGIN_DATADESC(CParticleSystem) +DEFINE_KEYFIELD(m_bStartActive, FIELD_BOOLEAN, "start_active"), +DEFINE_KEYFIELD(m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather"), +DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), #ifdef MAPBASE - DEFINE_FIELD( m_bDestroyImmediately, FIELD_BOOLEAN ), +DEFINE_FIELD(m_bDestroyImmediately, FIELD_BOOLEAN), #endif - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_iszEffectName, FIELD_STRING, "effect_name" ), - //DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. +DEFINE_FIELD(m_flStartTime, FIELD_TIME), +DEFINE_KEYFIELD(m_iszEffectName, FIELD_STRING, "effect_name"), +//DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. - DEFINE_KEYFIELD( m_iszControlPointNames[0], FIELD_STRING, "cpoint1" ), - DEFINE_KEYFIELD( m_iszControlPointNames[1], FIELD_STRING, "cpoint2" ), - DEFINE_KEYFIELD( m_iszControlPointNames[2], FIELD_STRING, "cpoint3" ), - DEFINE_KEYFIELD( m_iszControlPointNames[3], FIELD_STRING, "cpoint4" ), - DEFINE_KEYFIELD( m_iszControlPointNames[4], FIELD_STRING, "cpoint5" ), - DEFINE_KEYFIELD( m_iszControlPointNames[5], FIELD_STRING, "cpoint6" ), - DEFINE_KEYFIELD( m_iszControlPointNames[6], FIELD_STRING, "cpoint7" ), - DEFINE_KEYFIELD( m_iszControlPointNames[7], FIELD_STRING, "cpoint8" ), - DEFINE_KEYFIELD( m_iszControlPointNames[8], FIELD_STRING, "cpoint9" ), - DEFINE_KEYFIELD( m_iszControlPointNames[9], FIELD_STRING, "cpoint10" ), - DEFINE_KEYFIELD( m_iszControlPointNames[10], FIELD_STRING, "cpoint11" ), - DEFINE_KEYFIELD( m_iszControlPointNames[11], FIELD_STRING, "cpoint12" ), - DEFINE_KEYFIELD( m_iszControlPointNames[12], FIELD_STRING, "cpoint13" ), - DEFINE_KEYFIELD( m_iszControlPointNames[13], FIELD_STRING, "cpoint14" ), - DEFINE_KEYFIELD( m_iszControlPointNames[14], FIELD_STRING, "cpoint15" ), - DEFINE_KEYFIELD( m_iszControlPointNames[15], FIELD_STRING, "cpoint16" ), - DEFINE_KEYFIELD( m_iszControlPointNames[16], FIELD_STRING, "cpoint17" ), - DEFINE_KEYFIELD( m_iszControlPointNames[17], FIELD_STRING, "cpoint18" ), - DEFINE_KEYFIELD( m_iszControlPointNames[18], FIELD_STRING, "cpoint19" ), - DEFINE_KEYFIELD( m_iszControlPointNames[19], FIELD_STRING, "cpoint20" ), - DEFINE_KEYFIELD( m_iszControlPointNames[20], FIELD_STRING, "cpoint21" ), - DEFINE_KEYFIELD( m_iszControlPointNames[21], FIELD_STRING, "cpoint22" ), - DEFINE_KEYFIELD( m_iszControlPointNames[22], FIELD_STRING, "cpoint23" ), - DEFINE_KEYFIELD( m_iszControlPointNames[23], FIELD_STRING, "cpoint24" ), - DEFINE_KEYFIELD( m_iszControlPointNames[24], FIELD_STRING, "cpoint25" ), - DEFINE_KEYFIELD( m_iszControlPointNames[25], FIELD_STRING, "cpoint26" ), - DEFINE_KEYFIELD( m_iszControlPointNames[26], FIELD_STRING, "cpoint27" ), - DEFINE_KEYFIELD( m_iszControlPointNames[27], FIELD_STRING, "cpoint28" ), - DEFINE_KEYFIELD( m_iszControlPointNames[28], FIELD_STRING, "cpoint29" ), - DEFINE_KEYFIELD( m_iszControlPointNames[29], FIELD_STRING, "cpoint30" ), - DEFINE_KEYFIELD( m_iszControlPointNames[30], FIELD_STRING, "cpoint31" ), - DEFINE_KEYFIELD( m_iszControlPointNames[31], FIELD_STRING, "cpoint32" ), - DEFINE_KEYFIELD( m_iszControlPointNames[32], FIELD_STRING, "cpoint33" ), - DEFINE_KEYFIELD( m_iszControlPointNames[33], FIELD_STRING, "cpoint34" ), - DEFINE_KEYFIELD( m_iszControlPointNames[34], FIELD_STRING, "cpoint35" ), - DEFINE_KEYFIELD( m_iszControlPointNames[35], FIELD_STRING, "cpoint36" ), - DEFINE_KEYFIELD( m_iszControlPointNames[36], FIELD_STRING, "cpoint37" ), - DEFINE_KEYFIELD( m_iszControlPointNames[37], FIELD_STRING, "cpoint38" ), - DEFINE_KEYFIELD( m_iszControlPointNames[38], FIELD_STRING, "cpoint39" ), - DEFINE_KEYFIELD( m_iszControlPointNames[39], FIELD_STRING, "cpoint40" ), - DEFINE_KEYFIELD( m_iszControlPointNames[40], FIELD_STRING, "cpoint41" ), - DEFINE_KEYFIELD( m_iszControlPointNames[41], FIELD_STRING, "cpoint42" ), - DEFINE_KEYFIELD( m_iszControlPointNames[42], FIELD_STRING, "cpoint43" ), - DEFINE_KEYFIELD( m_iszControlPointNames[43], FIELD_STRING, "cpoint44" ), - DEFINE_KEYFIELD( m_iszControlPointNames[44], FIELD_STRING, "cpoint45" ), - DEFINE_KEYFIELD( m_iszControlPointNames[45], FIELD_STRING, "cpoint46" ), - DEFINE_KEYFIELD( m_iszControlPointNames[46], FIELD_STRING, "cpoint47" ), - DEFINE_KEYFIELD( m_iszControlPointNames[47], FIELD_STRING, "cpoint48" ), - DEFINE_KEYFIELD( m_iszControlPointNames[48], FIELD_STRING, "cpoint49" ), - DEFINE_KEYFIELD( m_iszControlPointNames[49], FIELD_STRING, "cpoint50" ), - DEFINE_KEYFIELD( m_iszControlPointNames[50], FIELD_STRING, "cpoint51" ), - DEFINE_KEYFIELD( m_iszControlPointNames[51], FIELD_STRING, "cpoint52" ), - DEFINE_KEYFIELD( m_iszControlPointNames[52], FIELD_STRING, "cpoint53" ), - DEFINE_KEYFIELD( m_iszControlPointNames[53], FIELD_STRING, "cpoint54" ), - DEFINE_KEYFIELD( m_iszControlPointNames[54], FIELD_STRING, "cpoint55" ), - DEFINE_KEYFIELD( m_iszControlPointNames[55], FIELD_STRING, "cpoint56" ), - DEFINE_KEYFIELD( m_iszControlPointNames[56], FIELD_STRING, "cpoint57" ), - DEFINE_KEYFIELD( m_iszControlPointNames[57], FIELD_STRING, "cpoint58" ), - DEFINE_KEYFIELD( m_iszControlPointNames[58], FIELD_STRING, "cpoint59" ), - DEFINE_KEYFIELD( m_iszControlPointNames[59], FIELD_STRING, "cpoint60" ), - DEFINE_KEYFIELD( m_iszControlPointNames[60], FIELD_STRING, "cpoint61" ), - DEFINE_KEYFIELD( m_iszControlPointNames[61], FIELD_STRING, "cpoint62" ), - DEFINE_KEYFIELD( m_iszControlPointNames[62], FIELD_STRING, "cpoint63" ), +DEFINE_KEYFIELD(m_iszControlPointNames[0], FIELD_STRING, "cpoint1"), +DEFINE_KEYFIELD(m_iszControlPointNames[1], FIELD_STRING, "cpoint2"), +DEFINE_KEYFIELD(m_iszControlPointNames[2], FIELD_STRING, "cpoint3"), +DEFINE_KEYFIELD(m_iszControlPointNames[3], FIELD_STRING, "cpoint4"), +DEFINE_KEYFIELD(m_iszControlPointNames[4], FIELD_STRING, "cpoint5"), +DEFINE_KEYFIELD(m_iszControlPointNames[5], FIELD_STRING, "cpoint6"), +DEFINE_KEYFIELD(m_iszControlPointNames[6], FIELD_STRING, "cpoint7"), +DEFINE_KEYFIELD(m_iszControlPointNames[7], FIELD_STRING, "cpoint8"), +DEFINE_KEYFIELD(m_iszControlPointNames[8], FIELD_STRING, "cpoint9"), +DEFINE_KEYFIELD(m_iszControlPointNames[9], FIELD_STRING, "cpoint10"), +DEFINE_KEYFIELD(m_iszControlPointNames[10], FIELD_STRING, "cpoint11"), +DEFINE_KEYFIELD(m_iszControlPointNames[11], FIELD_STRING, "cpoint12"), +DEFINE_KEYFIELD(m_iszControlPointNames[12], FIELD_STRING, "cpoint13"), +DEFINE_KEYFIELD(m_iszControlPointNames[13], FIELD_STRING, "cpoint14"), +DEFINE_KEYFIELD(m_iszControlPointNames[14], FIELD_STRING, "cpoint15"), +DEFINE_KEYFIELD(m_iszControlPointNames[15], FIELD_STRING, "cpoint16"), +DEFINE_KEYFIELD(m_iszControlPointNames[16], FIELD_STRING, "cpoint17"), +DEFINE_KEYFIELD(m_iszControlPointNames[17], FIELD_STRING, "cpoint18"), +DEFINE_KEYFIELD(m_iszControlPointNames[18], FIELD_STRING, "cpoint19"), +DEFINE_KEYFIELD(m_iszControlPointNames[19], FIELD_STRING, "cpoint20"), +DEFINE_KEYFIELD(m_iszControlPointNames[20], FIELD_STRING, "cpoint21"), +DEFINE_KEYFIELD(m_iszControlPointNames[21], FIELD_STRING, "cpoint22"), +DEFINE_KEYFIELD(m_iszControlPointNames[22], FIELD_STRING, "cpoint23"), +DEFINE_KEYFIELD(m_iszControlPointNames[23], FIELD_STRING, "cpoint24"), +DEFINE_KEYFIELD(m_iszControlPointNames[24], FIELD_STRING, "cpoint25"), +DEFINE_KEYFIELD(m_iszControlPointNames[25], FIELD_STRING, "cpoint26"), +DEFINE_KEYFIELD(m_iszControlPointNames[26], FIELD_STRING, "cpoint27"), +DEFINE_KEYFIELD(m_iszControlPointNames[27], FIELD_STRING, "cpoint28"), +DEFINE_KEYFIELD(m_iszControlPointNames[28], FIELD_STRING, "cpoint29"), +DEFINE_KEYFIELD(m_iszControlPointNames[29], FIELD_STRING, "cpoint30"), +DEFINE_KEYFIELD(m_iszControlPointNames[30], FIELD_STRING, "cpoint31"), +DEFINE_KEYFIELD(m_iszControlPointNames[31], FIELD_STRING, "cpoint32"), +DEFINE_KEYFIELD(m_iszControlPointNames[32], FIELD_STRING, "cpoint33"), +DEFINE_KEYFIELD(m_iszControlPointNames[33], FIELD_STRING, "cpoint34"), +DEFINE_KEYFIELD(m_iszControlPointNames[34], FIELD_STRING, "cpoint35"), +DEFINE_KEYFIELD(m_iszControlPointNames[35], FIELD_STRING, "cpoint36"), +DEFINE_KEYFIELD(m_iszControlPointNames[36], FIELD_STRING, "cpoint37"), +DEFINE_KEYFIELD(m_iszControlPointNames[37], FIELD_STRING, "cpoint38"), +DEFINE_KEYFIELD(m_iszControlPointNames[38], FIELD_STRING, "cpoint39"), +DEFINE_KEYFIELD(m_iszControlPointNames[39], FIELD_STRING, "cpoint40"), +DEFINE_KEYFIELD(m_iszControlPointNames[40], FIELD_STRING, "cpoint41"), +DEFINE_KEYFIELD(m_iszControlPointNames[41], FIELD_STRING, "cpoint42"), +DEFINE_KEYFIELD(m_iszControlPointNames[42], FIELD_STRING, "cpoint43"), +DEFINE_KEYFIELD(m_iszControlPointNames[43], FIELD_STRING, "cpoint44"), +DEFINE_KEYFIELD(m_iszControlPointNames[44], FIELD_STRING, "cpoint45"), +DEFINE_KEYFIELD(m_iszControlPointNames[45], FIELD_STRING, "cpoint46"), +DEFINE_KEYFIELD(m_iszControlPointNames[46], FIELD_STRING, "cpoint47"), +DEFINE_KEYFIELD(m_iszControlPointNames[47], FIELD_STRING, "cpoint48"), +DEFINE_KEYFIELD(m_iszControlPointNames[48], FIELD_STRING, "cpoint49"), +DEFINE_KEYFIELD(m_iszControlPointNames[49], FIELD_STRING, "cpoint50"), +DEFINE_KEYFIELD(m_iszControlPointNames[50], FIELD_STRING, "cpoint51"), +DEFINE_KEYFIELD(m_iszControlPointNames[51], FIELD_STRING, "cpoint52"), +DEFINE_KEYFIELD(m_iszControlPointNames[52], FIELD_STRING, "cpoint53"), +DEFINE_KEYFIELD(m_iszControlPointNames[53], FIELD_STRING, "cpoint54"), +DEFINE_KEYFIELD(m_iszControlPointNames[54], FIELD_STRING, "cpoint55"), +DEFINE_KEYFIELD(m_iszControlPointNames[55], FIELD_STRING, "cpoint56"), +DEFINE_KEYFIELD(m_iszControlPointNames[56], FIELD_STRING, "cpoint57"), +DEFINE_KEYFIELD(m_iszControlPointNames[57], FIELD_STRING, "cpoint58"), +DEFINE_KEYFIELD(m_iszControlPointNames[58], FIELD_STRING, "cpoint59"), +DEFINE_KEYFIELD(m_iszControlPointNames[59], FIELD_STRING, "cpoint60"), +DEFINE_KEYFIELD(m_iszControlPointNames[60], FIELD_STRING, "cpoint61"), +DEFINE_KEYFIELD(m_iszControlPointNames[61], FIELD_STRING, "cpoint62"), +DEFINE_KEYFIELD(m_iszControlPointNames[62], FIELD_STRING, "cpoint63"), - DEFINE_KEYFIELD( m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent" ), - - DEFINE_AUTO_ARRAY( m_hControlPointEnts, FIELD_EHANDLE ), +DEFINE_KEYFIELD(m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent"), - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), +DEFINE_AUTO_ARRAY(m_hControlPointEnts, FIELD_EHANDLE), +DEFINE_AUTO_ARRAY(m_vControlPointVecs, FIELD_VECTOR), + +DEFINE_INPUTFUNC(FIELD_VOID, "Start", InputStart), +DEFINE_INPUTFUNC(FIELD_VOID, "Stop", InputStop), #ifdef MAPBASE - DEFINE_INPUTFUNC( FIELD_VOID, "DestroyImmediately", InputDestroyImmediately ), +DEFINE_INPUTFUNC(FIELD_VOID, "DestroyImmediately", InputDestroyImmediately), #endif - DEFINE_THINKFUNC( StartParticleSystemThink ), +DEFINE_THINKFUNC(StartParticleSystemThink), END_DATADESC() -LINK_ENTITY_TO_CLASS( info_particle_system, CParticleSystem ); +LINK_ENTITY_TO_CLASS(info_particle_system, CParticleSystem); +LINK_ENTITY_TO_CLASS(info_particle_system_coordinate, CParticleSystemCoordinate); //----------------------------------------------------------------------------- // Purpose: @@ -143,22 +146,22 @@ CParticleSystem::CParticleSystem() //----------------------------------------------------------------------------- // Precache //----------------------------------------------------------------------------- -void CParticleSystem::Precache( void ) +void CParticleSystem::Precache(void) { - const char *pParticleSystemName = STRING( m_iszEffectName ); - if ( pParticleSystemName == NULL || pParticleSystemName[0] == '\0' ) + const char *pParticleSystemName = STRING(m_iszEffectName); + if (pParticleSystemName == NULL || pParticleSystemName[0] == '\0') { - Warning( "info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr() ); + Warning("info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr()); } - PrecacheParticleSystem( pParticleSystemName ); + PrecacheParticleSystem(pParticleSystemName); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::Spawn( void ) +void CParticleSystem::Spawn(void) { BaseClass::Spawn(); @@ -169,14 +172,14 @@ void CParticleSystem::Spawn( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::Activate( void ) +void CParticleSystem::Activate(void) { BaseClass::Activate(); // Find our particle effect index - m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) ); + m_iEffectIndex = GetParticleSystemIndex(STRING(m_iszEffectName)); - if ( m_bStartActive ) + if (m_bStartActive) { m_bStartActive = false; StartParticleSystem(); @@ -186,7 +189,7 @@ void CParticleSystem::Activate( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystemThink( void ) +void CParticleSystem::StartParticleSystemThink(void) { StartParticleSystem(); } @@ -196,22 +199,22 @@ void CParticleSystem::StartParticleSystemThink( void ) //----------------------------------------------------------------------------- int CParticleSystem::UpdateTransmitState() { - return SetTransmitState( FL_EDICT_ALWAYS ); + return SetTransmitState(FL_EDICT_ALWAYS); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystem( void ) +void CParticleSystem::StartParticleSystem(void) { - if ( m_bActive == false ) + if (m_bActive == false) { m_flStartTime = gpGlobals->curtime; m_bActive = true; #ifdef MAPBASE m_bDestroyImmediately = false; #endif - + // Setup our control points at this time (in case our targets weren't around at spawn time) ReadControlPointEnts(); } @@ -220,7 +223,7 @@ void CParticleSystem::StartParticleSystem( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StopParticleSystem( void ) +void CParticleSystem::StopParticleSystem(void) { m_bActive = false; } @@ -228,7 +231,7 @@ void CParticleSystem::StopParticleSystem( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputStart( inputdata_t &inputdata ) +void CParticleSystem::InputStart(inputdata_t &inputdata) { StartParticleSystem(); } @@ -236,7 +239,7 @@ void CParticleSystem::InputStart( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputStop( inputdata_t &inputdata ) +void CParticleSystem::InputStop(inputdata_t &inputdata) { StopParticleSystem(); } @@ -245,7 +248,7 @@ void CParticleSystem::InputStop( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputDestroyImmediately( inputdata_t &inputdata ) +void CParticleSystem::InputDestroyImmediately(inputdata_t &inputdata) { m_bDestroyImmediately = true; StopParticleSystem(); @@ -254,23 +257,36 @@ void CParticleSystem::InputDestroyImmediately( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: Find each entity referred to by m_iszControlPointNames and -// resolve it into the corresponding slot in m_hControlPointEnts +// resolve it into the corresponding slot in m_vControlPointVecs //----------------------------------------------------------------------------- -void CParticleSystem::ReadControlPointEnts( void ) +void CParticleSystem::ReadControlPointEnts(void) { - for ( int i = 0 ; i < kMAXCONTROLPOINTS; ++i ) + for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { - if ( m_iszControlPointNames[i] == NULL_STRING ) - continue; + if (UsesCoordinates()) { + float vecCoords[3]; + if (m_iszControlPointNames[i] == NULL_STRING) + m_vControlPointVecs.Set(i, GetAbsOrigin()); // use self as default position + else{ + // cast str to vector, add vector to array + const char* pszVector = STRING(m_iszControlPointNames[i]); + UTIL_StringToVector(vecCoords, pszVector); + m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); + } - CBaseEntity *pPointEnt = gEntList.FindEntityGeneric( NULL, STRING( m_iszControlPointNames[i] ), this ); - Assert( pPointEnt != NULL ); - if ( pPointEnt == NULL ) - { - Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr() ); - continue; } + else{ + if (m_iszControlPointNames[i] == NULL_STRING) + continue; + CBaseEntity *pPointEnt = gEntList.FindEntityGeneric(NULL, STRING(m_iszControlPointNames[i]), this); + Assert(pPointEnt != NULL); + if (pPointEnt == NULL) + { + Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr()); + continue; + } - m_hControlPointEnts.Set( i, pPointEnt ); + m_hControlPointEnts.Set(i, pPointEnt); + } } } diff --git a/sp/src/game/server/particle_system.h b/sp/src/game/server/particle_system.h index 6ce9a9c9..d9ed3fe6 100644 --- a/sp/src/game/server/particle_system.h +++ b/sp/src/game/server/particle_system.h @@ -17,49 +17,62 @@ //----------------------------------------------------------------------------- class CParticleSystem : public CBaseEntity { - DECLARE_CLASS( CParticleSystem, CBaseEntity ); + DECLARE_CLASS(CParticleSystem, CBaseEntity); public: DECLARE_SERVERCLASS(); DECLARE_DATADESC(); CParticleSystem(); - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); + virtual void Precache(void); + virtual void Spawn(void); + virtual void Activate(void); virtual int UpdateTransmitState(void); - void StartParticleSystem( void ); - void StopParticleSystem( void ); + void StartParticleSystem(void); + void StopParticleSystem(void); - void InputStart( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); + void InputStart(inputdata_t &inputdata); + void InputStop(inputdata_t &inputdata); #ifdef MAPBASE - void InputDestroyImmediately( inputdata_t &inputdata ); + void InputDestroyImmediately(inputdata_t &inputdata); #endif - void StartParticleSystemThink( void ); + void StartParticleSystemThink(void); enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me + virtual bool UsesCoordinates(void) { return false; } + protected: /// Load up and resolve the entities that are supposed to be the control points - void ReadControlPointEnts( void ); + virtual void ReadControlPointEnts(void); bool m_bStartActive; string_t m_iszEffectName; - - CNetworkVar( bool, m_bActive ); + + CNetworkVar(bool, m_bActive); #ifdef MAPBASE - CNetworkVar( bool, m_bDestroyImmediately ); + CNetworkVar(bool, m_bDestroyImmediately); #endif - CNetworkVar( int, m_iEffectIndex ) - CNetworkVar( float, m_flStartTime ); // Time at which this effect was started. This is used after restoring an active effect. + CNetworkVar(int, m_iEffectIndex) + CNetworkVar(float, m_flStartTime); // Time at which this effect was started. This is used after restoring an active effect. string_t m_iszControlPointNames[kMAXCONTROLPOINTS]; - CNetworkArray( EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS ); - CNetworkArray( unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS ); - CNetworkVar( bool, m_bWeatherEffect ); + CNetworkArray(EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS); + CNetworkArray(Vector, m_vControlPointVecs, kMAXCONTROLPOINTS); + CNetworkArray(unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS); + CNetworkVar(bool, m_bWeatherEffect); +}; + +//----------------------------------------------------------------------------- +// Purpose: An entity that spawns and controls a particle system using coordinates. +//----------------------------------------------------------------------------- +class CParticleSystemCoordinate : public CParticleSystem +{ + DECLARE_CLASS(CParticleSystemCoordinate, CParticleSystem); +public: + virtual bool UsesCoordinates(void) { return true; } }; #endif // PARTICLE_SYSTEM_H diff --git a/sp/src/game/server/props.cpp b/sp/src/game/server/props.cpp index c643dd68..e53582d5 100644 --- a/sp/src/game/server/props.cpp +++ b/sp/src/game/server/props.cpp @@ -2800,7 +2800,7 @@ void CInteractableProp::Precache( void ) // useType - // value - //----------------------------------------------------------------------------- -void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +void CInteractableProp::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { if (m_flCooldownTime > gpGlobals->curtime) return; @@ -2808,18 +2808,18 @@ void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_ // If we're using +USE mins/maxs, make sure this is being +USE'd from the right place if (m_vecUseMins.LengthSqr() != 0.0f && m_vecUseMaxs.LengthSqr() != 0.0f) { - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); + CBasePlayer *pPlayer = ToBasePlayer(pActivator); if (pPlayer) { Vector forward; - pPlayer->EyeVectors( &forward, NULL, NULL ); + pPlayer->EyeVectors(&forward, NULL, NULL); // This might be a little convoluted and/or seem needlessly expensive, but I couldn't figure out any better way to do this. // TOOD: Can we calculate a box in local space instead of world space? Vector vecWorldMins, vecWorldMaxs; - RotateAABB( EntityToWorldTransform(), m_vecUseMins, m_vecUseMaxs, vecWorldMins, vecWorldMaxs ); - TransformAABB( EntityToWorldTransform(), vecWorldMins, vecWorldMaxs, vecWorldMins, vecWorldMaxs ); - if (!IsBoxIntersectingRay( vecWorldMins, vecWorldMaxs, pPlayer->EyePosition(), forward * 1024 )) + RotateAABB(EntityToWorldTransform(), m_vecUseMins, m_vecUseMaxs, vecWorldMins, vecWorldMaxs); + TransformAABB(EntityToWorldTransform(), vecWorldMins, vecWorldMaxs, vecWorldMins, vecWorldMaxs); + if (!IsBoxIntersectingRay(vecWorldMins, vecWorldMaxs, pPlayer->EyePosition(), forward * 1024)) { // Reject this +USE if it's not in our box DevMsg("Outside of +USE box\n"); @@ -2832,28 +2832,36 @@ void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_ if (m_bLocked) { - m_OnLockedUse.FireOutput( pActivator, this ); + m_OnLockedUse.FireOutput(pActivator, this); EmitSound(STRING(m_iszLockedSound)); - nSequence = LookupSequence( STRING( m_iszLockedSequence ) ); + nSequence = LookupSequence(STRING(m_iszLockedSequence)); m_iCurSequence = INTERACTSEQ_LOCKED; } else { - m_OnPressed.FireOutput( pActivator, this ); + m_OnPressed.FireOutput(pActivator, this); EmitSound(STRING(m_iszPressedSound)); - nSequence = LookupSequence( STRING( m_iszInSequence ) ); + nSequence = LookupSequence(STRING(m_iszInSequence)); m_iCurSequence = INTERACTSEQ_IN; } - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) + if (nSequence > ACTIVITY_NOT_AVAILABLE) { SetPushSequence(nSequence); // We still fire our inherited animation outputs - m_pOutputAnimBegun.FireOutput( pActivator, this ); + m_pOutputAnimBegun.FireOutput(pActivator, this); } - m_flCooldownTime = gpGlobals->curtime + m_flCooldown; + if (m_flCooldown == -1 && !m_bLocked){ + m_flCooldownTime = 1e+30; // yeah we're not going to hit this any time soon + } + else if (m_flCooldown == -1){ + m_flCooldownTime = gpGlobals->curtime + 1.0f; // 1s cooldown if locked + } + else{ + m_flCooldownTime = gpGlobals->curtime + m_flCooldown; + } } //----------------------------------------------------------------------------- From fa3d686067a8829c3abe528fcbbb47a92c5392d9 Mon Sep 17 00:00:00 2001 From: Arbab Ahmed Date: Mon, 25 Jul 2022 23:43:58 +1000 Subject: [PATCH 03/65] remove setabsorigin() code in serverside particle system --- sp/src/game/server/particle_system.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index ca1caf4f..85ce3c10 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -265,13 +265,13 @@ void CParticleSystem::ReadControlPointEnts(void) { if (UsesCoordinates()) { float vecCoords[3]; - if (m_iszControlPointNames[i] == NULL_STRING) - m_vControlPointVecs.Set(i, GetAbsOrigin()); // use self as default position - else{ + if (UsesCoordinates()) { + float vecCoords[3]; // cast str to vector, add vector to array const char* pszVector = STRING(m_iszControlPointNames[i]); UTIL_StringToVector(vecCoords, pszVector); m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); + } } From a5770191bba498b220fe3bf5d9e8b03b3ae2bea8 Mon Sep 17 00:00:00 2001 From: Arbab Ahmed Date: Sat, 30 Jul 2022 15:56:50 +1000 Subject: [PATCH 04/65] use FLT_MAX instead of 1e+30, remove a busted two lines of code --- sp/src/game/server/particle_system.cpp | 13 ++++--------- sp/src/game/server/props.cpp | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index 85ce3c10..a8f576a7 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -265,15 +265,10 @@ void CParticleSystem::ReadControlPointEnts(void) { if (UsesCoordinates()) { float vecCoords[3]; - if (UsesCoordinates()) { - float vecCoords[3]; - // cast str to vector, add vector to array - const char* pszVector = STRING(m_iszControlPointNames[i]); - UTIL_StringToVector(vecCoords, pszVector); - m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); - - } - + // cast str to vector, add vector to array + const char* pszVector = STRING(m_iszControlPointNames[i]); + UTIL_StringToVector(vecCoords, pszVector); + m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); } else{ if (m_iszControlPointNames[i] == NULL_STRING) diff --git a/sp/src/game/server/props.cpp b/sp/src/game/server/props.cpp index e53582d5..ad5cc84f 100644 --- a/sp/src/game/server/props.cpp +++ b/sp/src/game/server/props.cpp @@ -2854,7 +2854,7 @@ void CInteractableProp::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T } if (m_flCooldown == -1 && !m_bLocked){ - m_flCooldownTime = 1e+30; // yeah we're not going to hit this any time soon + m_flCooldownTime = FLT_MAX; // yeah we're not going to hit this any time soon } else if (m_flCooldown == -1){ m_flCooldownTime = gpGlobals->curtime + 1.0f; // 1s cooldown if locked From 9bf1fb4ceaa62d1a18c4b2df2a303249d370a935 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Fri, 14 Oct 2022 18:23:33 +0300 Subject: [PATCH 05/65] Fix CScriptNetMsgHelper::WriteEntity() --- sp/src/game/shared/mapbase/vscript_singletons.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 8f821e6c..14949c60 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -1749,8 +1749,8 @@ void CNetMsgScriptHelper::WriteEntity( HSCRIPT hEnt ) { SCRIPT_NETMSG_WRITE_FUNC CBaseEntity *p = ToEnt(hEnt); - int i = p ? p->entindex() : -1; - m_MsgOut.WriteSBitLong( i, MAX_EDICT_BITS ); + int i = p ? p->entindex() : 0; + m_MsgOut.WriteUBitLong( i, MAX_EDICT_BITS ); } void CNetMsgScriptHelper::WriteEHandle( HSCRIPT hEnt ) @@ -1861,7 +1861,11 @@ bool CNetMsgScriptHelper::ReadBool() HSCRIPT CNetMsgScriptHelper::ReadEntity() { - int index = m_MsgIn_()ReadSBitLong( MAX_EDICT_BITS ); + int index = m_MsgIn_()ReadUBitLong( MAX_EDICT_BITS ); + + if ( !index ) + return NULL; + #ifdef GAME_DLL edict_t *e = INDEXENT(index); if ( e && !e->IsFree() ) From 7849b1440f875f7286f6902813727360622cf523 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Fri, 14 Oct 2022 18:25:46 +0300 Subject: [PATCH 06/65] Clarify comment --- sp/src/game/shared/mapbase/vscript_singletons.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 14949c60..67af8015 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -740,7 +740,11 @@ void CScriptGameEventListener::StopListeningForEvent() #ifdef _DEBUG // Event listeners are iterated forwards in the game event manager, // removing while iterating will cause it to skip one listener. - // This could be prevented by writing a custom game event manager. + // + // Fix this in engine without altering any behaviour by + // changing event exeuction order to tail->head, + // changing listener removal to tail->head, + // changing listener addition to head if ( m_nEventTick == gpGlobals->tickcount ) { Warning("CScriptGameEventListener stopped in the same frame it was fired. This will break other event listeners!\n"); From 2ca2d7c80f942821b231ac763cf218bd77ee730f Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 10:05:40 -0500 Subject: [PATCH 07/65] Specified 32-bit for gcc9+support.o --- sp/src/devtools/makefile_base_posix.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp/src/devtools/makefile_base_posix.mak b/sp/src/devtools/makefile_base_posix.mak index 21147f21..ed9467f9 100644 --- a/sp/src/devtools/makefile_base_posix.mak +++ b/sp/src/devtools/makefile_base_posix.mak @@ -11,6 +11,6 @@ $(MAKEFILE_LINK): $(shell which $(CXX)) $(THISFILE) $(SRCROOT)/devtools/gcc9+sup @ if [ "$(shell printf "$(shell $(CXX) -dumpversion)\n8" | sort -Vr | head -1)" = 8 ]; then \ ln -sf $(MAKEFILE_BASE).default $@ ;\ else \ - $(COMPILE.cpp) -o $(SRCROOT)/devtools/gcc9+support.o $(SRCROOT)/devtools/gcc9+support.cpp &&\ + $(COMPILE.cpp) -m32 -o $(SRCROOT)/devtools/gcc9+support.o $(SRCROOT)/devtools/gcc9+support.cpp &&\ ln -sf $(MAKEFILE_BASE).gcc8 $@ ;\ fi From 8cf06b2865a0d1e624b7ed5fe8e9c0bb0bab0464 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 10:06:26 -0500 Subject: [PATCH 08/65] Fixed GCC error in ivscript.h --- sp/src/public/vscript/ivscript.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sp/src/public/vscript/ivscript.h b/sp/src/public/vscript/ivscript.h index 0d105d55..7d4ed0ea 100644 --- a/sp/src/public/vscript/ivscript.h +++ b/sp/src/public/vscript/ivscript.h @@ -1605,6 +1605,10 @@ typedef CScriptScopeT<> CScriptScope; #define FOR_EACH_VEC_PTR( vecName, iteratorName ) \ for ( int iteratorName = 0; iteratorName < (vecName)->Count(); iteratorName++ ) +//----------------------------------------------------------------------------- + +static void __UpdateScriptHooks( HSCRIPT hooksList ); + //----------------------------------------------------------------------------- // // Keeps track of which events and scopes are hooked without polling this from the script VM on each request. @@ -1654,12 +1658,6 @@ public: return scopeMap->Find( g_pScriptVM->HScriptToRaw( hScope ) ) != scopeMap->InvalidIndex(); } - static void __UpdateScriptHooks( HSCRIPT hooksList ) - { - extern CScriptHookManager &GetScriptHookManager(); - GetScriptHookManager().Update( hooksList ); - } - // // On VM init, registers script func and caches the hook func. // @@ -1876,6 +1874,11 @@ inline CScriptHookManager &GetScriptHookManager() return g_ScriptHookManager; } +static void __UpdateScriptHooks( HSCRIPT hooksList ) +{ + GetScriptHookManager().Update( hooksList ); +} + //----------------------------------------------------------------------------- // Function bindings allow script functions to run C++ functions. From 6945ef2468a53fc40fc00b2eff814b47707a8ccf Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 13:47:29 -0500 Subject: [PATCH 09/65] Fixed npc_sniper not acquiring player as target after SP respawn --- sp/src/game/server/hl2/proto_sniper.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sp/src/game/server/hl2/proto_sniper.cpp b/sp/src/game/server/hl2/proto_sniper.cpp index 84eba6df..4315e35c 100644 --- a/sp/src/game/server/hl2/proto_sniper.cpp +++ b/sp/src/game/server/hl2/proto_sniper.cpp @@ -940,6 +940,14 @@ void CProtoSniper::OnScheduleChange( void ) { LaserOff(); +#ifdef MAPBASE + if ( m_bKilledPlayer && HasCondition( COND_SEE_PLAYER ) ) + { + // IMPOSSIBLE! (possible when SP respawn is enabled) + m_bKilledPlayer = false; + } +#endif + BaseClass::OnScheduleChange(); } @@ -3439,6 +3447,18 @@ AI_BEGIN_CUSTOM_NPC( proto_sniper, CProtoSniper ) //========================================================= //========================================================= +#ifdef MAPBASE + DEFINE_SCHEDULE + ( + SCHED_PSNIPER_PLAYER_DEAD, + + " Tasks" + " TASK_SNIPER_PLAYER_DEAD 0" + " " + " Interrupts" + " COND_SEE_PLAYER" + ) +#else DEFINE_SCHEDULE ( SCHED_PSNIPER_PLAYER_DEAD, @@ -3448,6 +3468,7 @@ AI_BEGIN_CUSTOM_NPC( proto_sniper, CProtoSniper ) " " " Interrupts" ) +#endif AI_END_CUSTOM_NPC() From d23160602041beddb57f6d04c01e47b3e10bc1ea Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 15:12:59 -0500 Subject: [PATCH 10/65] Fixed crash when a prop_dynamic with a model scale has no physics object --- sp/src/game/server/baseanimating.cpp | 4 ++-- sp/src/game/server/props.cpp | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sp/src/game/server/baseanimating.cpp b/sp/src/game/server/baseanimating.cpp index 74a9343e..38b1606a 100644 --- a/sp/src/game/server/baseanimating.cpp +++ b/sp/src/game/server/baseanimating.cpp @@ -2930,9 +2930,9 @@ void CBaseAnimating::InvalidateBoneCache( void ) bool CBaseAnimating::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) { // Return a special case for scaled physics objects - if ( GetModelScale() != 1.0f ) + IPhysicsObject *pPhysObject = VPhysicsGetObject(); + if ( GetModelScale() != 1.0f && pPhysObject ) { - IPhysicsObject *pPhysObject = VPhysicsGetObject(); Vector vecPosition; QAngle vecAngles; pPhysObject->GetPosition( &vecPosition, &vecAngles ); diff --git a/sp/src/game/server/props.cpp b/sp/src/game/server/props.cpp index 78675b7a..440566ba 100644 --- a/sp/src/game/server/props.cpp +++ b/sp/src/game/server/props.cpp @@ -2283,11 +2283,7 @@ bool CDynamicProp::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& } } } -#ifdef MAPBASE // From Alien Swarm SDK - return BaseClass::TestCollision( ray, mask, trace ); -#else return false; -#endif } From 802463acfbfce72b97520c8d09301e49a78e9c0f Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 15:13:36 -0500 Subject: [PATCH 11/65] Removed /force:multiple from client VPC for newer VS toolsets --- sp/src/game/client/client_base.vpc | 1 - 1 file changed, 1 deletion(-) diff --git a/sp/src/game/client/client_base.vpc b/sp/src/game/client/client_base.vpc index 2fda4762..daf5bf41 100644 --- a/sp/src/game/client/client_base.vpc +++ b/sp/src/game/client/client_base.vpc @@ -71,7 +71,6 @@ $Configuration $SystemFrameworks "Carbon" [$OSXALL] $SystemLibraries "rt" [$LINUXALL] $IgnoreImportLibrary "TRUE" - $AdditionalOptions "$BASE /force:multiple" [($VS2015||$VS2017||$VS2019||$VS2022)] // Required to fix _hypot in particles.lib (this may be a temporary solution) $AdditionalDependencies "$BASE winmm.lib" [$WIN32] $AdditionalDependencies "$BASE wsock32.lib Ws2_32.lib" [$BUILD_REPLAY] } From 7b836ece91d507c83e0e8a0c3742cc5569b5648c Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 15:14:25 -0500 Subject: [PATCH 12/65] Added support for hud_showemptyweaponslots 0 in hud_fastswitch 2 --- .../game/client/hl2/hud_weaponselection.cpp | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/sp/src/game/client/hl2/hud_weaponselection.cpp b/sp/src/game/client/hl2/hud_weaponselection.cpp index f5600705..b83d6429 100644 --- a/sp/src/game/client/hl2/hud_weaponselection.cpp +++ b/sp/src/game/client/hl2/hud_weaponselection.cpp @@ -644,6 +644,15 @@ void CHudWeaponSelection::Paint() // This is a bit of a misnomer... we really are asking "Is this the selected slot"? selectedWeapon = true; } +#ifdef MAPBASE + else if (!hud_showemptyweaponslots.GetBool() && !pWeapon) + { + // Revert the offset + xPos -= ( m_flMediumBoxWide + 5 ) * xModifiers[ i ]; + yPos -= ( m_flMediumBoxTall + 5 ) * yModifiers[ i ]; + continue; + } +#endif // Draw the box with the appropriate icon DrawLargeWeaponBox( pWeapon, @@ -1375,6 +1384,23 @@ void CHudWeaponSelection::PlusTypeFastWeaponSwitch( int iWeaponSlot ) // Changing vertical/horizontal direction. Reset the selected box position to zero. m_iSelectedBoxPosition = 0; m_iSelectedSlot = iWeaponSlot; + +#ifdef MAPBASE + if (!hud_showemptyweaponslots.GetBool()) + { + // Skip empty slots + int i = 0; + while ( i < MAX_WEAPON_POSITIONS ) + { + C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( iWeaponSlot, i ); + if ( pWeapon ) + break; + i++; + } + + m_iSelectedBoxPosition = i; + } +#endif } else { @@ -1385,6 +1411,27 @@ void CHudWeaponSelection::PlusTypeFastWeaponSwitch( int iWeaponSlot ) // Decrementing within the slot. If we're at the zero position in this slot, // jump to the zero position of the opposite slot. This also counts as our increment. increment = -1; +#ifdef MAPBASE + if (!hud_showemptyweaponslots.GetBool()) + { + // Skip empty slots + int iZeroPos = 0; + while ( iZeroPos < MAX_WEAPON_POSITIONS ) + { + C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( m_iSelectedSlot, iZeroPos ); + if ( pWeapon ) + break; + iZeroPos++; + } + + if ( iZeroPos == m_iSelectedBoxPosition ) + { + newSlot = ( m_iSelectedSlot + 2 ) % 4; + m_iSelectedBoxPosition = increment = 0; + } + } + else +#endif if ( 0 == m_iSelectedBoxPosition ) { newSlot = ( m_iSelectedSlot + 2 ) % 4; @@ -1402,6 +1449,35 @@ void CHudWeaponSelection::PlusTypeFastWeaponSwitch( int iWeaponSlot ) lastSlotPos = slotPos; } } + +#ifdef MAPBASE + if (!hud_showemptyweaponslots.GetBool()) + { + // Skip empty slots + int i = m_iSelectedBoxPosition + increment; + while ( i >= 0 && i < lastSlotPos ) + { + C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( newSlot, i ); + if ( !pWeapon ) + { + if (increment < 0) + { + increment--; + i--; + } + else + { + increment++; + i++; + } + } + else + { + break; + } + } + } +#endif // Increment/Decrement the selected box position if ( m_iSelectedBoxPosition + increment <= lastSlotPos ) From ccdc1719ae8d41a412cf52540ac9804cac3ba166 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 15:16:02 -0500 Subject: [PATCH 13/65] Fixed negated conditionals not being recognized by hudanimations.txt --- sp/src/vgui2/vgui_controls/AnimationController.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sp/src/vgui2/vgui_controls/AnimationController.cpp b/sp/src/vgui2/vgui_controls/AnimationController.cpp index 886b4291..bc2b1774 100644 --- a/sp/src/vgui2/vgui_controls/AnimationController.cpp +++ b/sp/src/vgui2/vgui_controls/AnimationController.cpp @@ -357,7 +357,12 @@ bool AnimationController::ParseScriptFile(char *pMem, int length) // get the open brace or a conditional pMem = ParseFile(pMem, token, NULL); +#ifdef MAPBASE + // Fixes ! conditionals + if ( Q_stristr( token, "[$" ) || Q_stristr( token, "[!$" ) ) +#else if ( Q_stristr( token, "[$" ) ) +#endif { bAccepted = EvaluateConditional( token ); @@ -622,7 +627,12 @@ bool AnimationController::ParseScriptFile(char *pMem, int length) // Look ahead one token for a conditional char *peek = ParseFile(pMem, token, NULL); +#ifdef MAPBASE + // Fixes ! conditionals + if ( Q_stristr( token, "[$" ) || Q_stristr( token, "[!$" ) ) +#else if ( Q_stristr( token, "[$" ) ) +#endif { if ( !EvaluateConditional( token ) ) { From 852d63ba6f2ef5553390435e5e5ee3f188dfd8d5 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 15:16:53 -0500 Subject: [PATCH 14/65] Added support for "custom" conditionals in KeyValues --- sp/src/tier1/KeyValues.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sp/src/tier1/KeyValues.cpp b/sp/src/tier1/KeyValues.cpp index 19d6d66c..16fae59c 100644 --- a/sp/src/tier1/KeyValues.cpp +++ b/sp/src/tier1/KeyValues.cpp @@ -2081,6 +2081,28 @@ bool EvaluateConditional( const char *str ) if ( Q_stristr( str, "$POSIX" ) ) return IsPosix() ^ bNot; + +#ifdef MAPBASE + // Custom conditional + switch( str[bNot ? 1 : 0] ) + { + case '%': + { + // Look for a cvar + ConVarRef cvar( str + (bNot ? 2 : 1), true ); + if (cvar.IsValid()) + { + return cvar.GetBool() ^ bNot; + } + } break; + + case '-': + { + // Look for a command line param + return (CommandLine()->CheckParm( bNot ? str+1 : str ) != 0) ^ bNot; + } break; + } +#endif return false; } From 1bf1225544d873c8ff507198d68f694a56ef99e3 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 16 Oct 2022 15:18:51 -0500 Subject: [PATCH 15/65] Incremented version numbers to v7.1 --- README | 2 +- sp/src/public/tier0/platform.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index d5ca32ee..8154a607 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ //=================================================================================================================================================== - Mapbase v7.0 - Source 2013 + Mapbase v7.1 - Source 2013 https://github.com/mapbase-source/source-sdk-2013 https://www.moddb.com/mods/mapbase diff --git a/sp/src/public/tier0/platform.h b/sp/src/public/tier0/platform.h index 7ed61545..6d5751a8 100644 --- a/sp/src/public/tier0/platform.h +++ b/sp/src/public/tier0/platform.h @@ -1281,8 +1281,8 @@ PLATFORM_INTERFACE bool Is64BitOS(); //----------------------------------------------------------------------------- // General Mapbase version constants compiled into projects for versioning purposes //----------------------------------------------------------------------------- -#define MAPBASE_VERSION "7.0" -#define MAPBASE_VER_INT 7000 // For use in #if in a similar fashion to macros like _MSC_VER +#define MAPBASE_VERSION "7.1" +#define MAPBASE_VER_INT 7100 // For use in #if in a similar fashion to macros like _MSC_VER #endif From eb4d01a988f325569f479bce7f99e9ada9add22e Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 17 Oct 2022 10:15:05 -0500 Subject: [PATCH 16/65] Fixed commentary speakers and printname not being combined properly on Linux --- sp/src/game/client/c_point_commentary_node.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sp/src/game/client/c_point_commentary_node.cpp b/sp/src/game/client/c_point_commentary_node.cpp index d8d9ad4c..d65896b5 100644 --- a/sp/src/game/client/c_point_commentary_node.cpp +++ b/sp/src/game/client/c_point_commentary_node.cpp @@ -1705,13 +1705,16 @@ void CHudCommentary::FixupCommentaryLabels( const char *pszPrintName, const char } else { - static wchar_t iszPrintNameLocalized[MAX_SPEAKER_NAME]; + static wchar_t iszSpeakersLocalized[MAX_SPEAKER_NAME] = { 0 }; + static wchar_t iszPrintNameLocalized[MAX_SPEAKER_NAME] = { 0 }; + + wcsncpy( iszSpeakersLocalized, m_szSpeakers, sizeof( iszSpeakersLocalized ) / sizeof( wchar_t ) ); if (m_szSpeakers[0] == '#') { wchar_t *pwszSpeakers = g_pVGuiLocalize->Find( pszSpeakers ); if (pwszSpeakers) - wcsncpy( m_szSpeakers, pwszSpeakers, sizeof( m_szSpeakers ) / sizeof( wchar_t ) ); + wcsncpy( iszSpeakersLocalized, pwszSpeakers, sizeof( iszSpeakersLocalized ) / sizeof( wchar_t ) ); } if (pszPrintName[0] == '#' && pszLocal) @@ -1719,7 +1722,7 @@ void CHudCommentary::FixupCommentaryLabels( const char *pszPrintName, const char else g_pVGuiLocalize->ConvertANSIToUnicode( pszPrintName, iszPrintNameLocalized, sizeof( iszPrintNameLocalized ) ); - V_snwprintf( m_szSpeakers, sizeof( m_szSpeakers ), L"%ls ~ %ls", m_szSpeakers, iszPrintNameLocalized ); + V_snwprintf( m_szSpeakers, sizeof( m_szSpeakers ), L"%ls ~ %ls", iszSpeakersLocalized, iszPrintNameLocalized ); } } From a1ab1616c56589507af45e5674ee32ee360b14f0 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 17 Oct 2022 10:34:29 -0500 Subject: [PATCH 17/65] Added VScript functions for checking the platform the server/client is using --- .../shared/mapbase/vscript_funcs_shared.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp b/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp index 76934119..4c6d4817 100644 --- a/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp +++ b/sp/src/game/shared/mapbase/vscript_funcs_shared.cpp @@ -938,6 +938,26 @@ bool ScriptIsClient() #endif } +bool ScriptIsWindows() +{ + return IsWindows(); +} + +bool ScriptIsLinux() +{ + return IsLinux(); +} + +bool ScriptIsOSX() +{ + return IsOSX(); +} + +bool ScriptIsPosix() +{ + return IsPosix(); +} + // Notification printing on the right edge of the screen void NPrint( int pos, const char* fmt ) { @@ -1077,5 +1097,10 @@ void RegisterSharedScriptFunctions() ScriptRegisterFunction( g_pScriptVM, GetFrameCount, "Absolute frame counter" ); //ScriptRegisterFunction( g_pScriptVM, GetTickCount, "Simulation ticks" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsWindows, "IsWindows", "Returns true if the game is being run on a Windows machine." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsLinux, "IsLinux", "Returns true if the game is being run on a Linux machine." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsOSX, "IsOSX", "Returns true if the game is being run on an OSX machine." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsPosix, "IsPosix", "Returns true if the game is being run on a Posix machine." ); + RegisterScriptSingletons(); } From c2d2df8c4222cb177b7b16ff0a04985abbbd2373 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 17 Oct 2022 12:51:23 -0500 Subject: [PATCH 18/65] Fixed forgotten #include in KeyValues.cpp --- sp/src/tier1/KeyValues.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sp/src/tier1/KeyValues.cpp b/sp/src/tier1/KeyValues.cpp index 16fae59c..7ce91354 100644 --- a/sp/src/tier1/KeyValues.cpp +++ b/sp/src/tier1/KeyValues.cpp @@ -28,6 +28,9 @@ #include "utlhash.h" #include "UtlSortVector.h" #include "convar.h" +#ifdef MAPBASE +#include "icommandline.h" +#endif // memdbgon must be the last include file in a .cpp file!!! #include From 2272b75772cf21e361145e2e7b4ac2a390a6637f Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 17 Oct 2022 13:37:58 -0500 Subject: [PATCH 19/65] Disabled Discord/Mapbase RPC by default --- sp/src/game/client/client_base.vpc | 3 +++ sp/src/vpc_scripts/source_base.vpc | 2 +- sp/src/vpc_scripts/source_dll_win32_base.vpc | 3 --- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sp/src/game/client/client_base.vpc b/sp/src/game/client/client_base.vpc index daf5bf41..dcdb9ad3 100644 --- a/sp/src/game/client/client_base.vpc +++ b/sp/src/game/client/client_base.vpc @@ -1260,6 +1260,9 @@ $Project $Lib vtf $ImpLib steam_api + // Discord integration + $Lib "$LIBPUBLIC\discord-rpc" [$MAPBASE_RPC] + $Lib $LIBCOMMON/libcrypto [$POSIX] $ImpLib "$LIBCOMMON\curl" [$OSXALL] diff --git a/sp/src/vpc_scripts/source_base.vpc b/sp/src/vpc_scripts/source_base.vpc index fac51e1d..eb655e83 100644 --- a/sp/src/vpc_scripts/source_base.vpc +++ b/sp/src/vpc_scripts/source_base.vpc @@ -19,7 +19,7 @@ // Mapbase functionality conditionals $Conditional MAPBASE "1" // Equivalent to (and required for) our MAPBASE preprocessor defined below -$Conditional MAPBASE_RPC "1" // Toggles Mapbase's Rich Presence Client implementations +$Conditional MAPBASE_RPC "0" // Toggles Mapbase's Rich Presence Client implementations (requires discord-rpc.dll in game bin) $Conditional MAPBASE_VSCRIPT "1" // Toggles VScript implementation (note: interfaces still exist, just the provided implementation is not present) $Conditional NEW_RESPONSE_SYSTEM "1" // Toggles the new Response System library based on the Alien Swarm SDK diff --git a/sp/src/vpc_scripts/source_dll_win32_base.vpc b/sp/src/vpc_scripts/source_dll_win32_base.vpc index e69456ea..fdac37d0 100644 --- a/sp/src/vpc_scripts/source_dll_win32_base.vpc +++ b/sp/src/vpc_scripts/source_dll_win32_base.vpc @@ -141,9 +141,6 @@ $Project $Implib "$LIBPUBLIC\tier0" $Lib "$LIBPUBLIC\tier1" $Implib "$LIBPUBLIC\vstdlib" - - // Discord integration - $Lib "$LIBPUBLIC\discord-rpc" [$MAPBASE_RPC] } } From a2cf90e3ace85881ea61ec1c2720cff318fe75b9 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Mon, 17 Oct 2022 23:10:10 +0300 Subject: [PATCH 20/65] Remove redundant SquirrelSafeCheck instance --- sp/src/vscript/vscript_squirrel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sp/src/vscript/vscript_squirrel.cpp b/sp/src/vscript/vscript_squirrel.cpp index 3b1e87ab..ddb8069e 100644 --- a/sp/src/vscript/vscript_squirrel.cpp +++ b/sp/src/vscript/vscript_squirrel.cpp @@ -2779,7 +2779,6 @@ bool SquirrelVM::GenerateUniqueKey(const char* pszRoot, char* pBuf, int nBufSize static int keyIdx = 0; // This gets used for script scope, still confused why it needs to be inside IScriptVM // is it just to be a compatible name for CreateScope? - SquirrelSafeCheck safeCheck(vm_); V_snprintf(pBuf, nBufSize, "%08X_%s", ++keyIdx, pszRoot); return true; } From b5428d5a77bf6b5275ab6fb97cf0c41213017018 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Thu, 20 Oct 2022 23:33:43 -0500 Subject: [PATCH 21/65] Fixed Response System not including scripts on Linux --- sp/src/game/server/AI_ResponseSystem.cpp | 3 ++- sp/src/responserules/runtime/response_system.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sp/src/game/server/AI_ResponseSystem.cpp b/sp/src/game/server/AI_ResponseSystem.cpp index 43fc871b..a46ddb36 100644 --- a/sp/src/game/server/AI_ResponseSystem.cpp +++ b/sp/src/game/server/AI_ResponseSystem.cpp @@ -2025,7 +2025,8 @@ void CResponseSystem::ParseInclude( CStringPool &includedFiles ) if (len+1 != strlen(scriptfile)) { - Q_snprintf(includefile, sizeof(includefile), "%s/%s", includefile, token); + Q_strncat( includefile, "/", sizeof( includefile ) ); + Q_strncat( includefile, token, sizeof( includefile ) ); } else includefile[0] = '\0'; diff --git a/sp/src/responserules/runtime/response_system.cpp b/sp/src/responserules/runtime/response_system.cpp index 653c5cbf..7ae9276c 100644 --- a/sp/src/responserules/runtime/response_system.cpp +++ b/sp/src/responserules/runtime/response_system.cpp @@ -1509,7 +1509,8 @@ void CResponseSystem::ParseInclude() if (len+1 != strlen(scriptfile)) { - Q_snprintf(includefile, sizeof(includefile), "%s/%s", includefile, token); + Q_strncat( includefile, "/", sizeof( includefile ) ); + Q_strncat( includefile, token, sizeof( includefile ) ); } else includefile[0] = '\0'; From d93a2f0b1717c59d7ebc70fab361320a1f3b0297 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Fri, 21 Oct 2022 10:14:51 -0500 Subject: [PATCH 22/65] Added shadow filter keyvalue to env_projectedtexture --- sp/src/game/client/C_Env_Projected_Texture.h | 1 + sp/src/game/client/c_env_projectedtexture.cpp | 3 +++ sp/src/game/server/env_projectedtexture.cpp | 9 +++++++++ sp/src/game/server/env_projectedtexture.h | 3 +++ 4 files changed, 16 insertions(+) diff --git a/sp/src/game/client/C_Env_Projected_Texture.h b/sp/src/game/client/C_Env_Projected_Texture.h index 6fbb6f12..cb626814 100644 --- a/sp/src/game/client/C_Env_Projected_Texture.h +++ b/sp/src/game/client/C_Env_Projected_Texture.h @@ -92,6 +92,7 @@ private: float m_flLinearAtten; float m_flQuadraticAtten; float m_flShadowAtten; + float m_flShadowFilter; bool m_bAlwaysDraw; //bool m_bProjectedTextureVersion; diff --git a/sp/src/game/client/c_env_projectedtexture.cpp b/sp/src/game/client/c_env_projectedtexture.cpp index 7bd15a17..66449652 100644 --- a/sp/src/game/client/c_env_projectedtexture.cpp +++ b/sp/src/game/client/c_env_projectedtexture.cpp @@ -60,6 +60,7 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvPro RecvPropFloat( RECVINFO( m_flLinearAtten ) ), RecvPropFloat( RECVINFO( m_flQuadraticAtten ) ), RecvPropFloat( RECVINFO( m_flShadowAtten ) ), + RecvPropFloat( RECVINFO( m_flShadowFilter ) ), RecvPropBool( RECVINFO( m_bAlwaysDraw ) ), // Not needed on the client right now, change when it actually is needed @@ -97,6 +98,7 @@ C_EnvProjectedTexture *C_EnvProjectedTexture::Create( ) pEnt->m_flLinearAtten = 100.0f; pEnt->m_flQuadraticAtten = 0.0f; pEnt->m_flShadowAtten = 0.0f; + pEnt->m_flShadowFilter = 0.5f; //pEnt->m_bProjectedTextureVersion = 1; #endif @@ -403,6 +405,7 @@ void C_EnvProjectedTexture::UpdateLight( void ) state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat(); state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat(); state.m_flShadowAtten = m_flShadowAtten; + state.m_flShadowFilterSize = m_flShadowFilter; #else state.m_fQuadraticAtten = 0.0; state.m_fLinearAtten = 100; diff --git a/sp/src/game/server/env_projectedtexture.cpp b/sp/src/game/server/env_projectedtexture.cpp index 0299fbd0..15fb1367 100644 --- a/sp/src/game/server/env_projectedtexture.cpp +++ b/sp/src/game/server/env_projectedtexture.cpp @@ -50,6 +50,7 @@ BEGIN_DATADESC( CEnvProjectedTexture ) DEFINE_FIELD( m_flLinearAtten, FIELD_FLOAT ), DEFINE_FIELD( m_flQuadraticAtten, FIELD_FLOAT ), DEFINE_KEYFIELD( m_flShadowAtten, FIELD_FLOAT, "shadowatten" ), + DEFINE_KEYFIELD( m_flShadowFilter, FIELD_FLOAT, "shadowfilter" ), #endif DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), @@ -77,6 +78,7 @@ BEGIN_DATADESC( CEnvProjectedTexture ) DEFINE_INPUTFUNC( FIELD_FLOAT, "SetLinear", InputSetLinear ), DEFINE_INPUTFUNC( FIELD_FLOAT, "SetConstant", InputSetConstant ), DEFINE_INPUTFUNC( FIELD_FLOAT, "SetShadowAtten", InputSetShadowAtten ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFilter", InputSetFilter ), DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearZ", InputSetNearZ ), DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFarZ", InputSetFarZ ), DEFINE_INPUTFUNC( FIELD_VOID, "AlwaysDrawOn", InputAlwaysDrawOn ), @@ -116,6 +118,7 @@ IMPLEMENT_SERVERCLASS_ST( CEnvProjectedTexture, DT_EnvProjectedTexture ) SendPropFloat( SENDINFO( m_flLinearAtten ) ), SendPropFloat( SENDINFO( m_flQuadraticAtten ) ), SendPropFloat( SENDINFO( m_flShadowAtten ) ), + SendPropFloat( SENDINFO( m_flShadowFilter ) ), SendPropBool( SENDINFO( m_bAlwaysDraw ) ), // Not needed on the client right now, change when it actually is needed @@ -158,6 +161,7 @@ CEnvProjectedTexture::CEnvProjectedTexture( void ) m_flLinearAtten = 100.0f; m_flConstantAtten = 0.0f; m_flShadowAtten = 0.0f; + m_flShadowFilter = 0.5f; #endif } @@ -316,6 +320,11 @@ void CEnvProjectedTexture::InputSetHorFOV( inputdata_t &inputdata ) { m_flLightHorFOV = inputdata.value.Float(); } + +void CEnvProjectedTexture::InputSetFilter( inputdata_t &inputdata ) +{ + m_flShadowFilter = inputdata.value.Float(); +} #endif void CEnvProjectedTexture::InputSetTarget( inputdata_t &inputdata ) diff --git a/sp/src/game/server/env_projectedtexture.h b/sp/src/game/server/env_projectedtexture.h index 06ff04ee..6cb248ba 100644 --- a/sp/src/game/server/env_projectedtexture.h +++ b/sp/src/game/server/env_projectedtexture.h @@ -64,6 +64,7 @@ public: void InputAlwaysDrawOff( inputdata_t &inputdata ) { m_bAlwaysDraw = false; } void InputStopFollowingTarget( inputdata_t &inputdata ) { m_bDontFollowTarget = true; } void InputStartFollowingTarget( inputdata_t &inputdata ) { m_bDontFollowTarget = false; } + void InputSetFilter( inputdata_t &inputdata ); // Corrects keyvalue/input attenuation for internal FlashlightEffect_t attenuation. float CorrectConstantAtten( float fl ) { return fl * 0.5f; } @@ -105,6 +106,8 @@ private: CNetworkVar( float, m_flQuadraticAtten ); CNetworkVar( float, m_flShadowAtten ); + CNetworkVar( float, m_flShadowFilter ); + CNetworkVar( bool, m_bAlwaysDraw ); // 1 = New projected texture From e2569f66572d40a0175ea4bb75ae0ff279cda740 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Fri, 21 Oct 2022 10:20:01 -0500 Subject: [PATCH 23/65] Fixed Linux debug build --- sp/src/game/shared/mapbase/vscript_singletons.cpp | 8 ++++---- sp/src/materialsystem/stdshaders/decalmodulate_dx9.cpp | 2 +- sp/src/public/vscript/ivscript.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 8f821e6c..0266fac9 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -1424,7 +1424,7 @@ void CNetMsgScriptHelper::ReceiveMessage( bf_read &msg ) m_MsgIn.StartReading( msg.m_pData, msg.m_nDataBytes ); #endif - DebugNetMsg( 2, DLL_LOC_STR " " __FUNCTION__ "()\n" ); + DebugNetMsg( 2, DLL_LOC_STR " %s()", __FUNCTION__ ); // Don't do anything if there's no VM here. This can happen if a message from the server goes to a VM-less client, or vice versa. if ( !g_pScriptVM ) @@ -1483,7 +1483,7 @@ void CNetMsgScriptHelper::Start( const char *msg ) return; } - DebugNetMsg( 1, DLL_LOC_STR " " __FUNCTION__ "() [%d]%s\n", Hash( msg ), msg ); + DebugNetMsg( 1, DLL_LOC_STR " %s() [%d]%s\n", __FUNCTION__, Hash( msg ), msg ); #ifdef CLIENT_DLL // Client can write multiple messages in a frame before the usercmd is sent, @@ -1519,7 +1519,7 @@ void CNetMsgScriptHelper::Start( const char *msg ) //----------------------------------------------------------------------------- void CNetMsgScriptHelper::Send( HSCRIPT player, bool bReliable ) { - DebugNetMsg( 1, DLL_LOC_STR " " __FUNCTION__ "() size(%d)\n", GetNumBitsWritten() ); + DebugNetMsg( 1, DLL_LOC_STR " %s() size(%d)\n", __FUNCTION__, GetNumBitsWritten() ); CBaseEntity *pPlayer = ToEnt(player); if ( pPlayer ) @@ -1544,7 +1544,7 @@ void CNetMsgScriptHelper::Send( HSCRIPT player, bool bReliable ) //----------------------------------------------------------------------------- void CNetMsgScriptHelper::Send() { - DebugNetMsg( 1, DLL_LOC_STR " " __FUNCTION__ "() size(%d)\n", m_bWriteIgnore ? 0 : GetNumBitsWritten() ); + DebugNetMsg( 1, DLL_LOC_STR " %s() size(%d)\n", __FUNCTION__, m_bWriteIgnore ? 0 : GetNumBitsWritten() ); m_bWriteReady = true; } diff --git a/sp/src/materialsystem/stdshaders/decalmodulate_dx9.cpp b/sp/src/materialsystem/stdshaders/decalmodulate_dx9.cpp index 1f0cf258..d1d0859f 100644 --- a/sp/src/materialsystem/stdshaders/decalmodulate_dx9.cpp +++ b/sp/src/materialsystem/stdshaders/decalmodulate_dx9.cpp @@ -225,7 +225,7 @@ BEGIN_VS_SHADER( SDK_DecalModulate_dx9, SetFlashLightColorFromState( state, pShaderAPI, 28 ); - Assert( state.m_pSpotlightTexture >= 0 && state.m_nSpotlightTextureFrame >= 0 ); + Assert( state.m_pSpotlightTexture && state.m_nSpotlightTextureFrame >= 0 ); BindTexture( SHADER_SAMPLER7, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); float atten_pos[8]; diff --git a/sp/src/public/vscript/ivscript.h b/sp/src/public/vscript/ivscript.h index 7d4ed0ea..58f981e0 100644 --- a/sp/src/public/vscript/ivscript.h +++ b/sp/src/public/vscript/ivscript.h @@ -1841,7 +1841,7 @@ public: scopemap_t *scopeMap = m_HookList.Element(i); char *szEvent = m_HookList.Key(i); - Msg( "%s [%x]\n", szEvent, (void*)scopeMap ); + Msg( "%s [%p]\n", szEvent, (void*)scopeMap ); Msg( "{\n" ); FOR_EACH_MAP_PTR( scopeMap, j ) @@ -1849,7 +1849,7 @@ public: HScriptRaw hScope = scopeMap->Key(j); contextmap_t *contextMap = scopeMap->Element(j); - Msg( "\t(0x%X) [%x]\n", hScope, (void*)contextMap ); + Msg( "\t(0x%X) [%p]\n", hScope, (void*)contextMap ); Msg( "\t{\n" ); FOR_EACH_VEC_PTR( contextMap, k ) From 03fffae585cbc7bb06cf70411d1c65caa200f4be Mon Sep 17 00:00:00 2001 From: Blixibon Date: Fri, 21 Oct 2022 10:21:09 -0500 Subject: [PATCH 24/65] Updated README --- README | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README b/README index 8154a607..af5c4c80 100644 --- a/README +++ b/README @@ -108,9 +108,11 @@ Direct contributions: - https://github.com/mapbase-source/source-sdk-2013/pull/116 (vgui_movie_display mute keyvalue from Alivebyte/rzkid) - https://github.com/mapbase-source/source-sdk-2013/pull/140 (logic_substring entity and icon created by moofemp) - https://github.com/mapbase-source/source-sdk-2013/pull/143 (Propper features for VBSP from Matty-64) +- https://github.com/mapbase-source/source-sdk-2013/pull/174 (Fix for multiply defined symbols in later toolsets from und) +- https://github.com/mapbase-source/source-sdk-2013/issues/201 (env_projectedtexture shadow filter keyvalue from celisej567) - 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) +- Custom HL2 ammo crate models created by Rykah (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 From 3f5807f1fd53796f58c92d6483a499c238b1fbea Mon Sep 17 00:00:00 2001 From: Blixibon Date: Fri, 21 Oct 2022 12:49:33 -0500 Subject: [PATCH 25/65] GitHub build workflows (#204) --- .github/CONTRIBUTING.md | 24 +- .github/labeler.yml | 27 ++ .../workflows/mapbase_build-base-dispatch.yml | 68 +++++ .github/workflows/mapbase_build-base.yml | 265 ++++++++++++++++++ .github/workflows/mapbase_build-sp-games.yml | 37 +++ .../workflows/mapbase_build-sp-maptools.yml | 38 +++ .../workflows/mapbase_build-sp-shaders.yml | 33 +++ .github/workflows/mapbase_pr.yml | 23 ++ sp/src/createmaptoolsprojects | 5 + sp/src/createmaptoolsprojects.bat | 1 + sp/src/createshadersprojects | 5 + sp/src/createshadersprojects.bat | 1 + sp/src/vpc_scripts/groups.vgc | 6 + .../vpc_scripts/source_exe_win_win32_base.vpc | 3 +- 14 files changed, 526 insertions(+), 10 deletions(-) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/mapbase_build-base-dispatch.yml create mode 100644 .github/workflows/mapbase_build-base.yml create mode 100644 .github/workflows/mapbase_build-sp-games.yml create mode 100644 .github/workflows/mapbase_build-sp-maptools.yml create mode 100644 .github/workflows/mapbase_build-sp-shaders.yml create mode 100644 .github/workflows/mapbase_pr.yml create mode 100755 sp/src/createmaptoolsprojects create mode 100644 sp/src/createmaptoolsprojects.bat create mode 100755 sp/src/createshadersprojects create mode 100644 sp/src/createshadersprojects.bat diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c51715cf..07391b88 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -23,12 +23,12 @@ All contributions must follow the following rules: is usually not fit for Mapbase. * All content in a contribution must be either already legally open-source or done with the - full permission of the content's original creator(s). If licensing is involved, the contribution - must ensure Mapbase follows said licensing. + full permission of the content's original creator(s). If a license is involved, the contributor + should ensure Mapbase conforms to its terms. * **NOTE:** Due to concerns with mods which do not wish to be open-source, content using GPL licenses (or any license with similar open-source requirements) are currently not allowed to be distributed with Mapbase. - Contributions which can draw from them without actually distributing the licensed content may theoretically - be excepted from this rule. + Contributions which can draw from them without actually distributing the licensed content may be excepted + from this rule. * Contributions must not break existing maps/content or interfere with them in a negative or non-objective way. @@ -41,13 +41,19 @@ All contributions must follow the following rules: * Do not modify the README to add attribution for your contribution. That is handled by Mapbase's maintainers. -Contributions which do not follow these guidelines cannot be accepted into Mapbase. - -Attempting to contribute content which seriously violates the rules above can lead to being blocked from contributing, -especially if done repeatedly. +Contributions which do not follow these guidelines cannot be accepted into Mapbase. Attempting to contribute content +which seriously violates the rules above can lead to being blocked from contributing, especially if done repeatedly. --- - + +Mapbase uses GitHub Actions to help manage issues and pull requests. Some of these workflows build the code of incoming +contributions to make sure they compile properly. The code is compiled separately for Visual Studio 2022 and GCC/G++ 9 (Linux) +and on both Debug and Release configurations. + +If these workflows fail, don't freak out! Accidents can happen frequently due to compiler syntax differences and conflicts +from other contributions. You can look at a failed workflow's log by clicking "Details", which will include the build's output. +Any errors must be resolved by you and/or by code reviewers before a pull request can be merged. + If your contribution is accepted, you may be listed in Mapbase's credits and the README's external content list: https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits#Contributors https://github.com/mapbase-source/source-sdk-2013/blob/master/README diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..cee65e07 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,27 @@ +# +# MAPBASE REPO AUTOMATION +# +# Automatically labels pull requests according to changed file paths. +# See mapbase_pr.yml for more information. +# +Repo: + - '*' + - '.github/**' + +Project Generation: + - '**/src/vpc_scripts/**' + - '**/src/devtools/**' + - '**/src/create*' + +Entities: + - '**/src/game/**/**logic**' + - '**/src/game/**/**point**' + +Shaders: + - '**/src/materialsystem/**' + +VScript: + - '**vscript**' + +Tools: + - '**utils**' \ No newline at end of file diff --git a/.github/workflows/mapbase_build-base-dispatch.yml b/.github/workflows/mapbase_build-base-dispatch.yml new file mode 100644 index 00000000..bd461597 --- /dev/null +++ b/.github/workflows/mapbase_build-base-dispatch.yml @@ -0,0 +1,68 @@ +# +# MAPBASE SOURCE 2013 CI +# +# This can be used to manually build the codebase. +# +# See mapbase_build-base.yml for more information on how this works. + +name: Build Projects (Manual) + +on: + workflow_dispatch: + inputs: + configuration: + description: 'Which configuration to build with' + default: 'Release' + required: true + type: choice + options: + - Release + - Debug + branch: + description: 'Which Source 2013 engine branch to compile for' + default: 'sp' + required: true + type: choice + options: + - sp + - mp + game: + description: 'Name of the game to build (if relevant)' + default: 'episodic' + required: false + type: choice + options: + - episodic + - hl2 + project-group: + description: 'Which group of projects to compile' + required: true + type: choice + options: + - all + - game + - shaders + - maptools + solution-name: + description: 'Name of the solution/makefile' + required: true + type: choice + options: + - everything + - games + - shaders + - maptools + build-on-linux: + description: 'Build on Ubuntu/Linux?' + default: true + required: false + type: boolean + +jobs: + build_manual: + uses: mapbase-source/source-sdk-2013/.github/workflows/mapbase_build-base.yml@feature/github-workflows + with: + configuration: '${{ github.event.inputs.configuration }}' + branch: '${{ github.event.inputs.branch }}' + project-group: '${{ github.event.inputs.project-group }}' + solution-name: '${{ github.event.inputs.solution-name }}' diff --git a/.github/workflows/mapbase_build-base.yml b/.github/workflows/mapbase_build-base.yml new file mode 100644 index 00000000..b5542f6e --- /dev/null +++ b/.github/workflows/mapbase_build-base.yml @@ -0,0 +1,265 @@ +# +# MAPBASE SOURCE 2013 CI +# +# This workflow script automatically builds the Source SDK 2013 codebase on Windows and Linux using GitHub Actions. +# +# This is useful in a number of ways: +# +# 1. It ensures pull requests compile correctly on multiple platforms and provides binaries that can be used to test them. +# 2. It can be used to compile code for releases without having to pull and prepare a local development environment. +# 3. It opens potential for scripts that can employ more principles of CI/CD. (e.g. automatically publishing a release) +# +# This is based on a workflow originally created by z33ky. + +name: Build Projects + +on: + workflow_call: + inputs: + configuration: + description: 'Which configuration to build with' + default: 'Release' + required: true + type: string + branch: + description: 'Which Source 2013 engine branch to compile for' + default: 'sp' + required: true + type: string + game: + description: 'The name of the game to build (if relevant)' + default: 'episodic' + required: false + type: string + project-group: + description: 'Which group of projects to compile' + required: true + type: string + solution-name: + description: 'The name of the solution/makefile' + required: true + type: string + build-on-linux: + description: 'Build on Ubuntu/Linux?' + default: true + required: false + type: boolean + +jobs: + build_windows: + name: Windows (VS2022) + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: Enable VS2022 + working-directory: '${{inputs.branch}}/src/vpc_scripts' + shell: bash + run: sed -i 's/^\($Conditional[ ]\+VS2022[ ]\+\).*/\1"1"/' newer_vs_toolsets.vpc + + - name: Pick game + if: inputs.project-group == 'game' || inputs.project-group == 'shaders' + working-directory: '${{inputs.branch}}/src' + shell: bash + run: sed -i 's/\/hl2 \/episodic/\/${{inputs.game}}/' create${{inputs.project-group}}projects.bat + + - name: Create project files + working-directory: '${{inputs.branch}}/src' + shell: cmd + # https://github.com/ValveSoftware/source-sdk-2013/issues/72 + run: | + reg add "HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\10.0\Projects\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" /v DefaultProjectExtension /t REG_SZ /d vcproj /f + create${{inputs.project-group}}projects.bat + + # -------------------------------------------------------------------- + + # "I'm invoking msbuild for each project individually, which looks a bit odd considering there is a solution file which should be able to invoke the builds in their proper order automatically, but passing the solution to msbuild doesn't seem to work." + # https://github.com/mapbase-source/source-sdk-2013/pull/162 + + - name: Build mathlib + #if: steps.filter.outputs.game == 'true' + working-directory: '${{inputs.branch}}/src' + shell: cmd + run: | + msbuild -m -p:Configuration=${{inputs.configuration}} mathlib\mathlib.vcxproj + + - name: Build Base Libraries + if: inputs.project-group == 'all' || inputs.project-group == 'game' || inputs.project-group == 'maptools' + working-directory: '${{inputs.branch}}/src' + shell: cmd + run: | + msbuild -m -p:Configuration=${{inputs.configuration}} raytrace\raytrace.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} tier1\tier1.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} vgui2\vgui_controls\vgui_controls.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} vscript\vscript.vcxproj + + - name: Build Map Tools + if: inputs.project-group == 'all' || inputs.project-group == 'maptools' + working-directory: '${{inputs.branch}}/src' + shell: cmd + run: | + msbuild -m -p:Configuration=${{inputs.configuration}} fgdlib\fgdlib.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} utils\vbsp\vbsp.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} utils\vvis\vvis_dll.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} utils\vvis_launcher\vvis_launcher.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} utils\vrad\vrad_dll.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} utils\vrad_launcher\vrad_launcher.vcxproj + + - name: Build Shaders + if: inputs.project-group == 'shaders' + working-directory: '${{inputs.branch}}/src' + shell: cmd + run: | + msbuild -m -p:Configuration=${{inputs.configuration}} materialsystem\stdshaders\game_shader_dx9_${{inputs.game}}.vcxproj + + - name: Build Game + if: inputs.project-group == 'game' + working-directory: '${{inputs.branch}}/src' + shell: cmd + run: | + msbuild -m -p:Configuration=${{inputs.configuration}} responserules\runtime\responserules.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} game\client\client_${{inputs.game}}.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} game\server\server_${{inputs.game}}.vcxproj + + # TODO: Hook to game naming? + - name: Build everything + if: inputs.project-group == 'all' + working-directory: '${{inputs.branch}}/src' + shell: cmd + run: | + msbuild -m -p:Configuration=${{inputs.configuration}} responserules\runtime\responserules.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} materialsystem\stdshaders\game_shader_dx9_episodic.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} materialsystem\stdshaders\game_shader_dx9_hl2.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} game\client\client_episodic.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} game\client\client_hl2.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} game\server\server_episodic.vcxproj + msbuild -m -p:Configuration=${{inputs.configuration}} game\server\server_hl2.vcxproj + + # -------------------------------------------------------------------- + + - name: Publish Windows game DLLs + if: inputs.project-group == 'all' || inputs.project-group == 'game' + uses: actions/upload-artifact@v3 + with: + name: 'Windows Game DLLs (server & client.dll) [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/mod_${{inputs.game}}/bin/client.dll + ${{inputs.branch}}/game/mod_${{inputs.game}}/bin/server.dll + if-no-files-found: error + + - name: Publish Windows shader DLL + if: inputs.project-group == 'shaders' + uses: actions/upload-artifact@v3 + with: + name: 'Windows Shader DLL (game_shader_dx9.dll) [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/mod_${{inputs.game}}/bin/game_shader_dx9.dll + if-no-files-found: error + + - name: Publish Windows map tools + if: inputs.project-group == 'maptools' + uses: actions/upload-artifact@v3 + with: + name: 'Windows Map Tools [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/bin/vbsp.exe + ${{inputs.branch}}/game/bin/vvis.exe + ${{inputs.branch}}/game/bin/vvis_dll.dll + ${{inputs.branch}}/game/bin/vrad.exe + ${{inputs.branch}}/game/bin/vrad_dll.dll + if-no-files-found: error + + - name: Publish everything (Windows) + if: inputs.project-group == 'all' + uses: actions/upload-artifact@v3 + with: + name: 'Everything (Windows) [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/bin + ${{inputs.branch}}/game/mod_*/bin + if-no-files-found: error + + build_ubuntu: + if: inputs.build-on-linux == true && inputs.project-group != 'maptools' # No Linux map tools for now + name: Ubuntu (GCC/G++) + runs-on: ubuntu-latest + env: + config: ${{ inputs.configuration }} + + steps: + - uses: actions/checkout@v3 + + - name: Install GCC/G++ multilib + run: sudo apt-get install gcc-multilib g++-multilib + + - name: Pick game + if: inputs.project-group == 'game' || inputs.project-group == 'shaders' + working-directory: '${{inputs.branch}}/src' + shell: bash + run: sed -i 's/\/hl2 \/episodic/\/${{inputs.game}}/' create${{inputs.project-group}}projects + + - name: Set configuration + working-directory: '${{inputs.branch}}/src' + shell: bash + run: | + config=${{inputs.configuration}} + export CFG=${config,,} + echo "config=${CFG}" >> $GITHUB_ENV + + - name: Create project files + working-directory: '${{inputs.branch}}/src' + run: sudo ./create${{inputs.project-group}}projects + + # -------------------------------------------------------------------- + + - name: Build + working-directory: '${{inputs.branch}}/src' + run: make CFG=${{env.config}} -f ${{inputs.solution-name}}.mak + + # -------------------------------------------------------------------- + + - name: Publish Linux game SOs + if: inputs.project-group == 'game' + uses: actions/upload-artifact@v3 + with: + name: 'Linux Game SOs (server & client.so) [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/mod_${{inputs.game}}/bin/client.so + ${{inputs.branch}}/game/mod_${{inputs.game}}/bin/server.so + if-no-files-found: error + + - name: Publish Linux shader SO + if: inputs.project-group == 'shaders' + uses: actions/upload-artifact@v3 + with: + name: 'Linux Shader SO (game_shader_dx9.so) [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/mod_${{inputs.game}}/bin/game_shader_dx9.so + if-no-files-found: error + + #- name: Publish Linux map tools + # if: inputs.project-group == 'maptools' + # uses: actions/upload-artifact@v3 + # with: + # name: 'Linux Map Tools [${{ inputs.configuration }}]' + # path: | + # ${{inputs.branch}}/game/bin/vbsp + # ${{inputs.branch}}/game/bin/vvis + # ${{inputs.branch}}/game/bin/vvis_dll.so + # ${{inputs.branch}}/game/bin/vrad + # ${{inputs.branch}}/game/bin/vrad_dll.so + # if-no-files-found: error + + - name: Publish everything (Linux) + if: inputs.project-group == 'all' + uses: actions/upload-artifact@v3 + with: + name: 'Everything (Linux) [${{ inputs.configuration }}]' + path: | + ${{inputs.branch}}/game/bin + ${{inputs.branch}}/game/mod_*/bin + if-no-files-found: error diff --git a/.github/workflows/mapbase_build-sp-games.yml b/.github/workflows/mapbase_build-sp-games.yml new file mode 100644 index 00000000..3e81ca72 --- /dev/null +++ b/.github/workflows/mapbase_build-sp-games.yml @@ -0,0 +1,37 @@ +# +# MAPBASE SOURCE 2013 CI +# +# Builds game projects every time a pull request which modifies the game code is opened. +# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs. +# +# See mapbase_build-base.yml for more information on how this works. + +name: Build Game Projects #(SP Release) + +on: + pull_request: + branches: + - develop + paths: + - '.github/workflows/mapbase_build-sp-rel-games.yml' + - 'sp/src/vpc_scripts/**' + - 'sp/src/game/**' + - 'sp/src/mathlib/**' + - 'sp/src/responserules/runtime/**' + - 'sp/src/tier1/**' + - 'sp/src/vgui2/vgui_controls/**' + - 'sp/src/vscript/**' + +jobs: + games: + strategy: + matrix: + configuration: [Release, Debug] + uses: ./.github/workflows/mapbase_build-base.yml + with: + configuration: ${{ matrix.configuration }} + branch: 'sp' + game: 'episodic' # Change this if your mod is not using HL2/Episodic game projects + project-group: 'game' + solution-name: 'games' + build-on-linux: true # Disable this if you don't want to compile for Linux diff --git a/.github/workflows/mapbase_build-sp-maptools.yml b/.github/workflows/mapbase_build-sp-maptools.yml new file mode 100644 index 00000000..0ae631b3 --- /dev/null +++ b/.github/workflows/mapbase_build-sp-maptools.yml @@ -0,0 +1,38 @@ +# +# MAPBASE SOURCE 2013 CI +# +# Builds map tool projects every time a pull request which modifies the map tool code is opened. +# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs. +# +# See mapbase_build-base.yml for more information on how this works. + +name: Build Map Tool Projects #(SP Release) + +on: + pull_request: + branches: + - develop + paths: + - '.github/workflows/mapbase_build-sp-rel-maptools.yml' + - 'sp/src/vpc_scripts/**' + - 'sp/src/utils/vbsp/**' + - 'sp/src/utils/vvis/**' + - 'sp/src/utils/vvis_launcher/**' + - 'sp/src/utils/vrad/**' + - 'sp/src/utils/vrad_launcher/**' + - 'sp/src/mathlib/**' + - 'sp/src/tier1/**' + - 'sp/src/vgui2/vgui_controls/**' + - 'sp/src/vscript/**' + +jobs: + maptools: + strategy: + matrix: + configuration: [Release, Debug] + uses: ./.github/workflows/mapbase_build-base.yml + with: + configuration: ${{ matrix.configuration }} + branch: 'sp' + project-group: 'maptools' + solution-name: 'maptools' diff --git a/.github/workflows/mapbase_build-sp-shaders.yml b/.github/workflows/mapbase_build-sp-shaders.yml new file mode 100644 index 00000000..73036e10 --- /dev/null +++ b/.github/workflows/mapbase_build-sp-shaders.yml @@ -0,0 +1,33 @@ +# +# MAPBASE SOURCE 2013 CI +# +# Builds shader projects every time a pull request which modifies the shader code is opened. +# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs. +# +# See mapbase_build-base.yml for more information on how this works. + +name: Build Shader Projects #(SP Release) + +on: + pull_request: + branches: + - develop + paths: + - '.github/workflows/mapbase_build-sp-rel-shaders.yml' + - 'sp/src/vpc_scripts/**' + - 'sp/src/materialsystem/**' + - 'sp/src/mathlib/**' + +jobs: + shaders: + strategy: + matrix: + configuration: [Release, Debug] + uses: ./.github/workflows/mapbase_build-base.yml + with: + configuration: ${{ matrix.configuration }} + branch: 'sp' + game: 'episodic' # Change this if your mod is not using HL2/Episodic game projects + project-group: 'shaders' + solution-name: 'shaders' + build-on-linux: true # Disable this if you don't want to compile for Linux diff --git a/.github/workflows/mapbase_pr.yml b/.github/workflows/mapbase_pr.yml new file mode 100644 index 00000000..f06982e4 --- /dev/null +++ b/.github/workflows/mapbase_pr.yml @@ -0,0 +1,23 @@ +# +# MAPBASE REPO AUTOMATION +# +# Automatically labels pull requests according to changed file paths. +# See mapbase_triage-pr.yml for more information. +# +# https://github.com/actions/labeler + +name: Pull Request Automation +on: [pull_request] + +jobs: + label: + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + + steps: + - uses: actions/labeler@v4 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/sp/src/createmaptoolsprojects b/sp/src/createmaptoolsprojects new file mode 100755 index 00000000..9cc950cb --- /dev/null +++ b/sp/src/createmaptoolsprojects @@ -0,0 +1,5 @@ +#!/bin/bash + +pushd `dirname $0` +devtools/bin/vpc /hl2 /episodic +maptools /mksln maptools +popd diff --git a/sp/src/createmaptoolsprojects.bat b/sp/src/createmaptoolsprojects.bat new file mode 100644 index 00000000..e21a53ff --- /dev/null +++ b/sp/src/createmaptoolsprojects.bat @@ -0,0 +1 @@ +devtools\bin\vpc.exe +maptools /mksln maptools.sln diff --git a/sp/src/createshadersprojects b/sp/src/createshadersprojects new file mode 100755 index 00000000..ff4823e0 --- /dev/null +++ b/sp/src/createshadersprojects @@ -0,0 +1,5 @@ +#!/bin/bash + +pushd `dirname $0` +devtools/bin/vpc /hl2 /episodic +shaders /mksln shaders +popd diff --git a/sp/src/createshadersprojects.bat b/sp/src/createshadersprojects.bat new file mode 100644 index 00000000..43569ae5 --- /dev/null +++ b/sp/src/createshadersprojects.bat @@ -0,0 +1 @@ +devtools\bin\vpc.exe /hl2 /episodic +shaders /mksln shaders.sln diff --git a/sp/src/vpc_scripts/groups.vgc b/sp/src/vpc_scripts/groups.vgc index 2ab187fa..b58dc416 100644 --- a/sp/src/vpc_scripts/groups.vgc +++ b/sp/src/vpc_scripts/groups.vgc @@ -26,9 +26,15 @@ $Group "game" "responserules" } +$Group "shaderdlls" +{ + "game_shader_dx9" +} + $Group "shaders" { "game_shader_dx9" + "mathlib" } $Group "everything" diff --git a/sp/src/vpc_scripts/source_exe_win_win32_base.vpc b/sp/src/vpc_scripts/source_exe_win_win32_base.vpc index a6d812ba..4d61b306 100644 --- a/sp/src/vpc_scripts/source_exe_win_win32_base.vpc +++ b/sp/src/vpc_scripts/source_exe_win_win32_base.vpc @@ -67,8 +67,9 @@ $Configuration $PostBuildEvent [!$ANALYZE] { + $CommandLine "if not exist $QUOTE$OUTBINDIR$QUOTE mkdir $QUOTE$OUTBINDIR$QUOTE" "\n" [($VS2015||$VS2017||$VS2019||$VS2022)] + $CommandLine "$BASE" "call $SRCDIR\vpc_scripts\valve_p4_edit.cmd $OUTBINDIR\$(TargetFileName) $SRCDIR" "\n" [!$SOURCESDK && ($VS2015||$VS2017||$VS2019||$VS2022)] $CommandLine "call $SRCDIR\vpc_scripts\valve_p4_edit.cmd $OUTBINDIR\$(TargetFileName) $SRCDIR" "\n" [!$SOURCESDK && !($VS2015||$VS2017||$VS2019||$VS2022)] - $CommandLine "if not exist $QUOTE$OUTBINDIR$QUOTE mkdir $QUOTE$OUTBINDIR$QUOTE" "\n" [!$SOURCESDK && ($VS2015||$VS2017||$VS2019||$VS2022)] $CommandLine "$BASE" "copy $QUOTE$(TargetDir)$QUOTE$(TargetFileName) $OUTBINDIR\$(TargetFileName) >nul" "\n" \ "if ERRORLEVEL 1 goto BuildEventFailed" "\n" \ "if exist $QUOTE$(TargetDir)$QUOTE$(TargetName).map copy $QUOTE$(TargetDir)$QUOTE$(TargetName).map $OUTBINDIR\$(TargetName).map >nul" "\n" From 3546bf9077aa78e1b3eb2ecb1999370b04229785 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sat, 22 Oct 2022 02:12:34 -0500 Subject: [PATCH 26/65] Added new labels to GitHub labeler --- .github/labeler.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index cee65e07..1166136f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -24,4 +24,12 @@ VScript: - '**vscript**' Tools: - - '**utils**' \ No newline at end of file + - '**utils**' + +NPCs: + - '**npc_**' + - '**ai_**' + +VGUI: + - '**hud_**' + - '**vgui_**' \ No newline at end of file From 00f00b508fc54bcb887c4b846e8197fb984efa7e Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sat, 22 Oct 2022 02:13:18 -0500 Subject: [PATCH 27/65] Updated README --- README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README b/README index af5c4c80..47b56b08 100644 --- a/README +++ b/README @@ -110,6 +110,8 @@ Direct contributions: - https://github.com/mapbase-source/source-sdk-2013/pull/143 (Propper features for VBSP from Matty-64) - https://github.com/mapbase-source/source-sdk-2013/pull/174 (Fix for multiply defined symbols in later toolsets from und) - https://github.com/mapbase-source/source-sdk-2013/issues/201 (env_projectedtexture shadow filter keyvalue from celisej567) +- https://github.com/mapbase-source/source-sdk-2013/pull/193 (RTB:R info_particle_system_coordinate by arbabf and Iridium77) +- https://github.com/mapbase-source/source-sdk-2013/pull/193 (Infinite prop_interactable cooldown by arbabf) - Demo autorecord code provided by Klems - cc_emit crash fix provided by 1upD - Custom HL2 ammo crate models created by Rykah (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code) @@ -131,6 +133,7 @@ Direct contributions: =-- https://github.com/mapbase-source/source-sdk-2013/pull/171 (VScript documentation sorting) =-- https://github.com/mapbase-source/source-sdk-2013/pull/173 (VScript fixes and optimizations) =-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes) +=-- https://github.com/mapbase-source/source-sdk-2013/pull/206 (Fix CScriptNetMsgHelper::WriteEntity()) == Contributions from z33ky: =-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes) From b5ba3f69c73c76cd3c72040763090d2080c5432f Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Wed, 22 Dec 2021 16:20:00 +0300 Subject: [PATCH 28/65] Add vscript vgui --- sp/src/game/client/client_mapbase.vpc | 6 +- sp/src/game/client/mapbase/vscript_vgui.cpp | 3710 +++++++++++++++++++ sp/src/game/client/mapbase/vscript_vgui.h | 16 + sp/src/game/client/mapbase/vscript_vgui.nut | 395 ++ sp/src/game/client/vscript_client.cpp | 31 +- 5 files changed, 4133 insertions(+), 25 deletions(-) create mode 100644 sp/src/game/client/mapbase/vscript_vgui.cpp create mode 100644 sp/src/game/client/mapbase/vscript_vgui.h create mode 100644 sp/src/game/client/mapbase/vscript_vgui.nut diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index 97a2217d..f8860e24 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -59,7 +59,11 @@ $Project $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\logic_script_client.cpp" [$MAPBASE_VSCRIPT] - + + $File "mapbase\vscript_vgui.cpp" [$MAPBASE_VSCRIPT] + $File "mapbase\vscript_vgui.h" [$MAPBASE_VSCRIPT] + $File "mapbase\vscript_vgui.nut" [$MAPBASE_VSCRIPT] + $File "mapbase\c_func_clientclip.cpp" $File "mapbase\c_func_fake_worldportal.cpp" $File "mapbase\c_func_fake_worldportal.h" diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp new file mode 100644 index 00000000..61354093 --- /dev/null +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -0,0 +1,3710 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +// $NoKeywords: $ +// +// Author: samisalreadytaken +// +//=============================================================================// + + +#include "cbase.h" +#include "tier1/utlcommon.h" + +#include "inputsystem/iinputsystem.h" +#include "iinput.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "matsys_controls/matsyscontrols.h" +#include "VGuiMatSurface/IMatSystemSurface.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +//#include + +//#include "bitmap/tgaloader.h" + +#if !defined(NO_STEAM) +#include "steam/steam_api.h" +#include "vgui_avatarimage.h" +#endif + +#include "view.h" + +#include "vscript_vgui.h" +#include "vscript_vgui.nut" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//============================================================================= +// +// Exposing a new panel class (e.g. vgui::FileOpenDialog): +// +// 1. Create C++ bindings using 'CLASS_HELPER_INTERFACE( FileOpenDialog, Frame ){};' +// 2. Define script bindings using '#define DEFINE_VGUI_SCRIPTFUNC_FileOpenDialog()' +// 3. Create 'class CScript_FileOpenDialog : FileOpenDialog' with vgui message callbacks and overrides if needed +// 4. Create script helper using 'BEGIN_VGUI_HELPER( FileOpenDialog )', 'END_VGUI_HELPER()'. This determines the script class name. +// 5. Register script bindings with 'BEGIN_SCRIPTDESC_VGUI( FileOpenDialog )', 'END_SCRIPTDESC()' +// 6. Add new condition in CScriptVGUI::CreatePanel() +// +// +// +// CScript_FileOpenDialog_Helper +// ^^ +// IScript_FileOpenDialog << CScript_FileOpenDialog +// ^^ ^^ +// IScript_Frame FileOpenDialog +// ^^ ^^ +// IScript_Panel Frame +// ^^ ^^ +// CScriptVGUIObject Panel +// +//============================================================================= + + +// When enabled, script panels will be parented to custom script root panels. +// When disabled, script panels will be parented to engine root panels, and allow Z values for script panels to be interplaced amongst non-script panels. +// Changing this is not backwards compatible, as existing top level script panel depth would then change relative to non-script panels. +#define SCRIPT_ENGINE_ROOT_PANELS 1 + +// On level transitions Restore is called up to 4 times in a row (due to .hl? client state files), each time +// trying to restore script panels from pre and post transitions, failing every time because script panels are +// destroyed on level shutdown but after client state files are written. +// +// Script variables are also reset between each OnRestore callback, causing duplicate panels if user scripts create panels +// by checking restored script variables. +// +// The workaround hack is to queue OnRestore callbacks with a think function. +// +// This code is left here for testing. +#define SCRIPT_VGUI_SAVERESTORE 0 + + +#ifdef _DEBUG +#define DebugMsg(...) ConColorMsg( Color(196, 196, 156, 255), __VA_ARGS__ ) +#define DebugWarning(...) Warning( __VA_ARGS__ ) +#define DebugDevMsg(...) DevMsg( __VA_ARGS__ ) + +#define DBG_PARAM(...) __VA_ARGS__ +#else +#define DebugMsg(...) (void)(0) +#define DebugWarning(...) (void)(0) +#define DebugDevMsg(...) (void)(0) + +#define DBG_PARAM(...) +#endif + + + +using namespace vgui; +class IScriptVGUIObject; +struct FontData_t; +template< typename T > class CCopyableUtlVectorConservative; + +// Aliases contain only one font definition unless 'yres' was defined +typedef CCopyableUtlVectorConservative< FontData_t > fontalias_t; +typedef CUtlDict< fontalias_t > CFontDict; + +template< typename T > +class CCopyableUtlVectorConservative : public CUtlVectorConservative< T > +{ + typedef CUtlVectorConservative< T > BaseClass; +public: + explicit CCopyableUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} + explicit CCopyableUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} + CCopyableUtlVectorConservative( CCopyableUtlVectorConservative const& vec ) { this->CopyArray( vec.Base(), vec.Count() ); } +}; + + + +CFontDict g_ScriptFonts( k_eDictCompareTypeCaseSensitive ); +CUtlVector< int > g_ScriptTextureIDs; +CUtlLinkedList< IScriptVGUIObject*, unsigned short > g_ScriptPanels; + + +// Boundary is not checked in Surface, keep count manually to sanitise user input. +static int g_nFontCount = 0; + +static inline HFont IntToFontHandle( int i ) +{ + if ( i < 0 || i > g_nFontCount ) + return INVALID_FONT; + return static_cast< unsigned int >(i); +} + +// vscript does not support unsigned int, +// but the representation of the handle does not matter, +// and these handles are CUtlVector indices +static inline int HandleToInt( unsigned int i ) +{ + return static_cast< int >(i); +} + + +struct FontData_t +{ + HFont font; + char *name; + int tall; + int weight; + int blur; + int scanlines; + int flags; + //int range_min; + //int range_max; + int yres_min; + int yres_max; + bool proportional; +}; + +static const char *GetFixedFontName( const char *name, bool proportional ) +{ + static char fontName[64]; + V_snprintf( fontName, sizeof(fontName), "%s-%s", name, proportional ? "p" : "no" ); + return fontName; +} + +CON_COMMAND( vgui_spew_fonts_script, "" ) +{ + char fontName[64]; + + FOR_EACH_DICT_FAST( g_ScriptFonts, i ) + { + const FontData_t &data = g_ScriptFonts[i].Head(); + const char *name = surface()->GetFontName( data.font ); + const char *alias = g_ScriptFonts.GetElementName(i); + + // Strip off the appendix "-p" / "-no" + V_StrLeft( alias, V_strlen(alias) - (data.proportional ? 2 : 3), fontName, sizeof(fontName) ); + + Msg( " %2d: HFont:0x%8.8lx, %s, %s, font:%s, tall:%d(%d) {%d}\n", + i, + data.font, + fontName, + alias, + name ? name : "??", + surface()->GetFontTall( data.font ), + surface()->GetFontTallRequested( data.font ), + g_ScriptFonts[i].Count() ); + } +} + +bool LoadFont( const FontData_t &font DBG_PARAM(, const char *fontAlias) ) +{ + if ( font.yres_min ) + { + int nScreenWide, nScreenTall; + surface()->GetScreenSize( nScreenWide, nScreenTall ); + + if ( nScreenTall < font.yres_min ) + return false; + + if ( font.yres_max && nScreenTall > font.yres_max ) + return false; + } + + int tall = font.tall; + int blur = font.blur; + int scanlines = font.scanlines; + + if ( font.proportional && !font.yres_min ) + { + tall = scheme()->GetProportionalScaledValue( tall ); + blur = scheme()->GetProportionalScaledValue( blur ); + scanlines = scheme()->GetProportionalScaledValue( scanlines ); + } + + bool bSuccess = surface()->SetFontGlyphSet( + font.font, + font.name, + tall, + font.weight, + blur, + scanlines, + font.flags ); + + NOTE_UNUSED( bSuccess ); + if ( bSuccess ) + { + if ( font.yres_min ) + DebugMsg( "Load font [%li]%s [%d %d]\n", font.font, fontAlias, font.yres_min, font.yres_max ); + else + DebugMsg( "Load font [%li]%s\n", font.font, fontAlias ); + } + else + { + DebugWarning( "Failed to load font [%li]%s\n", font.font, fontAlias ); + } + + return true; +} + +void ReloadScriptFontGlyphs() +{ + // Invalidate cached values + if ( g_pScriptVM ) + g_pScriptVM->Run( "ISurface.__OnScreenSizeChanged()" ); + + FOR_EACH_DICT_FAST( g_ScriptFonts, i ) + { + const fontalias_t &alias = g_ScriptFonts[i]; + for ( int j = 0; j < alias.Count(); ++j ) + { + if ( LoadFont( alias.Element(j) DBG_PARAM(, g_ScriptFonts.GetElementName(i)) ) ) + break; + } + } +} + + +static inline void InitRootPanel( Panel *p, VGuiPanel_t parent, const char *name ) +{ + int w, h; + surface()->GetScreenSize( w, h ); + p->Init( 0, 0, w, h ); + p->SetName( name ); + p->SetVisible( true ); + p->SetPaintEnabled( false ); + p->SetPaintBackgroundEnabled( false ); + p->SetPaintBorderEnabled( false ); + p->SetPostChildPaintEnabled( false ); + p->SetParent( enginevgui->GetPanel( parent ) ); +} + +class CScriptRootPanel : public Panel +{ +public: + CScriptRootPanel() + { + InitRootPanel( this, PANEL_ROOT, "VScriptRoot" ); + } + + void OnTick() + { + if ( m_nLastFrame == gpGlobals->framecount ) + return; + + ReloadScriptFontGlyphs(); + ivgui()->RemoveTickSignal( GetVPanel() ); + } + + // Used as a callback to font invalidation. + // Ideally script fonts would be loaded along with others in engine. + // In that case CScriptRootPanel would be removed, and + // g_pScriptRootPanel would be CScriptRootDLLPanel inside #if SCRIPT_ENGINE_ROOT_PANELS + void OnScreenSizeChanged( int, int ) + { + // Reload fonts in the next vgui frame + ivgui()->AddTickSignal( GetVPanel() ); + m_nLastFrame = gpGlobals->framecount; + + // Invalidate cached values + if ( g_pScriptVM ) + g_pScriptVM->Run( "ISurface.__OnScreenSizeChanged()" ); + } + +private: + int m_nLastFrame; +}; + +CScriptRootPanel *g_pScriptRootPanel = NULL; + +#if SCRIPT_ENGINE_ROOT_PANELS +class CScriptRootDLLPanel : public Panel +{ +public: + CScriptRootDLLPanel( VGuiPanel_t parent, const char *name ) + { + InitRootPanel( this, parent, name ); + } +}; + +CScriptRootDLLPanel *g_pScriptClientDLLPanel = NULL; +#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL +CScriptRootDLLPanel *g_pScriptGameUIDLLPanel = NULL; +#endif +#endif + +void VGUI_DestroyScriptRootPanels() +{ + if ( g_pScriptRootPanel ) + { + delete g_pScriptRootPanel; + g_pScriptRootPanel = NULL; + } +#if SCRIPT_ENGINE_ROOT_PANELS + if ( g_pScriptClientDLLPanel ) + { + delete g_pScriptClientDLLPanel; + g_pScriptClientDLLPanel = NULL; + } +#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL + if ( g_pScriptGameUIDLLPanel ) + { + delete g_pScriptGameUIDLLPanel; + g_pScriptGameUIDLLPanel = NULL; + } +#endif +#endif +} + +VPANEL VGUI_GetScriptRootPanel( VGuiPanel_t type ) +{ +#if !SCRIPT_ENGINE_ROOT_PANELS + if ( !g_pScriptRootPanel ) + g_pScriptRootPanel = new CScriptRootPanel(); + + return enginevgui->GetPanel( type ); +#else + switch ( type ) + { + case PANEL_ROOT: + { + if ( !g_pScriptRootPanel ) + g_pScriptRootPanel = new CScriptRootPanel(); + + return g_pScriptRootPanel->GetVPanel(); + } + case PANEL_CLIENTDLL: + { + if ( !g_pScriptClientDLLPanel ) + g_pScriptClientDLLPanel = new CScriptRootDLLPanel( PANEL_CLIENTDLL, "VScriptClient" ); + + return g_pScriptClientDLLPanel->GetVPanel(); + } +#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL + case PANEL_GAMEUIDLL: + { + if ( !g_pScriptGameUIDLLPanel ) + g_pScriptGameUIDLLPanel = new CScriptRootDLLPanel( PANEL_GAMEUIDLL, "VScriptGameUI" ); + + return g_pScriptGameUIDLLPanel->GetVPanel(); + } +#endif + } + return NULL; +#endif +} + + +// +// Escapes "vgui/" prepended to the file name in CSchemeManager::GetImage(). +// +IImage *vgui_GetImage( const char *imageName, bool hardwareFilter ) +{ + char fileName[MAX_PATH]; + V_snprintf( fileName, sizeof( fileName ), "../%s", imageName ); + + return scheme()->GetImage( fileName, hardwareFilter ); +} + + +//-------------------------------------------------------------- +// +//-------------------------------------------------------------- +class CScriptSurface +{ +public: + void PlaySound( const char* sound ); + void SetColor( int r, int g, int b, int a ); + void DrawFilledRect( int x0, int y0, int width, int height ); + void DrawFilledRectFade( int x0, int y0, int width, int height, int a0, int a1, bool bHorz ); + void DrawOutlinedRect( int x0, int y0, int width, int height, int thickness ); + void DrawLine( int x0, int y0, int x1, int y1 ); + void DrawOutlinedCircle( int x, int y, int radius, int segments ); + //void DrawColoredCircle( int x, int y, int radius, int r, int g, int b, int a ); + + void SetTextColor( int r, int g, int b, int a ); + void SetTextPos( int x, int y ); + void SetTextFont( int font ); + void DrawText( const char *text, int drawType/* = FONT_DRAW_DEFAULT*/ ); + void DrawUnicodeChar( int ch, int drawType/* = FONT_DRAW_DEFAULT*/ ); + + int GetFont( const char* name, bool proportional, const char* schema ); + int GetTextWidth( int font, const char* text ); + int GetFontTall( int font ); + int GetCharacterWidth( int font, int ch ); + + void CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional ); + bool AddCustomFontFile( const char *fontFileName ); + int GetTextureID( char const *filename ); + int ValidateTexture( const char *filename, bool hardwareFilter, bool forceReload, bool procedural ); + void SetTextureFile( int id, const char *filename, bool hardwareFilter ); + //int ValidateMaterial( const char *materialName, const char *textureGroupName ); + int GetTextureWide( int id ); + int GetTextureTall( int id ); + void SetTexture( int id ); + + void DrawTexturedRect( int x0, int y0, int width, int height ); + void DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 ); + + // ------------------------------------------------------------ + // Utility functions + // ------------------------------------------------------------ + + void DrawTexturedBox( int texture, int x, int y, int wide, int tall, int r, int g, int b, int a ); + void DrawColoredText( int font, int x, int y, int r, int g, int b, int a, const char *text ); + void DrawColoredTextRect( int font, int x, int y, int w, int h, int r, int g, int b, int a, const char *text ); + void DrawTexturedRectRotated( int x, int y, int w, int t, float yaw ); + +} script_surface; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptSurface, "ISurface", SCRIPT_SINGLETON ) + DEFINE_SCRIPTFUNC( PlaySound, "" ) + + DEFINE_SCRIPTFUNC( SetColor, "" ) + DEFINE_SCRIPTFUNC( DrawFilledRect, "" ) + DEFINE_SCRIPTFUNC( DrawFilledRectFade, "" ) + DEFINE_SCRIPTFUNC( DrawOutlinedRect, "" ) + DEFINE_SCRIPTFUNC( DrawLine, "" ) + DEFINE_SCRIPTFUNC( DrawOutlinedCircle, "" ) + + DEFINE_SCRIPTFUNC( SetTextColor, "" ) + DEFINE_SCRIPTFUNC( SetTextPos, "" ) + DEFINE_SCRIPTFUNC( SetTextFont, "" ) + DEFINE_SCRIPTFUNC( DrawText, "" ) + DEFINE_SCRIPTFUNC( DrawUnicodeChar, "" ) + + DEFINE_SCRIPTFUNC( GetFont, "" ) + DEFINE_SCRIPTFUNC( GetTextWidth, "" ) + DEFINE_SCRIPTFUNC( GetFontTall, "" ) + DEFINE_SCRIPTFUNC( GetCharacterWidth, "" ) + + DEFINE_SCRIPTFUNC( CreateFont, SCRIPT_HIDE ) + DEFINE_SCRIPTFUNC( AddCustomFontFile, "" ) + + DEFINE_SCRIPTFUNC( GetTextureID, "" ) + DEFINE_SCRIPTFUNC( ValidateTexture, "" ) + DEFINE_SCRIPTFUNC( SetTextureFile, "" ) + DEFINE_SCRIPTFUNC( GetTextureWide, "" ) + DEFINE_SCRIPTFUNC( GetTextureTall, "" ) + DEFINE_SCRIPTFUNC( SetTexture, "" ) + + DEFINE_SCRIPTFUNC( DrawTexturedRect, "" ) + DEFINE_SCRIPTFUNC( DrawTexturedSubRect, "" ) + + DEFINE_SCRIPTFUNC( DrawTexturedBox, "" ) + DEFINE_SCRIPTFUNC( DrawColoredText, "" ) + DEFINE_SCRIPTFUNC( DrawColoredTextRect, "" ) + DEFINE_SCRIPTFUNC( DrawTexturedRectRotated, "" ) +END_SCRIPTDESC() + + +void CScriptSurface::PlaySound( const char* sound ) +{ + surface()->PlaySound(sound); +} + +void CScriptSurface::SetColor( int r, int g, int b, int a ) +{ + surface()->DrawSetColor( r, g, b, a ); +} + +void CScriptSurface::DrawFilledRect( int x0, int y0, int width, int height ) +{ + surface()->DrawFilledRect( x0, y0, x0 + width, y0 + height ); +} + +void CScriptSurface::DrawFilledRectFade( int x0, int y0, int width, int height, int a0, int a1, bool bHorz ) +{ + surface()->DrawFilledRectFade( x0, y0, x0 + width, y0 + height, a0, a1, bHorz ); +} + +void CScriptSurface::DrawOutlinedRect( int x0, int y0, int width, int height, int thickness ) +{ + int x1 = x0 + width; + int y1 = y0 + height - thickness; + y0 += thickness; + + surface()->DrawFilledRect( x0, y0 - thickness, x1, y0 ); // top + surface()->DrawFilledRect( x1 - thickness, y0, x1, y1 ); // right + surface()->DrawFilledRect( x0, y1, x1, y1 + thickness ); // bottom + surface()->DrawFilledRect( x0, y0, x0 + thickness, y1 ); // left +} + +void CScriptSurface::DrawLine( int x0, int y0, int x1, int y1 ) +{ + surface()->DrawLine( x0, y0, x1, y1 ); +} +#if 0 +void CScriptSurface::DrawPolyLine( HSCRIPT ax, HSCRIPT ay, int count ) +{ + if (count < 1) + return; + + if (count > 4096) + count = 4096; + + int *px = (int*)stackalloc( count * sizeof(int) ); + int *py = (int*)stackalloc( count * sizeof(int) ); + ScriptVariant_t vx, vy; + + int i = count; + while ( i-- ) + { + g_pScriptVM->GetValue( ax, i, &vx ); + g_pScriptVM->GetValue( ay, i, &vy ); + + px[i] = vx.m_int; + py[i] = vy.m_int; + } + + surface()->DrawPolyLine( px, py, count ); +} +#endif +void CScriptSurface::DrawOutlinedCircle( int x, int y, int radius, int segments ) +{ + surface()->DrawOutlinedCircle( x, y, radius, segments ); +} + +void CScriptSurface::SetTextColor( int r, int g, int b, int a ) +{ + surface()->DrawSetTextColor( r, g, b, a ); +} + +void CScriptSurface::SetTextPos( int x, int y ) +{ + surface()->DrawSetTextPos( x, y ); +} + +void CScriptSurface::SetTextFont( int font ) +{ + surface()->DrawSetTextFont( IntToFontHandle(font) ); +} + +void CScriptSurface::DrawText( const char *text, int drawType ) +{ + wchar_t wcs[512]; + g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); + surface()->DrawPrintText( wcs, wcslen(wcs), (FontDrawType_t)drawType ); +} + +void CScriptSurface::DrawUnicodeChar( int ch, int drawType ) +{ + surface()->DrawUnicodeChar( (wchar_t)ch, (FontDrawType_t)drawType ); +} + +int CScriptSurface::GetFont( const char* name, bool proportional, const char* schema ) +{ + HFont font = INVALID_FONT; + + if ( !schema || !schema[0] ) + { + int idx = g_ScriptFonts.Find( GetFixedFontName( name, proportional ) ); + if ( idx != g_ScriptFonts.InvalidIndex() ) + { + font = g_ScriptFonts[idx].Head().font; + } + } + else + { + HScheme sch = scheme()->GetScheme( schema ); + font = scheme()->GetIScheme(sch)->GetFont( name, proportional ); + + // Update known count + if ( font > (unsigned int)g_nFontCount ) + g_nFontCount = font; + } + + return HandleToInt( font ); +} + +int CScriptSurface::GetTextWidth( int font, const char* text ) +{ + int w, t; + wchar_t wcs[512]; + g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); + surface()->GetTextSize( IntToFontHandle(font), wcs, w, t ); + return w; +} + +int CScriptSurface::GetFontTall( int font ) +{ + return surface()->GetFontTall( IntToFontHandle(font) ); +} + +int CScriptSurface::GetCharacterWidth( int font, int ch ) +{ + return surface()->GetCharacterWidth( IntToFontHandle(font), ch ); +} + +void CScriptSurface::CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional ) +{ + if ( flags & ISurface::FONTFLAG_BITMAP ) + { + AssertMsg( 0, "Bitmap fonts are not supported!" ); + return; + } + + if ( proportional && yresMin ) + { + AssertMsg( 0, "Resolution cannot be defined on a proportional font!" ); + return; + } + + if ( (yresMin < 0 || yresMax < 0) || (!!yresMin != !!yresMax) ) + { + AssertMsg( 0, "Invalid resolution!" ); + return; + } + + const char *fontAlias = GetFixedFontName( customName, proportional ); + + int idx = g_ScriptFonts.Find( fontAlias ); + if ( idx != g_ScriptFonts.InvalidIndex() ) + { + fontalias_t &alias = g_ScriptFonts[idx]; + // TODO: One proportional font to fall back to amongst resolution filtered fonts. + +#ifdef _DEBUG + if ( !yresMin && !yresMax ) + { + // There must be only one font registered. + Assert( alias.Count() == 1 ); + + HFont font = alias.Head().font; + int oldTall = surface()->GetFontTallRequested( font ); + int newTall = proportional ? scheme()->GetProportionalScaledValue( tall ) : tall; + const char *oldName = surface()->GetFontName( font ); + + // Font changes will not be applied. + Assert( oldTall == newTall ); + if ( oldName ) // can be null + Assert( !V_stricmp( oldName, windowsFontName ) ); + } +#endif + + // if input resolutions match any of the existing fonts, + // then this must be a duplicate call. + for ( int i = 0; i < alias.Count(); ++i ) + { + FontData_t &data = alias.Element(i); + + if ( yresMin == data.yres_min && yresMax == data.yres_max ) + return; + } + + DebugMsg( "Create font add '%s' [%d %d]\n", fontAlias, yresMin, yresMax ); + + FontData_t &newFont = alias.Element( alias.AddToTail() ); + newFont.font = alias.Head().font; + newFont.name = strdup( windowsFontName ); + newFont.tall = tall; + newFont.weight = weight; + newFont.blur = blur; + newFont.scanlines = scanlines; + newFont.flags = flags; + newFont.yres_min = yresMin; + newFont.yres_max = yresMax; + newFont.proportional = proportional; + + LoadFont( newFont DBG_PARAM(, fontAlias) ); + } + else + { + HFont font = surface()->CreateFont(); + + // Sanity check + Assert( font > (unsigned int)g_nFontCount && font < INT_MAX ); + + // Update known count + if ( font > (unsigned int)g_nFontCount ) + g_nFontCount = font; + + if ( yresMax && yresMin > yresMax ) + { + int t = yresMin; + yresMin = yresMax; + yresMax = t; + } + + if ( yresMin ) + DebugMsg( "Create font new '%s' [%d %d]\n", fontAlias, yresMin, yresMax ); + else + DebugMsg( "Create font new '%s'\n", fontAlias ); + + fontalias_t &alias = g_ScriptFonts.Element( g_ScriptFonts.Insert( fontAlias ) ); + FontData_t &newFont = alias.Element( alias.AddToTail() ); + newFont.font = font; + newFont.name = strdup( windowsFontName ); + newFont.tall = tall; + newFont.weight = weight; + newFont.blur = blur; + newFont.scanlines = scanlines; + newFont.flags = flags; + newFont.yres_min = yresMin; + newFont.yres_max = yresMax; + newFont.proportional = proportional; + + LoadFont( newFont DBG_PARAM(, fontAlias) ); + } +} + +bool CScriptSurface::AddCustomFontFile( const char *fontFileName ) +{ + return surface()->AddCustomFontFile( NULL, fontFileName ); +} + +int CScriptSurface::GetTextureID( char const *filename ) +{ + return surface()->DrawGetTextureId( filename ); +} + +// Create texture if it does not already exist +int CScriptSurface::ValidateTexture( const char *filename, bool hardwareFilter, bool forceReload, bool procedural ) +{ + int id = surface()->DrawGetTextureId( filename ); + if ( id <= 0 ) + { + id = surface()->CreateNewTextureID( procedural ); + g_ScriptTextureIDs.AddToTail( id ); + + surface()->DrawSetTextureFile( id, filename, hardwareFilter, forceReload ); + +#ifdef _DEBUG + char tex[MAX_PATH]; + surface()->DrawGetTextureFile( id, tex, sizeof(tex)-1 ); + if ( !V_stricmp( filename, tex ) ) + { + DebugMsg( "Create texture [%i]%s\n", id, filename ); + } + else + { + DebugWarning( "Create texture [%i]%s(%s)\n", id, tex, filename ); + } +#endif + } + else if ( forceReload && g_ScriptTextureIDs.HasElement( id ) ) + { + surface()->DrawSetTextureFile( id, filename, hardwareFilter, forceReload ); + } + else + { + surface()->DrawSetTexture( id ); + } + + return id; +} + +// Replace existing texture +void CScriptSurface::SetTextureFile( int id, const char *filename, bool hardwareFilter ) +{ + if ( g_ScriptTextureIDs.HasElement(id) ) + { + Assert( surface()->IsTextureIDValid(id) ); + surface()->DrawSetTextureFile( id, filename, hardwareFilter, true ); + +#ifdef _DEBUG + char tex[MAX_PATH]; + surface()->DrawGetTextureFile( id, tex, sizeof(tex)-1 ); + if ( !V_stricmp( filename, tex ) ) + { + DebugMsg( "Set texture [%i]%s\n", id, filename ); + } + else + { + DebugWarning( "Set texture [%i]%s(%s)\n", id, tex, filename ); + } +#endif + } + +#ifdef _DEBUG + if ( !g_ScriptTextureIDs.HasElement(id) && surface()->IsTextureIDValid(id) ) + { + DebugWarning( "Tried to set non-script created texture! [%i]%s\n", id, filename ); + } + + if ( !surface()->IsTextureIDValid(id) ) + { + DebugWarning( "Tried to set invalid texture id! [%i]%s\n", id, filename ); + } +#endif +} + +int CScriptSurface::GetTextureWide( int id ) +{ + int w, t; + surface()->DrawGetTextureSize( id, w, t ); + return w; +} + +int CScriptSurface::GetTextureTall( int id ) +{ + int w, t; + surface()->DrawGetTextureSize( id, w, t ); + return t; +} + +void CScriptSurface::SetTexture( int id ) +{ + surface()->DrawSetTexture( id ); +} + +void CScriptSurface::DrawTexturedRect( int x0, int y0, int width, int height ) +{ + surface()->DrawTexturedRect( x0, y0, x0 + width, y0 + height ); +} + +void CScriptSurface::DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 ) +{ + surface()->DrawTexturedSubRect( x0, y0, x1, y1, texs0, text0, texs1, text1 ); +} + +void CScriptSurface::DrawTexturedRectRotated( int x, int y, int w, int t, float yaw ) +{ + Vertex_t verts[4]; + Vector2D axis[2]; + + float sy, cy; + SinCos( DEG2RAD( -yaw ), &sy, &cy ); + + axis[0].x = cy; + axis[0].y = sy; + axis[1].x = -axis[0].y; + axis[1].y = axis[0].x; + + verts[0].m_TexCoord.Init( 0, 0 ); + Vector2DMA( Vector2D( x + w * 0.5f, y + t * 0.5f ), w * -0.5f, axis[0], verts[0].m_Position ); + Vector2DMA( verts[0].m_Position, t * -0.5f, axis[1], verts[0].m_Position ); + + verts[1].m_TexCoord.Init( 1, 0 ); + Vector2DMA( verts[0].m_Position, w, axis[0], verts[1].m_Position ); + + verts[2].m_TexCoord.Init( 1, 1 ); + Vector2DMA( verts[1].m_Position, t, axis[1], verts[2].m_Position ); + + verts[3].m_TexCoord.Init( 0, 1 ); + Vector2DMA( verts[0].m_Position, t, axis[1], verts[3].m_Position ); + + surface()->DrawTexturedPolygon( 4, verts ); +} + +void CScriptSurface::DrawTexturedBox( int texture, int x, int y, int wide, int tall, int r, int g, int b, int a ) +{ + surface()->DrawSetColor( r, g, b, a ); + surface()->DrawSetTexture( texture ); + surface()->DrawTexturedRect( x, y, x + wide, y + tall ); +} + +void CScriptSurface::DrawColoredText( int font, int x, int y, int r, int g, int b, int a, const char *text ) +{ + wchar_t wcs[512]; + g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); + + surface()->DrawSetTextFont( IntToFontHandle(font) ); + surface()->DrawSetTextColor( r, g, b, a ); + surface()->DrawSetTextPos( x, y ); + surface()->DrawPrintText( wcs, wcslen(wcs) ); +} + +void CScriptSurface::DrawColoredTextRect( int font, int x, int y, int w, int h, int r, int g, int b, int a, const char *text ) +{ + MatSystemSurface()->DrawColoredTextRect( IntToFontHandle(font), x, y, w, h, r, g, b, a, text ); +} + + +//============================================================== +//============================================================== + +#define __base() this->_base + +#define BEGIN_SCRIPTDESC_VGUI( panelClass )\ + BEGIN_SCRIPTDESC_NAMED( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "" )\ + DEFINE_VGUI_SCRIPTFUNC_##panelClass() + +// +// Script helpers are wrappers that only redirect to VGUI panels (such as CScript_Panel : Panel), +// these macros help to simplify definitions. +// + +// +// BEGIN_VGUI_HELPER() assumes the VGUI panel class has the prefix 'CScript_' +// Use BEGIN_VGUI_HELPER_EX() to manually define VGUI panel class name. +// +#define BEGIN_VGUI_HELPER( panelClass )\ + BEGIN_VGUI_HELPER_EX( panelClass, CScript_##panelClass ) + +#define BEGIN_VGUI_HELPER_DEFAULT_TEXT( panelClass )\ + BEGIN_VGUI_HELPER_DEFAULT_TEXT_EX( panelClass, CScript_##panelClass ) + +#define BEGIN_VGUI_HELPER_EX( panelClass, baseClass )\ + class CScript_##panelClass##_Helper : public IScript_##panelClass< baseClass >\ + {\ + void Create( const char *panelName ) override\ + {\ + Assert( !_base && !_vpanel );\ + _base = new baseClass( NULL, panelName );\ + }\ +\ + public: + +#define BEGIN_VGUI_HELPER_DEFAULT_TEXT_EX( panelClass, baseClass )\ + class CScript_##panelClass##_Helper : public IScript_##panelClass< baseClass >\ + {\ + void Create( const char *panelName ) override\ + {\ + Assert( !_base && !_vpanel );\ + _base = new baseClass( NULL, panelName, (const char*)NULL );\ + }\ +\ + public: +#define END_VGUI_HELPER()\ + }; + + +#define CLASS_HELPER_INTERFACE_ROOT( panelClass )\ + template \ + class IScript_##panelClass : public CScriptVGUIObject + +#define CLASS_HELPER_INTERFACE( panelClass, baseClass )\ + template \ + class IScript_##panelClass : public IScript_##baseClass + + +#ifdef _DEBUG +#define DEBUG_DESTRUCTOR( panelClass, baseClass )\ + panelClass()\ + {\ + DebugDestructor( baseClass )\ + } + +#define DebugDestructor( panelClass )\ + {\ + DebugDevMsg( " ~" #panelClass "() '%s'\n", GetName() );\ + } +#else +#define DEBUG_DESTRUCTOR( panelClass, baseClass ) +#define DebugDestructor( panelClass ) +#endif + +#define DECLARE_SCRIPTVGUI_CLASS( baseClass )\ + DECLARE_SCRIPTVGUI_CLASS_EX( CScript_##baseClass, baseClass )\ + DEBUG_DESTRUCTOR( ~CScript_##baseClass, baseClass ) + +#define DECLARE_SCRIPTVGUI_CLASS_EX( panelClass, baseClass )\ + typedef baseClass BaseClass;\ + typedef panelClass ThisClass;\ +public:\ + void OnDelete()\ + {\ + DebugMsg( #baseClass "::OnDelete() '%s'\n", GetName() );\ + int i;\ + IScriptVGUIObject *obj = FindInScriptPanels( GetVPanel(), i );\ + if ( obj )\ + {\ + obj->Destroy( i );\ + }\ + BaseClass::OnDelete();\ + } + +// +// Definitions for 'empty' vgui objects that do not have any script specific implementation - overrides or callbacks. +// These are required to shutdown script objects on panel death +// (on save restore where panel destructor is called after the VM is restarted while HSCRIPT members are invalid but not nullified, +// and on C++ deletion where IScriptVGUIObject::Destroy() is not automatically called). +// +#define DEFINE_VGUI_CLASS_EMPTY( panelClass )\ + class CScript_##panelClass : public panelClass\ + {\ + DECLARE_SCRIPTVGUI_CLASS( panelClass )\ + void Shutdown() {}\ +\ + public:\ + CScript_##panelClass( Panel *parent, const char *name )\ + : BaseClass( parent, name )\ + {}\ + };\ +\ + BEGIN_VGUI_HELPER( panelClass )\ + END_VGUI_HELPER()\ +\ + BEGIN_SCRIPTDESC_VGUI( panelClass )\ + END_SCRIPTDESC() + +#define DEFINE_VGUI_CLASS_EMPTY_DEFAULT_TEXT( panelClass )\ + class CScript_##panelClass : public panelClass\ + {\ + DECLARE_SCRIPTVGUI_CLASS( panelClass )\ + void Shutdown() {}\ +\ + public:\ + CScript_##panelClass( Panel *parent, const char *name, const char *text )\ + : BaseClass( parent, name, text )\ + {}\ + };\ +\ + BEGIN_VGUI_HELPER_DEFAULT_TEXT( panelClass )\ + END_VGUI_HELPER()\ +\ + BEGIN_SCRIPTDESC_VGUI( panelClass )\ + END_SCRIPTDESC() + +class IScriptVGUIObject +{ +public: + virtual ~IScriptVGUIObject() {} + +#ifdef _DEBUG + virtual const char *GetName() = 0; +#endif + //----------------------------------------------------- + // Free the VGUI panel and script instance. + //----------------------------------------------------- + virtual void Destroy( int ) = 0; + + //----------------------------------------------------- + // Create new panel + //----------------------------------------------------- + virtual void Create( const char *panelName ) = 0; + +public: + VPANEL GetVPanel() { return _vpanel; } + HSCRIPT GetScriptInstance() { return m_hScriptInstance; } + +protected: + VPANEL _vpanel; + HSCRIPT m_hScriptInstance; + + // Called on deletion + static void ResolveChildren_r( VPANEL panel DBG_PARAM(, int level) ); + +public: +#if SCRIPT_VGUI_SAVERESTORE + IScriptVGUIObject() {} + void SetScriptInstance( HSCRIPT h ) { m_hScriptInstance = h; } + char m_pszScriptId[16]; +#endif + +#ifdef _DEBUG + #if SCRIPT_VGUI_SAVERESTORE + const char *GetDebugName() { return m_pszScriptId; } + #else + const char *GetDebugName() { return ""; } + #endif +#endif +}; + +BEGIN_SCRIPTDESC_ROOT( IScriptVGUIObject, SCRIPT_HIDE ) +END_SCRIPTDESC() + + +#if SCRIPT_VGUI_SAVERESTORE +class CScriptVGUIScriptInstanceHelper : public IScriptInstanceHelper +{ + void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId ) + { + DebugMsg( "BindOnRead (0x%p) (%s) (count %d)\n", (uint)hInstance, pszId, g_ScriptPanels.Count() ); + + FOR_EACH_LL( g_ScriptPanels, i ) + { + IScriptVGUIObject *pPanel = g_ScriptPanels[i]; + // DebugMsg( " cmp (%s)\n", pPanel->m_pszScriptId ); + if ( !V_stricmp( pPanel->m_pszScriptId, pszId ) ) + { + pPanel->SetScriptInstance( hInstance ); + DebugMsg( " ret (%s)\n", pPanel->m_pszScriptId ); + return pPanel; + } + } + DebugMsg( " ret (null)\n" ); + return NULL; + } +}; + +static CScriptVGUIScriptInstanceHelper g_ScriptVGUIScriptInstanceHelper; + +#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() DEFINE_SCRIPT_INSTANCE_HELPER( &g_ScriptVGUIScriptInstanceHelper ) +#else +#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() +#endif + + +IScriptVGUIObject *ToScriptVGUIObj( HSCRIPT inst ) +{ + return (IScriptVGUIObject *)g_pScriptVM->GetInstanceValue( inst, ::GetScriptDesc( (IScriptVGUIObject *)0 ) ); +} + +template < typename T > inline T* AllocScriptPanel() +{ + return new T; +} + +inline IScriptVGUIObject *FindInScriptPanels( VPANEL panel, int &I ) +{ + for ( int i = g_ScriptPanels.Head(); i != g_ScriptPanels.InvalidIndex(); i = g_ScriptPanels.Next(i) ) + { + IScriptVGUIObject *obj = g_ScriptPanels[i]; + if ( obj->GetVPanel() == panel ) + { + I = i; + return obj; + } + } + return NULL; +} + +void IScriptVGUIObject::ResolveChildren_r( VPANEL panel DBG_PARAM(, int level = 0) ) +{ +#ifdef _DEBUG + char indent[32]; + + int l = level, c = 0; + if ( l > 15 ) + l = 15; + + while ( l-- ) + { + indent[c++] = ' '; + indent[c++] = ' '; + } + indent[c] = 0; + + if ( level > 15 ) + { + indent[c-1] = '.'; + indent[c-2] = '.'; + } +#endif + + CUtlVector< VPANEL > &children = ipanel()->GetChildren( panel ); + FOR_EACH_VEC_BACK( children, i ) + { + VPANEL child = children[i]; + int j; + IScriptVGUIObject *obj = FindInScriptPanels( child, j ); + if ( obj ) + { + if ( ipanel()->IsAutoDeleteSet(child) ) + { + DebugMsg( " %sResolveChildren: '%s' (autodelete)\n", indent, obj->GetName() ); + + if ( g_pScriptVM ) + g_pScriptVM->RemoveInstance( obj->m_hScriptInstance ); + g_ScriptPanels.Remove( j ); + delete obj; + + ResolveChildren_r( child DBG_PARAM(, level+1) ); + } + else + { + DebugMsg( " %sResolveChildren: '%s'\n", indent, obj->GetName() ); + + // Panel::SetAutoDelete should not be added until + // what to do on their parent death is finalised. + // + // This assert will be hit if a deleted panel has + // C++ created and autodelete disabled children who are + // also registered to script. + Assert(0); + } + } + } +} + +template +class CScriptVGUIObject : public IScriptVGUIObject +{ +public: + T *_base; + + CScriptVGUIObject() : _base(0) + { + _vpanel = 0; + m_hScriptInstance = 0; + } + + void Destroy( int i = -1 ) + { + if ( i != -1 ) + { + Assert( g_ScriptPanels.IsValidIndex(i) ); + Assert( g_ScriptPanels[i] == this ); + + g_ScriptPanels.Remove( i ); + } + else + { + Assert( g_ScriptPanels.Find( this ) != g_ScriptPanels.InvalidIndex() ); + + g_ScriptPanels.FindAndRemove( this ); + } + + if ( GetVPanel() ) + { + DebugMsg( " Destroy panel '%s' %s\n", _base->GetName(), GetDebugName() ); + _base->Shutdown(); + ResolveChildren_r( _vpanel ); + _base->MarkForDeletion(); + } + + if ( m_hScriptInstance ) + { + if ( g_pScriptVM ) + g_pScriptVM->RemoveInstance( m_hScriptInstance ); + } + + delete this; + } + + template + void CreateFromScript( HSCRIPT parent, const char *panelName, int root ) + { + Assert( !_vpanel && !m_hScriptInstance && !g_ScriptPanels.IsValidIndex( g_ScriptPanels.Find( this ) ) ); + + Create( panelName && *panelName ? panelName : NULL ); + _vpanel = _base->GetVPanel(); + m_hScriptInstance = g_pScriptVM->RegisterInstance< CHelper >( static_cast< CHelper* >( this ) ); + +#if SCRIPT_VGUI_SAVERESTORE + g_pScriptVM->GenerateUniqueKey( "", m_pszScriptId, sizeof(m_pszScriptId) ); + g_pScriptVM->SetInstanceUniqeId( m_hScriptInstance, m_pszScriptId ); +#endif + + if ( parent ) + { + IScriptVGUIObject *obj = ToScriptVGUIObj( parent ); + if ( obj ) + { + // Insert this after the parent to make sure children come after their parents, + // and their removal is done inside ResolveChildren_r(), not by individual Destroy() calls from LevelShutdown. + unsigned short parentIdx = g_ScriptPanels.Find( obj ); + + // My parent can't not be in the list. + Assert( parentIdx != g_ScriptPanels.InvalidIndex() && g_ScriptPanels.IsInList( parentIdx ) ); + + g_ScriptPanels.InsertAfter( parentIdx, this ); + + _base->SetParent( obj->GetVPanel() ); + return; + } + + AssertMsg( 0, "invalid parent" ); + } + + g_ScriptPanels.AddToTail( this ); + + // Script specified engine root panel. + // Match the values to vscript_vgui.nut. + // + // This parameter is hidden in script, and is defined by the return value of dummy functions. + VPANEL vparent = 0; + switch ( root ) + { + case 0: + vparent = VGUI_GetScriptRootPanel( PANEL_ROOT ); + break; +#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL + case 1: + vparent = VGUI_GetScriptRootPanel( PANEL_GAMEUIDLL ); + break; +#endif + case 2: + vparent = VGUI_GetScriptRootPanel( PANEL_CLIENTDLL ); + break; + } + + _base->SetParent( vparent ); + } +}; + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE_ROOT( Panel ) +{ +public: + void Destroy() + { + CScriptVGUIObject::Destroy(); + } + + void MakeReadyForUse() + { + __base()->MakeReadyForUse(); + } + + const char *GetName() + { + return __base()->GetName(); + } + + void AddTickSignal( int i ) + { + ivgui()->AddTickSignal( this->GetVPanel(), i ); + } +#if VGUI_SIGNAL_INTERFACE + void AddActionSignalTarget( HSCRIPT messageTarget ) + { + IScriptVGUIObject *obj = ToScriptVGUIObj( messageTarget ); + if ( obj ) + { + __base()->AddActionSignalTarget( obj->GetVPanel() ); + } + } +#endif + //----------------------------------------------------- + // Get script created parent + //----------------------------------------------------- + HSCRIPT GetParent() + { + VPANEL parent = ipanel()->GetParent( this->GetVPanel() ); + if ( !parent ) + return NULL; + + int i; + IScriptVGUIObject* obj = FindInScriptPanels( parent, i ); + if ( obj ) + { + // My parent can't be invalid. + Assert( ToScriptVGUIObj( obj->GetScriptInstance() ) ); + + return obj->GetScriptInstance(); + } + +#ifdef _DEBUG + // Is my parent one of the root panels? + bool b = false; +#if SCRIPT_ENGINE_ROOT_PANELS + if ( parent == g_pScriptRootPanel->GetVPanel() || +#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL + (g_pScriptGameUIDLLPanel && parent == g_pScriptGameUIDLLPanel->GetVPanel()) || +#endif + (g_pScriptClientDLLPanel && parent == g_pScriptClientDLLPanel->GetVPanel()) ) + { + b = true; + } + else +#endif + for ( int i = PANEL_ROOT; i <= PANEL_CLIENTDLL_TOOLS; ++i ) + { + if ( parent == enginevgui->GetPanel( (VGuiPanel_t)i ) ) + { + b = true; + break; + } + } + + // My parent wasn't registered. + AssertMsg1( b, "'%s'", ipanel()->GetName(parent) ); +#endif + + return NULL; + } + + //----------------------------------------------------- + // Set script created parent + //----------------------------------------------------- + void SetParent( HSCRIPT parent ) + { + if ( !parent ) + { + __base()->SetParent( (VPANEL)NULL ); + return; + } + + IScriptVGUIObject *obj = ToScriptVGUIObj( parent ); + if ( obj ) + { + __base()->SetParent( obj->GetVPanel() ); + return; + } + + AssertMsg( 0, "invalid parent" ); + } + + void GetChildren( HSCRIPT arr ) + { + CUtlVector< VPANEL > &children = ipanel()->GetChildren( this->GetVPanel() ); + FOR_EACH_VEC( children, i ) + { + VPANEL child = children[i]; + int j; + IScriptVGUIObject* obj = FindInScriptPanels( child, j ); + if ( obj ) + { + g_pScriptVM->ArrayAppend( arr, obj->GetScriptInstance() ); + } + // UNDONE: Register C++ created children of script created panels. + // It is safe to do so because their lifetime depends on their script parents. + } + } + + int GetXPos() + { + int x, y; + ipanel()->GetPos( this->GetVPanel(), x, y ); + return x; + } + + int GetYPos() + { + int x, y; + ipanel()->GetPos( this->GetVPanel(), x, y ); + return y; + } + + void SetPos( int x, int y ) + { + ipanel()->SetPos( this->GetVPanel(), x, y ); + } + + void SetZPos( int i ) + { + ipanel()->SetZPos( this->GetVPanel(), i ); + } + + int GetZPos() + { + return ipanel()->GetZPos( this->GetVPanel() ); + } + + void SetSize( int w, int t ) + { + ipanel()->SetSize( this->GetVPanel(), w, t ); + } + + void SetWide( int w ) + { + ipanel()->SetSize( this->GetVPanel(), w, GetTall() ); + } + + int GetWide() + { + int w, t; + ipanel()->GetSize( this->GetVPanel(), w, t ); + return w; + } + + void SetTall( int t ) + { + ipanel()->SetSize( this->GetVPanel(), GetWide(), t ); + } + + int GetTall() + { + int w, t; + ipanel()->GetSize( this->GetVPanel(), w, t ); + return t; + } + + int GetAlpha() + { + return __base()->GetAlpha(); + } + + void SetAlpha( int i ) + { + __base()->SetAlpha( i ); + } + + void SetVisible( bool i ) + { + ipanel()->SetVisible( this->GetVPanel(), i ); + } + + bool IsVisible() + { + return ipanel()->IsVisible( this->GetVPanel() ); + } +#if BUILD_GROUPS_ENABLED + void SetProportional( bool i ) + { + __base()->SetProportional(i); + } +#endif +#if 0 + void LocalToScreen( HSCRIPT out ) + { + int px, py; + ipanel()->GetAbsPos( this->GetVPanel(), px, py ); + + ScriptVariant_t x, y; + g_pScriptVM->GetValue( out, (ScriptVariant_t)0, &x ); + g_pScriptVM->GetValue( out, 1, &y ); + + g_pScriptVM->SetValue( out, (ScriptVariant_t)0, x.m_int + px ); + g_pScriptVM->SetValue( out, 1, y.m_int + py ); + } + + void ScreenToLocal( HSCRIPT out ) + { + int px, py; + ipanel()->GetAbsPos( this->GetVPanel(), px, py ); + + ScriptVariant_t x, y; + g_pScriptVM->GetValue( out, (ScriptVariant_t)0, &x ); + g_pScriptVM->GetValue( out, 1, &y ); + + g_pScriptVM->SetValue( out, (ScriptVariant_t)0, x.m_int - px ); + g_pScriptVM->SetValue( out, 1, y.m_int - py ); + } +#endif + bool IsWithin( int x, int y ) + { + return __base()->IsWithin( x, y ); + } + + void SetEnabled( bool i ) + { + __base()->SetEnabled(i); + } + + bool IsEnabled() + { + return __base()->IsEnabled(); + } + + void SetPaintEnabled( bool i ) + { + __base()->SetPaintEnabled(i); + } + + void SetPaintBackgroundEnabled( bool i ) + { + __base()->SetPaintBackgroundEnabled(i); + } + + void SetPaintBorderEnabled( bool i ) + { + __base()->SetPaintBorderEnabled(i); + } + + void SetPostChildPaintEnabled( bool i ) + { + __base()->SetPostChildPaintEnabled(i); + } + + // 0 for normal(opaque), 1 for single texture from Texture1, and 2 for rounded box w/ four corner textures + void SetPaintBackgroundType( int i ) + { + __base()->SetPaintBackgroundType(i); + } + + void SetFgColor( int r, int g, int b, int a ) + { + __base()->SetFgColor( Color( r, g, b, a ) ); + } + + void SetBgColor( int r, int g, int b, int a ) + { + __base()->SetBgColor( Color( r, g, b, a ) ); + } +#if 0 + void SetScheme( const char *tag ) + { + return __base()->SetScheme( tag ); + } +#endif + void SetCursor( int cursor ) + { + AssertMsg( cursor >= 0 && cursor < dc_last, "invalid cursor" ); + + // do nothing + if ( cursor < 0 || cursor >= dc_last ) + return; + + return __base()->SetCursor( (HCursor)cursor ); + } + + bool IsCursorOver() + { + return __base()->IsCursorOver(); + } + + bool HasFocus() + { + return __base()->HasFocus(); + } + + void RequestFocus() + { + __base()->RequestFocus(); + } + + void MakePopup() + { + __base()->MakePopup(); + } + + void MoveToFront() + { + __base()->MoveToFront(); + } + + void SetMouseInputEnabled( bool i ) + { + __base()->SetMouseInputEnabled(i); + } + + void SetKeyBoardInputEnabled( bool i ) + { + __base()->SetKeyBoardInputEnabled(i); + } + + // ----------------------- + // Drawing utility + // ----------------------- + //void SetRoundedCorners( int cornerFlags ) + //{ + // __base()->SetRoundedCorners( cornerFlags & 0xff ); + //} + + void DrawBox( int x, int y, int wide, int tall, int r, int g, int b, int a, bool hollow ) + { + __base()->DrawBox( x, y, wide, tall, Color(r, g, b, a), 1.0f, hollow ); + } + + void DrawBoxFade( int x, int y, int wide, int tall, int r, int g, int b, int a, int alpha0, int alpha1, bool bHorizontal, bool hollow ) + { + __base()->DrawBoxFade( x, y, wide, tall, Color(r, g, b, a), 1.0f, alpha0, alpha1, bHorizontal, hollow ); + } +#if 0 + // ----------------------- + // drag drop + // ----------------------- + void SetDragEnabled( bool i ) + { + __base()->SetDragEnabled(i); + } + + bool IsDragEnabled() + { + return __base()->IsDragEnabled(); + } + + void SetDropEnabled( bool i ) + { + __base()->SetDropEnabled( i, 0.0f ); + } + + bool IsDropEnabled() + { + return __base()->IsDropEnabled(); + } + + void SetShowDragHelper( int i ) + { + __base()->SetShowDragHelper(i); + } + + int GetDragStartTolerance() + { + return __base()->GetDragStartTolerance(); + } + + void SetDragStartTolerance( int i ) + { + __base()->SetDragSTartTolerance(i); + } +#endif +#if 0 + void SetTooltip( const char *text ) + { + __base()->GetTooltip()->SetText( text ); + } + + void SetTooltipDelay( int delay ) + { + __base()->GetTooltip()->SetTooltipDelay( delay ); + } +#endif +}; + +#define DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()\ +\ + DEFINE_SCRIPTFUNC( Destroy, "" )\ + DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\ + DEFINE_SCRIPTFUNC( GetName, "" )\ + DEFINE_SCRIPTFUNC( AddTickSignal, "" )\ +\ + DEFINE_SCRIPTFUNC( GetParent, "" )\ + DEFINE_SCRIPTFUNC( SetParent, "" )\ + DEFINE_SCRIPTFUNC( GetChildren, "" )\ +\ + DEFINE_SCRIPTFUNC( GetXPos, "" )\ + DEFINE_SCRIPTFUNC( GetYPos, "" )\ + DEFINE_SCRIPTFUNC( SetPos, "" )\ +\ + DEFINE_SCRIPTFUNC( GetZPos, "" )\ + DEFINE_SCRIPTFUNC( SetZPos, "" )\ +\ + DEFINE_SCRIPTFUNC( SetSize, "" )\ + DEFINE_SCRIPTFUNC( GetWide, "" )\ + DEFINE_SCRIPTFUNC( SetWide, "" )\ +\ + DEFINE_SCRIPTFUNC( GetTall, "" )\ + DEFINE_SCRIPTFUNC( SetTall, "" )\ +\ + DEFINE_SCRIPTFUNC( GetAlpha, "" )\ + DEFINE_SCRIPTFUNC( SetAlpha, "" )\ +\ + DEFINE_SCRIPTFUNC( SetVisible, "" )\ + DEFINE_SCRIPTFUNC( IsVisible, "" )\ +\ + DEFINE_SCRIPTFUNC( IsWithin, "" )\ +\ + DEFINE_SCRIPTFUNC( SetEnabled, "" )\ + DEFINE_SCRIPTFUNC( IsEnabled, "" )\ +\ + DEFINE_SCRIPTFUNC( SetPaintEnabled, "" )\ + DEFINE_SCRIPTFUNC( SetPaintBackgroundEnabled, "" )\ + DEFINE_SCRIPTFUNC( SetPaintBorderEnabled, "" )\ + DEFINE_SCRIPTFUNC( SetPostChildPaintEnabled, "" )\ + DEFINE_SCRIPTFUNC( SetPaintBackgroundType, "" )\ +\ + DEFINE_SCRIPTFUNC( SetFgColor, "" )\ + DEFINE_SCRIPTFUNC( SetBgColor, "" )\ +\ + DEFINE_SCRIPTFUNC( SetCursor, "" )\ + DEFINE_SCRIPTFUNC( IsCursorOver, "" )\ + DEFINE_SCRIPTFUNC( HasFocus, "" )\ + DEFINE_SCRIPTFUNC( RequestFocus, "" )\ + DEFINE_SCRIPTFUNC( MakePopup, "" )\ + DEFINE_SCRIPTFUNC( MoveToFront, "" )\ + DEFINE_SCRIPTFUNC( SetMouseInputEnabled, "" )\ + DEFINE_SCRIPTFUNC( SetKeyBoardInputEnabled, "" )\ +\ + DEFINE_SCRIPTFUNC( DrawBox, "" )\ + DEFINE_SCRIPTFUNC( DrawBoxFade, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- +// These need more testing. +// TODO: IScript_Panel::FindChildByName() +// TODO: DECLARE_BUILD_FACTORY_SCRIPT() to create overridable script panels from controls file +// TODO: CScript_EditablePanel::ApplySchemeSettings() callback +// (IScheme parameter can be passed as null until schemes are also tested) +#if BUILD_GROUPS_ENABLED +CLASS_HELPER_INTERFACE( EditablePanel, Panel ) +{ +public: + // Call on creation or on ApplySchemeSettings() + void LoadControlSettings( const char *resName ) + { + __base()->LoadControlSettings( resName ); + } +}; + +#define DEFINE_VGUI_SCRIPTFUNC_EditablePanel()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( LoadControlSettings, "" ) +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE( Label, Panel ) +{ +public: + void SetText( const char *text ) + { + wchar_t wcs[512]; + g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); + __base()->SetText( wcs ); + } + + void SetFont( int i ) + { + __base()->SetFont( IntToFontHandle(i) ); + } + + void SetAllCaps( bool i ) + { + __base()->SetAllCaps(i); + } + + void SetWrap( bool i ) + { + __base()->SetWrap(i); + } + + void SetCenterWrap( bool i ) + { + __base()->SetCenterWrap(i); + } + + void SetContentAlignment( int i ) + { + __base()->SetContentAlignment( (Label::Alignment)i ); + } + + void SetTextInset( int x, int y ) + { + __base()->SetTextInset( x, y ); + } + + void SizeToContents() + { + __base()->SizeToContents(); + } + + void SetAssociatedControl( HSCRIPT control ) + { + IScriptVGUIObject *obj = ToScriptVGUIObj( control ); + if ( obj ) + { + __base()->SetAssociatedControl( ipanel()->GetPanel( obj->GetVPanel(), GetControlsModuleName() ) ); + } + } + + void AddColorChange( int r, int g, int b, int a, int iTextStreamIndex ) + { + __base()->GetTextImage()->AddColorChange( Color( r, g, b, a ), iTextStreamIndex ); + } + + void ClearColorChangeStream() + { + __base()->GetTextImage()->ClearColorChangeStream(); + } +#if 0 + void SetTextImageIndex( int index ) + { + __base()->SetTextImageIndex( index ); + } + + void SetImageAtIndex( int index, const char *imageName, bool hardwareFilter, int offset ) + { + return __base()->SetImageAtIndex( index, vgui_GetImage( imageName, hardwareFilter ), offset ); + } + + int AddImage( const char *imageName, bool hardwareFilter, int offset ) + { + return __base()->AddImage( vgui_GetImage( imageName, hardwareFilter ), offset ); + } +#endif +}; + +#define DEFINE_VGUI_SCRIPTFUNC_Label()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetText, "" )\ + DEFINE_SCRIPTFUNC( SetFont, "" )\ + DEFINE_SCRIPTFUNC( SetAllCaps, "" )\ + DEFINE_SCRIPTFUNC( SetWrap, "" )\ + DEFINE_SCRIPTFUNC( SetCenterWrap, "" )\ + DEFINE_SCRIPTFUNC( SetContentAlignment, "" )\ + DEFINE_SCRIPTFUNC( SetTextInset, "" )\ + DEFINE_SCRIPTFUNC( SizeToContents, "" )\ + DEFINE_SCRIPTFUNC( SetAssociatedControl, "" )\ + DEFINE_SCRIPTFUNC( AddColorChange, "" )\ + DEFINE_SCRIPTFUNC( ClearColorChangeStream, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE( Button, Label ) +{ +public: + // NOTE: This is used if DoClick() callback is not implemented in CScript_Button. + // This changes where and how button command is processed - + // whether in the button { DoClick() } or in an external panel { OnCommand(cmd) }. + // It is fine to always use DoClick() instead of vgui messages + // because of the dynamic nature of script closures. +#if VGUI_SIGNAL_INTERFACE + void SetCommand( const char *command ) + { + if ( !V_strncmp( command, "url ", 4 ) ) + { + __base()->SetCommand( (KeyValues*)NULL ); + + g_pScriptVM->RaiseException("invalid button command"); + return; + } + + __base()->SetCommand( command ); + } +#endif + void SetButtonActivationType( int activationType ) + { + __base()->SetButtonActivationType( (Button::ActivationType_t)activationType ); + } + + bool IsArmed() + { + return __base()->IsArmed(); + } + + void SetArmed( bool state ) + { + __base()->SetArmed(state); + } + + bool IsSelected() + { + return __base()->IsSelected(); + } + + void SetSelected( bool state ) + { + __base()->SetSelected(state); + } + + bool IsDepressed() + { + return __base()->IsDepressed(); + } + + void ForceDepressed( bool state ) + { + __base()->ForceDepressed(state); + } +#if 0 + void SetBlink( bool state ) + { + __base()->SetBlink(state); + } +#endif + void SetMouseClickEnabled( int code, bool state ) + { + __base()->SetMouseClickEnabled( (MouseCode)code, state ); + } + + bool IsMouseClickEnabled( int code ) + { + return __base()->IsMouseClickEnabled( (MouseCode)code ); + } + + void SetDefaultColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) + { + __base()->SetDefaultColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); + } + + void SetArmedColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) + { + __base()->SetArmedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); + } + + void SetSelectedColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) + { + __base()->SetSelectedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); + } + + void SetDepressedColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) + { + __base()->SetDepressedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); + } +#if 0 + void SetBlinkColor( int r, int g, int b, int a ) + { + __base()->SetBlinkColor( Color(r, g, b, a) ); + } +#endif + void SetArmedSound( const char *sound ) + { + __base()->SetArmedSound( sound ); + } + + void SetDepressedSound( const char *sound ) + { + __base()->SetDepressedSound( sound ); + } + + void SetReleasedSound( const char *sound ) + { + __base()->SetReleasedSound( sound ); + } +}; + +#define DEFINE_VGUI_SCRIPTFUNC_Button()\ + DEFINE_VGUI_SCRIPTFUNC_Label()\ + DEFINE_SCRIPTFUNC( SetButtonActivationType, "" )\ + DEFINE_SCRIPTFUNC( IsArmed, "" )\ + DEFINE_SCRIPTFUNC( SetArmed, "" )\ + DEFINE_SCRIPTFUNC( IsSelected, "" )\ + DEFINE_SCRIPTFUNC( SetSelected, "" )\ + DEFINE_SCRIPTFUNC( IsDepressed, "" )\ + DEFINE_SCRIPTFUNC( ForceDepressed, "" )\ + DEFINE_SCRIPTFUNC( SetMouseClickEnabled, "" )\ + DEFINE_SCRIPTFUNC( IsMouseClickEnabled, "" )\ + DEFINE_SCRIPTFUNC( SetDefaultColor, "" )\ + DEFINE_SCRIPTFUNC( SetArmedColor, "" )\ + DEFINE_SCRIPTFUNC( SetSelectedColor, "" )\ + DEFINE_SCRIPTFUNC( SetDepressedColor, "" )\ + DEFINE_SCRIPTFUNC( SetArmedSound, "" )\ + DEFINE_SCRIPTFUNC( SetDepressedSound, "" )\ + DEFINE_SCRIPTFUNC( SetReleasedSound, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE( ImagePanel, Panel ) +{ +public: + void SetImage( const char *imageName, bool hardwareFilter ) + { + __base()->EvictImage(); + __base()->SetImage( vgui_GetImage( imageName, hardwareFilter ) ); + } + + void SetDrawColor( int r, int g, int b, int a ) + { + __base()->SetDrawColor( Color( r, g, b, a ) ); + } + + void SetTileImage( bool bTile ) + { + __base()->SetTileImage( bTile ); + } + + void SetShouldScaleImage( bool state ) + { + __base()->SetShouldScaleImage( state ); + } +#if 0 + void SetFrame( int nFrame ) + { + __base()->SetFrame( nFrame ); + } +#endif +}; + +#define DEFINE_VGUI_SCRIPTFUNC_ImagePanel()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetImage, "" )\ + DEFINE_SCRIPTFUNC( SetDrawColor, "" )\ + DEFINE_SCRIPTFUNC( SetTileImage, "" )\ + DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE( Frame, Panel ) +{ +public: + void SetMinimumSize( int wide, int tall ) + { + __base()->SetMinimumSize( wide, tall ); + } + + void SetTitle( const char* titel ) + { + __base()->SetTitle( titel, false ); + } + + void Close() + { + __base()->Close(); + } + + void SetDeleteSelfOnClose( bool state ) + { + __base()->SetDeleteSelfOnClose( state ); + } + + void SetMoveable( bool state ) + { + __base()->SetMoveable( state ); + } + + void SetSizeable( bool state ) + { + __base()->SetSizeable( state ); + } + + void SetCloseButtonVisible( bool state ) + { + __base()->SetCloseButtonVisible( state ); + } + + void SetTitleBarVisible( bool state ) + { + __base()->SetTitleBarVisible( state ); + } +}; + +#define DEFINE_VGUI_SCRIPTFUNC_Frame()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetMinimumSize, "" )\ + DEFINE_SCRIPTFUNC( SetTitle, "" )\ + DEFINE_SCRIPTFUNC( Close, "" )\ + DEFINE_SCRIPTFUNC( SetDeleteSelfOnClose, "" )\ + DEFINE_SCRIPTFUNC( SetMoveable, "" )\ + DEFINE_SCRIPTFUNC( SetSizeable, "" )\ + DEFINE_SCRIPTFUNC( SetCloseButtonVisible, "" )\ + DEFINE_SCRIPTFUNC( SetTitleBarVisible, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE( RichText, Panel ) +{ +public: + void SetText( const char* text ) + { + __base()->SetText( text ); + } + + void SetFont( int font ) + { + __base()->SetFont( IntToFontHandle(font) ); + } + + void InsertString( const char* text ) + { + __base()->InsertString( text ); + } + + void SetPanelInteractive( bool bInteractive ) + { + __base()->SetPanelInteractive( bInteractive ); + } + + void SetUnusedScrollbarInvisible( bool bInvis ) + { + __base()->SetUnusedScrollbarInvisible( bInvis ); + } + + void GotoTextStart() + { + __base()->GotoTextStart(); + } + + void GotoTextEnd() + { + __base()->GotoTextEnd(); + } + + void SetMaximumCharCount( int maxChars ) + { + __base()->SetMaximumCharCount( maxChars ); + } + + void InsertColorChange( int r, int g, int b, int a ) + { + __base()->InsertColorChange( Color( r, g, b, a ) ); + } + + int GetNumLines() + { + return __base()->GetNumLines(); + } + + void SetDrawTextOnly() + { + __base()->SetDrawTextOnly(); + } +}; + +#define DEFINE_VGUI_SCRIPTFUNC_RichText()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetText, "" )\ + DEFINE_SCRIPTFUNC( SetFont, "" )\ + DEFINE_SCRIPTFUNC( InsertString, "" )\ + DEFINE_SCRIPTFUNC( SetPanelInteractive, "" )\ + DEFINE_SCRIPTFUNC( SetUnusedScrollbarInvisible, "" )\ + DEFINE_SCRIPTFUNC( GotoTextStart, "" )\ + DEFINE_SCRIPTFUNC( GotoTextEnd, "" )\ + DEFINE_SCRIPTFUNC( SetMaximumCharCount, "" )\ + DEFINE_SCRIPTFUNC( InsertColorChange, "" )\ + DEFINE_SCRIPTFUNC( GetNumLines, "" )\ + DEFINE_SCRIPTFUNC( SetDrawTextOnly, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +CLASS_HELPER_INTERFACE( TextEntry, Panel ) +{ +public: + void SetText( const char* text ) + { + wchar_t wcs[512]; + g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); + __base()->SetText( wcs ); + } + + const char *GetText() + { + static char sz[512]; + __base()->GetText( sz, sizeof(sz) ); + return sz; + } + + void SetFont( int font ) + { + __base()->SetFont( IntToFontHandle(font) ); + } + + void SetEditable( bool state ) + { + __base()->SetEditable( state ); + } + + void GotoTextStart() + { + __base()->GotoTextStart(); + } + + void GotoTextEnd() + { + __base()->GotoTextEnd(); + } + + void InsertString( const char* text ) + { + __base()->InsertString( text ); + } + + void SelectNone() + { + __base()->SelectNone(); + } + + void SetMultiline( bool state ) + { + __base()->SetMultiline( state ); + } + + void SetVerticalScrollbar( bool state ) + { + __base()->SetVerticalScrollbar( state ); + } +#if 0 + void SetHorizontalScrolling( bool status ) + { + __base()->SetHorizontalScrolling( status ); + } +#endif + void SetCatchEnterKey( bool state ) + { + __base()->SetCatchEnterKey( state ); + } + + void SetMaximumCharCount( int maxChars ) + { + __base()->SetMaximumCharCount( maxChars ); + } +#if 0 + void SetWrap( bool wrap ) + { + __base()->SetWrap( wrap ); + } +#endif + void SetAllowNumericInputOnly( bool state ) + { + __base()->SetAllowNumericInputOnly( state ); + } +#if 0 + void SetDisabledBgColor( int r, int g, int b, int a ) + { + __base()->SetDisabledBgColor( Color( r, g, b, a ) ); + } + + void SetSelectionTextColor( int r, int g, int b, int a ) + { + __base()->SetSelectionTextColor( Color( r, g, b, a ) ); + } + + void SetSelectionBgColor( int r, int g, int b, int a ) + { + __base()->SetSelectionBgColor( Color( r, g, b, a ) ); + } + + void SetSelectionUnfocusedBgColor( int r, int g, int b, int a ) + { + __base()->SetSelectionUnfocusedBgColor( Color( r, g, b, a ) ); + } +#endif +}; + +#define DEFINE_VGUI_SCRIPTFUNC_TextEntry()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetText, "" )\ + DEFINE_SCRIPTFUNC( GetText, "" )\ + DEFINE_SCRIPTFUNC( SetFont, "" )\ + DEFINE_SCRIPTFUNC( SetEditable, "" )\ + DEFINE_SCRIPTFUNC( GotoTextStart, "" )\ + DEFINE_SCRIPTFUNC( GotoTextEnd, "" )\ + DEFINE_SCRIPTFUNC( InsertString, "" )\ + DEFINE_SCRIPTFUNC( SelectNone, "" )\ + DEFINE_SCRIPTFUNC( SetMultiline, "" )\ + DEFINE_SCRIPTFUNC( SetVerticalScrollbar, "" )\ + DEFINE_SCRIPTFUNC( SetCatchEnterKey, "" )\ + DEFINE_SCRIPTFUNC( SetMaximumCharCount, "" )\ + DEFINE_SCRIPTFUNC( SetAllowNumericInputOnly, "" )\ + +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#if !defined(NO_STEAM) +CLASS_HELPER_INTERFACE( AvatarImage, Panel ) +{ +public: + void SetPlayer( const char *steam2id, int eAvatarSize ) + { + uint32 __SteamInstanceID; + uint32 __SteamLocalUserID_Low32Bits; + uint32 __SteamLocalUserID_High32Bits; + + int c = sscanf( steam2id, "STEAM_%u:%u:%u", + &__SteamInstanceID, &__SteamLocalUserID_High32Bits, &__SteamLocalUserID_Low32Bits ); + + if ( c < 3 ) + return; + + CSteamID id( __SteamLocalUserID_Low32Bits * 2 + __SteamLocalUserID_High32Bits, + k_EUniversePublic, + k_EAccountTypeIndividual ); + + __base()->SetPlayer( id, (EAvatarSize)eAvatarSize ); + } + + void SetPlayerByIndex( int entindex, int eAvatarSize ) + { + if ( !entindex ) + { + __base()->ClearAvatar(); + return; + } + + __base()->SetPlayer( entindex, (EAvatarSize)eAvatarSize ); + } + + void SetDefaultAvatar( const char *imageName ) + { + __base()->SetDefaultAvatar( vgui_GetImage( imageName, false ) ); + } + + void SetShouldScaleImage( bool state ) + { + __base()->SetShouldScaleImage( state ); + } +}; + +#define DEFINE_VGUI_SCRIPTFUNC_AvatarImage()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetPlayer, "" )\ + DEFINE_SCRIPTFUNC( SetPlayerByIndex, "" )\ + DEFINE_SCRIPTFUNC( SetDefaultAvatar, "" )\ + DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" ) +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#if 0 +CLASS_HELPER_INTERFACE( TGAImagePanel, Panel ) +{ +public: + void SetTGAImage( const char *p ) + { + __base()->SetTGAImage( p ); + } + + void SetDrawColor( int r, int g, int b, int a ) + { + __base()->SetDrawColor( r, g, b, a ); + } + + void SetShouldScaleImage( bool i ) + { + __base()->SetShouldScaleImage( i ); + } +}; + +#define DEFINE_VGUI_SCRIPTFUNC_TGAImagePanel()\ + DEFINE_VGUI_SCRIPTFUNC_Panel()\ + DEFINE_SCRIPTFUNC( SetTGAImage, "" )\ + DEFINE_SCRIPTFUNC( SetDrawColor, "" )\ + DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" ) +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + + +//============================================================== +//============================================================== + + +#define SetHScript( var, val ) \ + if ( var && g_pScriptVM ) \ + g_pScriptVM->ReleaseScript( var ); \ + var = val; + +#define CheckCallback(s)\ + if ( FStrEq( cb, #s ) )\ + {\ + SetHScript( m_hfn##s, fn );\ + return;\ + } + +//-------------------------------------------------------- +// C++ objects for vgui overrides and messages. +//-------------------------------------------------------- + + +class CScript_Panel : public Panel +{ + DECLARE_SCRIPTVGUI_CLASS( Panel ); + +private: + HSCRIPT m_hfnPaint; + HSCRIPT m_hfnPaintBackground; + HSCRIPT m_hfnPostChildPaint; + + HSCRIPT m_hfnPerformLayout; + HSCRIPT m_hfnOnTick; + HSCRIPT m_hfnOnScreenSizeChanged; + + HSCRIPT m_hfnOnCursorEntered; + HSCRIPT m_hfnOnCursorExited; + HSCRIPT m_hfnOnCursorMoved; + + HSCRIPT m_hfnOnMousePressed; + HSCRIPT m_hfnOnMouseDoublePressed; + HSCRIPT m_hfnOnMouseReleased; + HSCRIPT m_hfnOnMouseWheeled; + + HSCRIPT m_hfnOnKeyCodePressed; + HSCRIPT m_hfnOnKeyCodeReleased; + HSCRIPT m_hfnOnKeyCodeTyped; + +public: + CScript_Panel( Panel *parent, const char *name ) : + BaseClass( parent, name ), + + m_hfnPaint(NULL), + m_hfnPaintBackground(NULL), + m_hfnPostChildPaint(NULL), + + m_hfnPerformLayout(NULL), + m_hfnOnTick(NULL), + m_hfnOnScreenSizeChanged(NULL), + + m_hfnOnCursorEntered(NULL), + m_hfnOnCursorExited(NULL), + m_hfnOnCursorMoved(NULL), + + m_hfnOnMousePressed(NULL), + m_hfnOnMouseDoublePressed(NULL), + m_hfnOnMouseReleased(NULL), + m_hfnOnMouseWheeled(NULL), + + m_hfnOnKeyCodePressed(NULL), + m_hfnOnKeyCodeReleased(NULL), + m_hfnOnKeyCodeTyped(NULL) + {} + + void Shutdown() + { + ivgui()->RemoveTickSignal( GetVPanel() ); + + SetHScript( m_hfnPaint, NULL ); + SetHScript( m_hfnPaintBackground, NULL ); + SetHScript( m_hfnPostChildPaint, NULL ); + + SetHScript( m_hfnPerformLayout, NULL ); + SetHScript( m_hfnOnTick, NULL ); + SetHScript( m_hfnOnScreenSizeChanged, NULL ); + + SetHScript( m_hfnOnCursorEntered, NULL ); + SetHScript( m_hfnOnCursorExited, NULL ); + SetHScript( m_hfnOnCursorMoved, NULL ); + + SetHScript( m_hfnOnMousePressed, NULL ); + SetHScript( m_hfnOnMouseDoublePressed, NULL ); + SetHScript( m_hfnOnMouseReleased, NULL ); + SetHScript( m_hfnOnMouseWheeled, NULL ); + + SetHScript( m_hfnOnKeyCodePressed, NULL ); + SetHScript( m_hfnOnKeyCodeReleased, NULL ); + SetHScript( m_hfnOnKeyCodeTyped, NULL ); + } + +public: + void Paint() + { + g_pScriptVM->ExecuteFunction( m_hfnPaint, NULL, 0, NULL, NULL, true ); + } + + void PaintBackground() + { + if ( m_hfnPaintBackground ) + { + g_pScriptVM->ExecuteFunction( m_hfnPaintBackground, NULL, 0, NULL, NULL, true ); + } + else + { + BaseClass::PaintBackground(); + } + } + + void PostChildPaint() + { + g_pScriptVM->ExecuteFunction( m_hfnPostChildPaint, NULL, 0, NULL, NULL, true ); + } + + void PerformLayout() + { + BaseClass::PerformLayout(); + + if ( m_hfnPerformLayout ) + { + g_pScriptVM->ExecuteFunction( m_hfnPerformLayout, NULL, 0, NULL, NULL, true ); + } + } + + void OnTick() + { + g_pScriptVM->ExecuteFunction( m_hfnOnTick, NULL, 0, NULL, NULL, true ); + } + + void OnScreenSizeChanged( int oldwide, int oldtall ) + { + BaseClass::OnScreenSizeChanged( oldwide, oldtall ); + + if ( m_hfnOnScreenSizeChanged ) + { + ScriptVariant_t args[2] = { oldwide, oldtall }; + g_pScriptVM->ExecuteFunction( m_hfnOnScreenSizeChanged, args, 2, NULL, NULL, true ); + } + } +#if VGUI_SIGNAL_INTERFACE + void OnCommand( const char *command ) + { + if ( m_hfnOnCommand ) + { + ScriptVariant_t ret, arg = command; + g_pScriptVM->ExecuteFunction( m_hfnOnCommand, &arg, 1, &ret, NULL, true ); + + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnCommand( command ); + } +#endif + void OnCursorEntered() + { + if ( m_hfnOnCursorEntered ) + { + g_pScriptVM->ExecuteFunction( m_hfnOnCursorEntered, NULL, 0, NULL, NULL, true ); + } + } + + void OnCursorExited() + { + if ( m_hfnOnCursorExited ) + { + g_pScriptVM->ExecuteFunction( m_hfnOnCursorExited, NULL, 0, NULL, NULL, true ); + } + } + + void OnCursorMoved( int x, int y ) + { + if ( m_hfnOnCursorMoved ) + { + ScriptVariant_t args[2] = { x, y }; + g_pScriptVM->ExecuteFunction( m_hfnOnCursorMoved, args, 2, NULL, NULL, true ); + } + else + { + Assert( !ParentNeedsCursorMoveEvents() ); + } + } + + void OnMousePressed( MouseCode code ) + { + if ( m_hfnOnMousePressed ) + { + ScriptVariant_t arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnMousePressed, &arg, 1, NULL, NULL, true ); + } + } + + void OnMouseDoublePressed( MouseCode code ) + { + if ( m_hfnOnMouseDoublePressed ) + { + ScriptVariant_t arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnMouseDoublePressed, &arg, 1, NULL, NULL, true ); + } + } + + void OnMouseReleased( MouseCode code ) + { + if ( m_hfnOnMouseReleased ) + { + ScriptVariant_t arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnMouseReleased, &arg, 1, NULL, NULL, true ); + } + } + + void OnMouseWheeled( int delta ) + { + if ( m_hfnOnMouseWheeled ) + { + ScriptVariant_t arg = (int)delta; + g_pScriptVM->ExecuteFunction( m_hfnOnMouseWheeled, &arg, 1, NULL, NULL, true ); + } + } + + void OnKeyCodePressed( KeyCode code ) + { + if ( m_hfnOnKeyCodePressed ) + { + ScriptVariant_t ret, arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodePressed, &arg, 1, &ret, NULL, true ); + + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnKeyCodePressed( code ); + } + + void OnKeyCodeReleased( KeyCode code ) + { + if ( m_hfnOnKeyCodeReleased ) + { + ScriptVariant_t ret, arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeReleased, &arg, 1, &ret, NULL, true ); + + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnKeyCodeReleased( code ); + } + + void OnKeyCodeTyped( KeyCode code ) + { + if ( m_hfnOnKeyCodeTyped ) + { + ScriptVariant_t ret, arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeTyped, &arg, 1, &ret, NULL, true ); + + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnKeyCodeTyped( code ); + } +public: + void SetCallback( const char* cb, HSCRIPT fn ) + { + CheckCallback( Paint ); + CheckCallback( PaintBackground ); + CheckCallback( PostChildPaint ); + + CheckCallback( PerformLayout ); + CheckCallback( OnTick ); + CheckCallback( OnScreenSizeChanged ); + + CheckCallback( OnCursorEntered ); + CheckCallback( OnCursorExited ); + CheckCallback( OnCursorMoved ); + + CheckCallback( OnMousePressed ); + CheckCallback( OnMouseDoublePressed ); + CheckCallback( OnMouseReleased ); + CheckCallback( OnMouseWheeled ); + + CheckCallback( OnKeyCodePressed ); + CheckCallback( OnKeyCodeReleased ); + CheckCallback( OnKeyCodeTyped ); + + g_pScriptVM->RaiseException("invalid callback"); + } +}; + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +class CScript_Frame : public Frame +{ + DECLARE_SCRIPTVGUI_CLASS( Frame ); + +private: + HSCRIPT m_hfnPaint; + HSCRIPT m_hfnPaintBackground; + + HSCRIPT m_hfnPerformLayout; + HSCRIPT m_hfnOnTick; + HSCRIPT m_hfnOnScreenSizeChanged; + + HSCRIPT m_hfnOnCursorEntered; + HSCRIPT m_hfnOnCursorExited; + HSCRIPT m_hfnOnCursorMoved; + + HSCRIPT m_hfnOnMousePressed; + HSCRIPT m_hfnOnMouseDoublePressed; + HSCRIPT m_hfnOnMouseReleased; + HSCRIPT m_hfnOnMouseWheeled; + + HSCRIPT m_hfnOnKeyCodePressed; + HSCRIPT m_hfnOnKeyCodeReleased; + HSCRIPT m_hfnOnKeyCodeTyped; + +public: + CScript_Frame( Panel *parent, const char *name ) : + + // Start without popup + BaseClass( parent, name, false, false ), + + m_hfnPaint(NULL), + m_hfnPaintBackground(NULL), + + m_hfnPerformLayout(NULL), + m_hfnOnTick(NULL), + m_hfnOnScreenSizeChanged(NULL), + + m_hfnOnCursorEntered(NULL), + m_hfnOnCursorExited(NULL), + m_hfnOnCursorMoved(NULL), + + m_hfnOnMousePressed(NULL), + m_hfnOnMouseDoublePressed(NULL), + m_hfnOnMouseReleased(NULL), + m_hfnOnMouseWheeled(NULL), + + m_hfnOnKeyCodePressed(NULL), + m_hfnOnKeyCodeReleased(NULL), + m_hfnOnKeyCodeTyped(NULL) + { + SetFadeEffectDisableOverride( true ); + } + + void Shutdown() + { + ivgui()->RemoveTickSignal( GetVPanel() ); + + SetHScript( m_hfnPaint, NULL ); + SetHScript( m_hfnPaintBackground, NULL ); + + SetHScript( m_hfnPerformLayout, NULL ); + SetHScript( m_hfnOnTick, NULL ); + SetHScript( m_hfnOnScreenSizeChanged, NULL ); + + SetHScript( m_hfnOnMousePressed, NULL ); + SetHScript( m_hfnOnMouseDoublePressed, NULL ); + SetHScript( m_hfnOnMouseReleased, NULL ); + SetHScript( m_hfnOnMouseWheeled, NULL ); + + SetHScript( m_hfnOnKeyCodePressed, NULL ); + SetHScript( m_hfnOnKeyCodeReleased, NULL ); + SetHScript( m_hfnOnKeyCodeTyped, NULL ); + } + +public: + void Paint() + { + g_pScriptVM->ExecuteFunction( m_hfnPaint, NULL, 0, NULL, NULL, true ); + } + + void PaintBackground() + { + if ( m_hfnPaintBackground ) + { + g_pScriptVM->ExecuteFunction( m_hfnPaintBackground, NULL, 0, NULL, NULL, true ); + } + else + { + BaseClass::PaintBackground(); + } + } + + void PerformLayout() + { + BaseClass::PerformLayout(); + + if ( m_hfnPerformLayout ) + { + g_pScriptVM->ExecuteFunction( m_hfnPerformLayout, NULL, 0, NULL, NULL, true ); + } + } + + void OnTick() + { + g_pScriptVM->ExecuteFunction( m_hfnOnTick, NULL, 0, NULL, NULL, true ); + } + + void OnScreenSizeChanged( int oldwide, int oldtall ) + { + BaseClass::OnScreenSizeChanged( oldwide, oldtall ); + + if ( m_hfnOnScreenSizeChanged ) + { + ScriptVariant_t args[2] = { oldwide, oldtall }; + g_pScriptVM->ExecuteFunction( m_hfnOnScreenSizeChanged, args, 2, NULL, NULL, true ); + } + } + + void OnCursorEntered() + { + if ( m_hfnOnCursorEntered ) + { + g_pScriptVM->ExecuteFunction( m_hfnOnCursorEntered, NULL, 0, NULL, NULL, true ); + } + } + + void OnCursorExited() + { + if ( m_hfnOnCursorExited ) + { + g_pScriptVM->ExecuteFunction( m_hfnOnCursorExited, NULL, 0, NULL, NULL, true ); + } + } + + void OnCursorMoved( int x, int y ) + { + if ( m_hfnOnCursorMoved ) + { + ScriptVariant_t args[2] = { x, y }; + g_pScriptVM->ExecuteFunction( m_hfnOnCursorMoved, args, 2, NULL, NULL, true ); + } + else + { + Assert( !ParentNeedsCursorMoveEvents() ); + } + } + + void OnMousePressed( MouseCode code ) + { + BaseClass::OnMousePressed( code ); + + if ( m_hfnOnMousePressed ) + { + ScriptVariant_t arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnMousePressed, &arg, 1, NULL, NULL, true ); + } + } + + void OnMouseDoublePressed( MouseCode code ) + { + if ( m_hfnOnMouseDoublePressed ) + { + ScriptVariant_t arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnMouseDoublePressed, &arg, 1, NULL, NULL, true ); + } + } + + void OnMouseReleased( MouseCode code ) + { + if ( m_hfnOnMouseReleased ) + { + ScriptVariant_t arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnMouseReleased, &arg, 1, NULL, NULL, true ); + } + } + + void OnMouseWheeled( int delta ) + { + if ( m_hfnOnMouseWheeled ) + { + ScriptVariant_t arg = (int)delta; + g_pScriptVM->ExecuteFunction( m_hfnOnMouseWheeled, &arg, 1, NULL, NULL, true ); + } + } + + void OnKeyCodePressed( KeyCode code ) + { + if ( m_hfnOnKeyCodePressed ) + { + ScriptVariant_t ret, arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodePressed, &arg, 1, &ret, NULL, true ); + + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnKeyCodePressed( code ); + } + + void OnKeyCodeReleased( KeyCode code ) + { + if ( m_hfnOnKeyCodeReleased ) + { + ScriptVariant_t ret, arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeReleased, &arg, 1, &ret, NULL, true ); + + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnKeyCodeReleased( code ); + } + + void OnKeyCodeTyped( KeyCode code ) + { + if ( m_hfnOnKeyCodeTyped ) + { + ScriptVariant_t ret, arg = (int)code; + g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeTyped, &arg, 1, &ret, NULL, true ); + + // Return true to swallow the CanChainKeysToParent() override check and fallback, + // which by default swallows the input. + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + + if ( CanChainKeysToParent() ) + { + BaseClass::OnKeyCodeTyped( code ); + } + } + else + { + BaseClass::OnKeyCodeTyped( code ); + } + } +public: + void SetCallback( const char* cb, HSCRIPT fn ) + { + CheckCallback( Paint ); + CheckCallback( PaintBackground ); + + CheckCallback( PerformLayout ); + CheckCallback( OnTick ); + CheckCallback( OnScreenSizeChanged ); + + CheckCallback( OnCursorEntered ); + CheckCallback( OnCursorExited ); + CheckCallback( OnCursorMoved ); + + CheckCallback( OnMousePressed ); + CheckCallback( OnMouseDoublePressed ); + CheckCallback( OnMouseReleased ); + CheckCallback( OnMouseWheeled ); + + CheckCallback( OnKeyCodePressed ); + CheckCallback( OnKeyCodeReleased ); + CheckCallback( OnKeyCodeTyped ); + + g_pScriptVM->RaiseException("invalid callback"); + } +}; + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +class CScript_Button : public Button +{ + DECLARE_SCRIPTVGUI_CLASS( Button ); + +private: + HSCRIPT m_hfnPaint; + HSCRIPT m_hfnPaintBackground; + HSCRIPT m_hfnDoClick; + +public: + CScript_Button( Panel *parent, const char *name, const char *text ) : + BaseClass( parent, name, text ), + + m_hfnPaint(NULL), + m_hfnPaintBackground(NULL), + + m_hfnDoClick(NULL) + {} + + void Shutdown() + { + SetHScript( m_hfnPaint, NULL ); + SetHScript( m_hfnPaintBackground, NULL ); + + SetHScript( m_hfnDoClick, NULL ); + } + +public: + void Paint() + { + if ( m_hfnPaint ) + { + g_pScriptVM->ExecuteFunction( m_hfnPaint, NULL, 0, NULL, NULL, true ); + } + else + { + BaseClass::Paint(); + } + } + + void PaintBackground() + { + if ( m_hfnPaintBackground ) + { + g_pScriptVM->ExecuteFunction( m_hfnPaintBackground, NULL, 0, NULL, NULL, true ); + } + else + { + BaseClass::PaintBackground(); + } + } + + void DoClick() + { + BaseClass::DoClick(); + + if ( m_hfnDoClick ) + { + g_pScriptVM->ExecuteFunction( m_hfnDoClick, NULL, 0, NULL, NULL, true ); + } + } + +public: + void SetCallback( const char* cb, HSCRIPT fn ) + { + CheckCallback( Paint ); + CheckCallback( PaintBackground ); + CheckCallback( DoClick ); + + g_pScriptVM->RaiseException("invalid callback"); + } +}; + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +class CScript_TextEntry : public TextEntry +{ + DECLARE_SCRIPTVGUI_CLASS( TextEntry ); + +private: + HSCRIPT m_hfnTextChanged; + +public: + CScript_TextEntry( Panel *parent, const char *name ) : + BaseClass( parent, name ), + + m_hfnTextChanged(NULL) + {} + + void Shutdown() + { + SetHScript( m_hfnTextChanged, NULL ); + } + +public: + //--------------------------------------------- + // On "TextMessage" message. + // Used for responding to user input as it is typed. + //--------------------------------------------- + void FireActionSignal() + { + BaseClass::FireActionSignal(); + + if ( m_hfnTextChanged ) + { + g_pScriptVM->ExecuteFunction( m_hfnTextChanged, NULL, 0, NULL, NULL, true ); + } + } + +public: + void SetCallback( const char* cb, HSCRIPT fn ) + { + CheckCallback( TextChanged ); + + g_pScriptVM->RaiseException("invalid callback"); + } +}; + +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#if !defined(NO_STEAM) +class CScript_AvatarImage : public CAvatarImagePanel +{ + DECLARE_SCRIPTVGUI_CLASS_EX( CScript_AvatarImage, CAvatarImagePanel ); + +public: + CScript_AvatarImage( Panel *parent, const char *name ) : + BaseClass( parent, name ) + { + SetShouldDrawFriendIcon( false ); + } + + DEBUG_DESTRUCTOR( ~CScript_AvatarImage, CAvatarImagePanel ) + + void Shutdown() {} +}; +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#if 0 +class CTGAImagePanel : public Panel +{ + DECLARE_SCRIPTVGUI_CLASS_EX( CTGAImagePanel, Panel ); + +private: + int m_iTextureID; + int m_nWidth; + int m_nHeight; + Color m_ImageColor; + bool m_bScaleImage; + +public: + CTGAImagePanel( Panel *parent, const char *name ) : + BaseClass( parent, name ), + m_iTextureID(-1), + m_bScaleImage(0), + m_ImageColor( 255, 255, 255, 255 ) + { + SetPaintBackgroundEnabled( false ); + } + + ~CTGAImagePanel() + { + DebugDestructor( CTGAImagePanel ); + + if ( m_iTextureID != -1 ) + { + surface()->DestroyTextureID( m_iTextureID ); + } + } + + void Shutdown() {} + +public: + void Paint() + { + if ( m_iTextureID != -1 ) + { + surface()->DrawSetColor( m_ImageColor ); + surface()->DrawSetTexture( m_iTextureID ); + + if ( m_bScaleImage ) + { + int w, t; + GetSize( w, t ); + surface()->DrawTexturedRect( 0, 0, w, t ); + } + else + { + surface()->DrawTexturedRect( 0, 0, m_nWidth, m_nHeight ); + } + } + else + { + int w, t; + GetSize( w, t ); + surface()->DrawSetColor( 200, 50, 150, 255 ); + surface()->DrawFilledRect( 0, 0, w, t ); + } + } + +public: + void SetTGAImage( const char *fileName ) + { + if ( V_stricmp( V_GetFileExtension( fileName ), "tga" ) != 0 ) + return; + + CUtlMemory< unsigned char > tga; + + if ( TGALoader::LoadRGBA8888( fileName, tga, m_nWidth, m_nHeight ) ) + { + if ( m_iTextureID == -1 ) + { + m_iTextureID = surface()->CreateNewTextureID( true ); + } + + surface()->DrawSetTextureRGBA( m_iTextureID, tga.Base(), m_nWidth, m_nHeight, false, false ); + } + else + { + Warning( "Failed to load TGA image: '%s'\n", fileName ); + } + } + + void SetDrawColor( int r, int g, int b, int a ) + { + m_ImageColor.SetColor( r, g, b, a ); + } + + void SetShouldScaleImage( bool state ) + { + m_bScaleImage = state; + } +}; +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + + +//============================================================== +//============================================================== + +//-------------------------------------------------------- +// Script objects +//-------------------------------------------------------- + +DEFINE_VGUI_CLASS_EMPTY_DEFAULT_TEXT( Label ) +DEFINE_VGUI_CLASS_EMPTY( ImagePanel ) +DEFINE_VGUI_CLASS_EMPTY( RichText ) + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +BEGIN_VGUI_HELPER( Panel ) + void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( Panel ) + DEFINE_SCRIPTFUNC( SetCallback, "" ) +END_SCRIPTDESC() + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +BEGIN_VGUI_HELPER( Frame ) + void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( Frame ) + DEFINE_SCRIPTFUNC( SetCallback, "" ) +END_SCRIPTDESC() + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +BEGIN_VGUI_HELPER_DEFAULT_TEXT( Button ) + void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( Button ) + DEFINE_SCRIPTFUNC( SetCallback, "" ) +END_SCRIPTDESC() + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +BEGIN_VGUI_HELPER( TextEntry ) + void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( TextEntry ) + DEFINE_SCRIPTFUNC( SetCallback, "" ) +END_SCRIPTDESC() + +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#if !defined(NO_STEAM) +BEGIN_VGUI_HELPER( AvatarImage ) +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( AvatarImage ) +END_SCRIPTDESC() +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#if 0 +BEGIN_VGUI_HELPER_EX( TGAImagePanel, CTGAImagePanel ) +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( TGAImagePanel ) +END_SCRIPTDESC() +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + + +//============================================================== +//============================================================== + + +class CScriptVGUI : public CAutoGameSystem +{ +public: + void LevelShutdownPostEntity(); + void Shutdown(); + +public: + HSCRIPT CreatePanel( const char* panelClass, HSCRIPT parent, const char* panelName, int root ); + //void LoadSchemeFromFile( const char *filename, const char *tag ); + +} script_vgui; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptVGUI, "IVGui", SCRIPT_SINGLETON ) + DEFINE_SCRIPTFUNC( CreatePanel, SCRIPT_HIDE ) +END_SCRIPTDESC() + + +HSCRIPT CScriptVGUI::CreatePanel( const char* panelClass, HSCRIPT parent, const char* panelName, int root ) +{ + if ( (unsigned)g_ScriptPanels.Count() >= (unsigned)g_ScriptPanels.InvalidIndex()-1 ) + { + Warning( "CScriptVGUI::CreatePanel() exhausted vgui panel storage!\n" ); + return NULL; + } + +#define Check( _name )\ + if ( FStrEq( panelClass, #_name ) )\ + {\ + CScript_##_name##_Helper *helper = AllocScriptPanel< CScript_##_name##_Helper >();\ + helper->CreateFromScript< CScript_##_name##_Helper >( (HSCRIPT)parent, panelName, root );\ + DebugDevMsg( "%3d | Create vgui %s '%s' %s\n", g_ScriptPanels.Count(), panelClass, panelName, helper->GetDebugName() );\ + return helper->GetScriptInstance();\ + } + + Check( Panel ); + Check( Label ); + Check( Button ); + Check( ImagePanel ); + Check( Frame ); + Check( RichText ); + Check( TextEntry ); +#if !defined(NO_STEAM) + Check( AvatarImage ); +#endif + + g_pScriptVM->RaiseException("invalid vgui class"); + return NULL; + +#undef Check +} + +void CScriptVGUI::LevelShutdownPostEntity() +{ + DebugMsg( "LevelShutdownPostEntity()\n" ); + + while ( g_ScriptPanels.Count() ) + { + Assert( g_ScriptPanels.Head() != g_ScriptPanels.InvalidIndex() ); + + int head = g_ScriptPanels.Head(); + g_ScriptPanels[ head ]->Destroy( head ); + } + g_ScriptPanels.Purge(); + + FOR_EACH_VEC( g_ScriptTextureIDs, i ) + { +#ifdef _DEBUG + char tex[MAX_PATH]; + surface()->DrawGetTextureFile( g_ScriptTextureIDs[i], tex, sizeof(tex)-1 ); + DebugMsg( "Destroy texture [%i]%s\n", g_ScriptTextureIDs[i], tex ); +#endif + surface()->DestroyTextureID( g_ScriptTextureIDs[i] ); + } + g_ScriptTextureIDs.Purge(); +} + +void CScriptVGUI::Shutdown() +{ + VGUI_DestroyScriptRootPanels(); + + FOR_EACH_DICT_FAST( g_ScriptFonts, i ) + { + fontalias_t &alias = g_ScriptFonts[i]; + for ( int j = 0; j < alias.Count(); ++j ) + { + char *pName = alias.Element(j).name; + if ( pName ) + { + free( pName ); + alias.Element(j).name = NULL; + } + } + + alias.Purge(); + } + + g_ScriptFonts.Purge(); +} + + +class CScriptIInput +{ +public: + void MakeWeaponSelection( HSCRIPT weapon ) + { + ::input->MakeWeaponSelection( HScriptToClass< C_BaseCombatWeapon >( weapon ) ); + } +#if 0 + int GetButtonBits() + { + return ::input->GetButtonBits(0); + } + + void ClearInputButton( int i ) + { + return ::input->ClearInputButton(i); + } +#endif + void SetCursorPos( int x, int y ) + { + vgui::input()->SetCursorPos( x, y ); + } + + int GetAnalogValue( int code ) + { + Assert( code >= 0 && code < ANALOG_CODE_LAST ); + + if ( code < 0 || code >= ANALOG_CODE_LAST ) + return 0; + + return inputsystem->GetAnalogValue( (AnalogCode_t)code ); + } + + int GetAnalogDelta( int code ) + { + Assert( code >= 0 && code < ANALOG_CODE_LAST ); + + if ( code < 0 || code >= ANALOG_CODE_LAST ) + return 0; + + return inputsystem->GetAnalogDelta( (AnalogCode_t)code ); + } + + bool IsButtonDown( int code ) + { + Assert( code >= BUTTON_CODE_NONE && code < BUTTON_CODE_LAST ); + + if ( code < BUTTON_CODE_NONE || code >= BUTTON_CODE_LAST ) + return 0; + + return inputsystem->IsButtonDown( (ButtonCode_t)code ); + } + + // key -> button + int StringToButtonCode( const char *key ) + { + return inputsystem->StringToButtonCode( key ); + } + + // button -> key + const char *ButtonCodeToString( int code ) + { + Assert( code >= BUTTON_CODE_NONE && code < BUTTON_CODE_LAST ); + + if ( code < BUTTON_CODE_NONE || code >= BUTTON_CODE_LAST ) + return 0; + + return inputsystem->ButtonCodeToString( (ButtonCode_t)code ); + } + + // bind -> key + const char *LookupBinding( const char *bind ) + { + return engine->Key_LookupBinding( bind ); + } + + // button -> bind + const char *BindingForKey( int code ) + { + return engine->Key_BindingForKey( (ButtonCode_t)code ); + } +#if 0 + const char *GetIMELanguageShortCode() + { + static char ret[5]; + wchar_t get[5]; + get[0] = L'\0'; + vgui::input()->GetIMELanguageShortCode( get, wcslen(get) ); + g_pVGuiLocalize->ConvertUnicodeToANSI( get, ret, sizeof(ret) ); + return ret; + } +#endif +} script_input; + +BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptIInput, "IInput", SCRIPT_SINGLETON ) + DEFINE_SCRIPTFUNC( MakeWeaponSelection, "" ) + + DEFINE_SCRIPTFUNC( SetCursorPos, "" ) + + DEFINE_SCRIPTFUNC( GetAnalogValue, "" ) + DEFINE_SCRIPTFUNC( GetAnalogDelta, "" ) + DEFINE_SCRIPTFUNC( IsButtonDown, "" ) + + DEFINE_SCRIPTFUNC( StringToButtonCode, "" ) + DEFINE_SCRIPTFUNC( ButtonCodeToString, "" ) + DEFINE_SCRIPTFUNC( LookupBinding, "" ) + DEFINE_SCRIPTFUNC( BindingForKey, "" ) +END_SCRIPTDESC() + + +void SetClipboardText( const char *text ) +{ + system()->SetClipboardText( text, V_strlen(text) ); +} + +//============================================================== +//============================================================== + +#if 0 +//----------------------------------------------------------------------------- +// Get world position in screen space [0,1]. Return true if on screen. +//----------------------------------------------------------------------------- +inline bool WorldToScreen( const Vector &pos, int &ix, int &iy ) +{ + int scrw, scrh; + surface()->GetScreenSize( scrw, scrh ); + + const VMatrix &worldToScreen = engine->WorldToScreenMatrix(); + bool bOnScreen; + + // VMatrix * Vector (position projective) + vec_t w = worldToScreen[3][0] * pos[0] + worldToScreen[3][1] * pos[1] + worldToScreen[3][2] * pos[2] + worldToScreen[3][3]; + vec_t fx = worldToScreen[0][0] * pos[0] + worldToScreen[0][1] * pos[1] + worldToScreen[0][2] * pos[2] + worldToScreen[0][3]; + vec_t fy = worldToScreen[1][0] * pos[0] + worldToScreen[1][1] * pos[1] + worldToScreen[1][2] * pos[2] + worldToScreen[1][3]; + + if ( w < 0.001f ) + { + fx *= 1e5f; + fy *= 1e5f; + bOnScreen = false; + } + else + { + w = 1.0f / w; + fx *= w; + fy *= w; + bOnScreen = true; + } + + ix = (int)( scrw * 0.5f * ( 1.0f + fx ) + 0.5f ); + iy = (int)( scrh * 0.5f * ( 1.0f - fy ) + 0.5f ); + + return bOnScreen; +} +#endif +//----------------------------------------------------------------------------- +// Get screen pixel position [0,1] in world space. +//----------------------------------------------------------------------------- +inline void ScreenToWorld( int x, int y, Vector &out ) +{ + int scrw, scrh; + surface()->GetScreenSize( scrw, scrh ); + float scrx = (float)x / (float)scrw; + float scry = (float)y / (float)scrh; + + vec_t tmp[2]; + tmp[0] = 2.0f * scrx - 1.0f; + tmp[1] = 1.0f - 2.0f * scry; + //tmp[2] = 1.0f; + //tmp[3] = 1.0f; + + VMatrix screenToWorld; + MatrixInverseGeneral( engine->WorldToScreenMatrix(), screenToWorld ); + + // VMatrix * Vector (position projective) + vec_t iw = 1.0f / ( screenToWorld[3][0] * tmp[0] + screenToWorld[3][1] * tmp[1] + screenToWorld[3][2] + screenToWorld[3][3] ); + out[0] = iw * ( screenToWorld[0][0] * tmp[0] + screenToWorld[0][1] * tmp[1] + screenToWorld[0][2] + screenToWorld[0][3] ); + out[1] = iw * ( screenToWorld[1][0] * tmp[0] + screenToWorld[1][1] * tmp[1] + screenToWorld[1][2] + screenToWorld[1][3] ); + out[2] = iw * ( screenToWorld[2][0] * tmp[0] + screenToWorld[2][1] * tmp[1] + screenToWorld[2][2] + screenToWorld[2][3] ); +} + +#if 0 +static bool ScriptWorldToScreen( const Vector &pos, HSCRIPT out ) +{ + int ix, iy; + bool r = WorldToScreen( pos, ix, iy ); + + g_pScriptVM->SetValue( out, (ScriptVariant_t)0, ix ); + g_pScriptVM->SetValue( out, 1, iy ); + return r; +} +#endif +static const Vector& ScriptScreenToWorld( int x, int y ) +{ + static Vector out; + ScreenToWorld( x, y, out ); + return out; +} + +static const Vector& ScreenToRay( int x, int y ) +{ + static Vector out; + ScreenToWorld( x, y, out ); + VectorSubtract( out, CurrentViewOrigin(), out ); + VectorNormalize( out ); + return out; +} + +//----------------------------------------------------------------------------- +// Get world position normalised in screen space. Return true if on screen. +//----------------------------------------------------------------------------- +int ScreenTransform( const Vector& point, Vector& screen ); +static bool ScriptScreenTransform( const Vector &pos, HSCRIPT out ) +{ + Vector v; + bool r = ScreenTransform( pos, v ); + float x = 0.5f * ( 1.0f + v[0] ); + float y = 0.5f * ( 1.0f - v[1] ); + + g_pScriptVM->SetValue( out, (ScriptVariant_t)0, x ); + g_pScriptVM->SetValue( out, 1, y ); + return !r; +} + +int ScriptScreenWidth() +{ + int w, h; + surface()->GetScreenSize( w, h ); + return w; +} + +int ScriptScreenHeight() +{ + int w, h; + surface()->GetScreenSize( w, h ); + return h; +} + +// +// Saving the static (ScreenWidth/640) ratio in a script closure +// messes up on save/restore at differing resolutions - +// the closure and the user script funcs retain the ratio at the time of the save. +// It is not possible to update restored script closure outer variables without writing language specific functions. +// +// NOTE: Returns int! int usage is more common than float operations. +// +static int ScriptXRES( float x ) +{ + return x * ( (float)ScriptScreenWidth() / 640.0f ); +} + +static int ScriptYRES( float y ) +{ + return y * ( (float)ScriptScreenHeight() / 480.0f ); +} + +vgui::HFont GetScriptFont( const char *name, bool proportional ) +{ + return script_surface.GetFont( name, proportional, NULL ); +} + + +void RegisterScriptVGUI() +{ + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptXRES, "XRES", "" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptYRES, "YRES", "" ); + + ScriptRegisterFunction( g_pScriptVM, SetClipboardText, "" ); + //ScriptRegisterFunctionNamed( g_pScriptVM, ScriptWorldToScreen, "WorldToScreen", "Get world position in screen space [0,1]. Return true if on screen." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenToWorld, "ScreenToWorld", "Get screen pixel position [0,1] in world space." ); + ScriptRegisterFunction( g_pScriptVM, ScreenToRay, "Get a ray from screen pixel position to world space." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get world position normalised in screen space. Return true if on screen." ); + + g_pScriptVM->Run( g_Script_vgui_init ); + + g_pScriptVM->RegisterInstance( &script_surface, "surface" ); + g_pScriptVM->RegisterInstance( &script_input, "input" ); + g_pScriptVM->RegisterInstance( &script_vgui, "vgui" ); +} diff --git a/sp/src/game/client/mapbase/vscript_vgui.h b/sp/src/game/client/mapbase/vscript_vgui.h new file mode 100644 index 00000000..d5214073 --- /dev/null +++ b/sp/src/game/client/mapbase/vscript_vgui.h @@ -0,0 +1,16 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VSCRIPT_VGUI_H +#define VSCRIPT_VGUI_H +#ifdef _WIN32 +#pragma once +#endif + +void RegisterScriptVGUI(); + +#endif diff --git a/sp/src/game/client/mapbase/vscript_vgui.nut b/sp/src/game/client/mapbase/vscript_vgui.nut new file mode 100644 index 00000000..df0285eb --- /dev/null +++ b/sp/src/game/client/mapbase/vscript_vgui.nut @@ -0,0 +1,395 @@ +static const char* g_Script_vgui_init = R"script( +local DoCreateFont = ISurface.CreateFont; +ISurface.CreateFont <- function( name, props ) +{ + if ( !("name" in props) || typeof props.name != "string" ) + throw "invalid parameter 'name'"; + + if ( !("tall" in props) || typeof props.tall != "integer" || !props.tall ) + throw "invalid parameter 'tall'"; + + if ( !("weight" in props) || typeof props.weight != "integer" ) + throw "invalid parameter 'weight'"; + + local yres_min = 0, yres_max = 0; + + if ( "yres" in props && typeof props.yres == "string" ) + { + local ss = ::split( props.yres, " " ); + try + { + yres_min = ss[0].tointeger(); + yres_max = ss[1].tointeger(); + } + catch(x) + { + throw "invalid parameter 'yres'"; + } + } + + if ( ( (!("proportional" in props) || typeof props.proportional != "bool") ) && !yres_min ) + { + throw "parameter 'proportional' or 'yres' not found"; + } + else if ( "proportional" in props && props.proportional && yres_min ) + { + throw "resolution definition on a proportional font" + } + + local blur = 0, scanlines = 0, proportional = false, flags = 0; + + if ( "blur" in props && typeof props.blur == "integer" ) + blur = props.blur; + + if ( "scanlines" in props && typeof props.scanlines == "integer" ) + scanlines = props.scanlines; + + if ( "proportional" in props && typeof props.proportional == "bool" ) + proportional = props.proportional; + + if ( "italic" in props && props.italic == true ) + flags = flags | 0x001; + + if ( "underline" in props && props.underline == true ) + flags = flags | 0x002; + + if ( "strikeout" in props && props.strikeout == true ) + flags = flags | 0x004; + + if ( "symbol" in props && props.symbol == true ) + flags = flags | 0x008; + + if ( "antialias" in props && props.antialias == true ) + flags = flags | 0x010; + + if ( "gaussianblur" in props && props.gaussianblur == true ) + flags = flags | 0x020; + + if ( "rotary" in props && props.rotary == true ) + flags = flags | 0x040; + + if ( "dropshadow" in props && props.dropshadow == true ) + flags = flags | 0x080; + + if ( "additive" in props && props.additive == true ) + flags = flags | 0x100; + + if ( "outline" in props && props.outline == true ) + flags = flags | 0x200; + + if ( "custom" in props && props.custom == true ) + flags = flags | 0x400; + + if ( "bitmap" in props && props.bitmap == true ) + flags = flags | 0x800; + + return DoCreateFont( name, props.name, props.tall, props.weight, blur, scanlines, flags, yres_min, yres_max, proportional ); +} + +local _Schemes = {} +local _FontTall = {} +local DoGetFont = ISurface.DoGetFont <- ISurface.GetFont; +local DoGetFontTall = ISurface.GetFontTall; + +ISurface.GetFont <- function( name, proportional = false, sch = "" ) +{ + if ( sch in _Schemes ) + { + local fonts = _Schemes[sch][proportional.tointeger()]; + if ( name in fonts ) + return fonts[name]; + } + else + { + _Schemes[sch] <- [{}, {}]; + } + + local id = DoGetFont( name, proportional, sch ); + if ( id > 0 ) + _Schemes[sch][proportional.tointeger()][name] <- id; + + return id; +} + +ISurface.GetFontTall <- function( id ) +{ + if ( id in _FontTall ) + return _FontTall[id]; + return _FontTall[id] <- DoGetFontTall( id ); +} + +local _Textures = {} +local DoGetTextureID = ISurface.GetTextureID; +local DoValidateTexture = ISurface.ValidateTexture; +local DoSetTextureFile = ISurface.SetTextureFile; + +ISurface.ValidateTexture <- function( filename, hardwareFilter, forceReload = false, procedural = false ) +{ + return DoValidateTexture( filename, hardwareFilter, forceReload, procedural ); +} + +ISurface.SetTextureFile <- function( id, filename, hardwareFilter ) +{ + if ( filename in _Textures ) + delete _Textures[filename]; + + return DoSetTextureFile( id, filename, hardwareFilter ); +} + +ISurface.GetTextureID <- function( name ) +{ + if ( name in _Textures ) + return _Textures[name]; + + local id = DoGetTextureID( name ); + if ( id > 0 ) + _Textures[name] <- id; + + return id; +} + +// Forward compatibility +IVGui.GetRootPanel <- function() { return 1000 } +//IVGui.GetGameUIRootPanel <- function() { return 1001 } +IVGui.GetClientDLLRootPanel <- function() { return 1002 } + +local CreatePanel = IVGui.CreatePanel; +IVGui.CreatePanel <- function( type, parent, name ) +{ + if ( !parent ) + throw "invalid parent"; + + local root = 0; + + if ( typeof parent == "integer" ) + { + switch ( parent ) + { + case 1000: + root = 0; + break; + + case 1001: + root = 1; + break; + + case 1002: + root = 2; + break; + + default: + throw "invalid parent"; + } + parent = null; + } + return CreatePanel( type, parent, name, root ); +} + +ISurface.__OnScreenSizeChanged <- function() +{ + _FontTall.clear(); +} + +// MAX_JOYSTICKS = 1 // ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) +// MAX_JOYSTICK_AXES = 6 // X,Y,Z,R,U,V +// JOYSTICK_MAX_BUTTON_COUNT = 32 +// JOYSTICK_POV_BUTTON_COUNT = 4 +// JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2 + +enum ButtonCode +{ + KEY_FIRST = 0 + KEY_0 = 1 + KEY_1 = 2 + KEY_2 = 3 + KEY_3 = 4 + KEY_4 = 5 + KEY_5 = 6 + KEY_6 = 7 + KEY_7 = 8 + KEY_8 = 9 + KEY_9 = 10 + KEY_A = 11 + KEY_B = 12 + KEY_C = 13 + KEY_D = 14 + KEY_E = 15 + KEY_F = 16 + KEY_G = 17 + KEY_H = 18 + KEY_I = 19 + KEY_J = 20 + KEY_K = 21 + KEY_L = 22 + KEY_M = 23 + KEY_N = 24 + KEY_O = 25 + KEY_P = 26 + KEY_Q = 27 + KEY_R = 28 + KEY_S = 29 + KEY_T = 30 + KEY_U = 31 + KEY_V = 32 + KEY_W = 33 + KEY_X = 34 + KEY_Y = 35 + KEY_Z = 36 + KEY_PAD_0 = 37 + KEY_PAD_1 = 38 + KEY_PAD_2 = 39 + KEY_PAD_3 = 40 + KEY_PAD_4 = 41 + KEY_PAD_5 = 42 + KEY_PAD_6 = 43 + KEY_PAD_7 = 44 + KEY_PAD_8 = 45 + KEY_PAD_9 = 46 + KEY_PAD_DIVIDE = 47 + KEY_PAD_MULTIPLY = 48 + KEY_PAD_MINUS = 49 + KEY_PAD_PLUS = 50 + KEY_PAD_ENTER = 51 + KEY_PAD_DECIMAL = 52 + KEY_LBRACKET = 53 + KEY_RBRACKET = 54 + KEY_SEMICOLON = 55 + KEY_APOSTROPHE = 56 + KEY_BACKQUOTE = 57 + KEY_COMMA = 58 + KEY_PERIOD = 59 + KEY_SLASH = 60 + KEY_BACKSLASH = 61 + KEY_MINUS = 62 + KEY_EQUAL = 63 + KEY_ENTER = 64 + KEY_SPACE = 65 + KEY_BACKSPACE = 66 + KEY_TAB = 67 + KEY_CAPSLOCK = 68 + KEY_NUMLOCK = 69 + KEY_ESCAPE = 70 + KEY_SCROLLLOCK = 71 + KEY_INSERT = 72 + KEY_DELETE = 73 + KEY_HOME = 74 + KEY_END = 75 + KEY_PAGEUP = 76 + KEY_PAGEDOWN = 77 + KEY_BREAK = 78 + KEY_LSHIFT = 79 + KEY_RSHIFT = 80 + KEY_LALT = 81 + KEY_RALT = 82 + KEY_LCONTROL = 83 + KEY_RCONTROL = 84 + KEY_LWIN = 85 + KEY_RWIN = 86 + KEY_APP = 87 + KEY_UP = 88 + KEY_LEFT = 89 + KEY_DOWN = 90 + KEY_RIGHT = 91 + KEY_F1 = 92 + KEY_F2 = 93 + KEY_F3 = 94 + KEY_F4 = 95 + KEY_F5 = 96 + KEY_F6 = 97 + KEY_F7 = 98 + KEY_F8 = 99 + KEY_F9 = 100 + KEY_F10 = 101 + KEY_F11 = 102 + KEY_F12 = 103 + KEY_CAPSLOCKTOGGLE = 104 + KEY_NUMLOCKTOGGLE = 105 + KEY_SCROLLLOCKTOGGLE = 106 + KEY_LAST = 106 + + MOUSE_FIRST = 107 + MOUSE_LEFT = 107 + MOUSE_RIGHT = 108 + MOUSE_MIDDLE = 109 + MOUSE_4 = 110 + MOUSE_5 = 111 + MOUSE_WHEEL_UP = 112 + MOUSE_WHEEL_DOWN = 113 + MOUSE_LAST = 113 + + JOYSTICK_FIRST = 114 + JOYSTICK_FIRST_BUTTON = 114 + JOYSTICK_LAST_BUTTON = 145 + JOYSTICK_FIRST_POV_BUTTON = 146 + JOYSTICK_LAST_POV_BUTTON = 149 + JOYSTICK_FIRST_AXIS_BUTTON = 150 + JOYSTICK_LAST_AXIS_BUTTON = 161 + JOYSTICK_LAST = 161 +} + +enum AnalogCode +{ + MOUSE_X = 0 + MOUSE_Y = 1 + MOUSE_XY = 2 + MOUSE_WHEEL = 3 + + JOYSTICK_FIRST_AXIS = 4 + JOYSTICK_LAST_AXIS = 9 +} + +enum CursorCode +{ + dc_none = 1 + dc_arrow = 2 + dc_ibeam = 3 + dc_hourglass = 4 + dc_waitarrow = 5 + dc_crosshair = 6 + dc_up = 7 + dc_sizenwse = 8 + dc_sizenesw = 9 + dc_sizewe = 10 + dc_sizens = 11 + dc_sizeall = 12 + dc_no = 13 + dc_hand = 14 + dc_blank = 15 +} + +enum Alignment +{ + northwest = 0 + north = 1 + northeast = 2 + west = 3 + center = 4 + east = 5 + southwest = 6 + south = 7 + southeast = 8 +} + +if ( __Documentation.RegisterHelp != dummy ) +{ + local RegEnum = function( e ) + { + local K = getconsttable()[e]; + __Documentation.RegisterEnumHelp( e, K.len(), "" ); + e += "."; + foreach ( s, v in K ) + { + __Documentation.RegisterConstHelp( e+s, v, "" ); + } + } + RegEnum( "ButtonCode" ); + RegEnum( "AnalogCode" ); + RegEnum( "CursorCode" ); + RegEnum( "Alignment" ); + + __Documentation.RegisterHelp( "ISurface::CreateFont", "void ISurface::CreateFont(string, handle)", "" ); + __Documentation.RegisterHelp( "IVGui::CreatePanel", "handle IVGui::CreatePanel(string, handle, string)", "" ); + __Documentation.RegisterHelp( "IVGui::GetRootPanel", "handle IVGui::GetRootPanel()", "" ); + __Documentation.RegisterHelp( "IVGui::GetClientDLLRootPanel", "handle IVGui::GetClientDLLRootPanel()", "" ); +} +)script"; diff --git a/sp/src/game/client/vscript_client.cpp b/sp/src/game/client/vscript_client.cpp index faf35c16..6c8c5371 100644 --- a/sp/src/game/client/vscript_client.cpp +++ b/sp/src/game/client/vscript_client.cpp @@ -22,6 +22,7 @@ #include "materialsystem/imaterialvar.h" #include "mapbase/matchers.h" #include "mapbase/vscript_singletons.h" +#include "mapbase/vscript_vgui.h" #endif extern IScriptManager *scriptmanager; @@ -521,6 +522,9 @@ bool DoIncludeScript( const char *pszScript, HSCRIPT hScope ) } #ifdef MAPBASE_VSCRIPT +int ScriptScreenWidth(); +int ScriptScreenHeight(); + static float FrameTime() { return gpGlobals->frametime; @@ -536,27 +540,6 @@ static bool IsWindowedMode() return engine->IsWindowedMode(); } -int ScreenTransform( const Vector& point, Vector& screen ); - -//----------------------------------------------------------------------------- -// Input array [x,y], set normalised screen space pos. Return true if on screen -//----------------------------------------------------------------------------- -static bool ScriptScreenTransform( const Vector &pos, HSCRIPT hArray ) -{ - if ( g_pScriptVM->GetNumTableEntries(hArray) >= 2 ) - { - Vector v; - bool r = ScreenTransform( pos, v ); - float x = 0.5f * ( 1.0f + v[0] ); - float y = 0.5f * ( 1.0f - v[1] ); - - g_pScriptVM->SetValue( hArray, ScriptVariant_t(0), x ); - g_pScriptVM->SetValue( hArray, 1, y ); - return !r; - } - return false; -} - // Creates a client-side prop HSCRIPT CreateProp( const char *pszEntityName, const Vector &vOrigin, const char *pszModelName, int iAnim ) { @@ -657,10 +640,9 @@ bool VScriptClientInit() #ifdef MAPBASE_VSCRIPT ScriptRegisterFunction( g_pScriptVM, FrameTime, "Get the time spent on the client in the last frame" ); ScriptRegisterFunction( g_pScriptVM, Con_IsVisible, "Returns true if the console is visible" ); - ScriptRegisterFunction( g_pScriptVM, ScreenWidth, "Width of the screen in pixels" ); - ScriptRegisterFunction( g_pScriptVM, ScreenHeight, "Height of the screen in pixels" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenWidth, "ScreenWidth", "Width of the screen in pixels" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenHeight, "ScreenHeight", "Height of the screen in pixels" ); ScriptRegisterFunction( g_pScriptVM, IsWindowedMode, "" ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get the x & y positions of a world position in screen space. Returns true if it's onscreen" ); ScriptRegisterFunction( g_pScriptVM, MainViewOrigin, "" ); ScriptRegisterFunction( g_pScriptVM, MainViewAngles, "" ); @@ -695,6 +677,7 @@ bool VScriptClientInit() RegisterSharedScriptConstants(); RegisterSharedScriptFunctions(); + RegisterScriptVGUI(); #else //g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" ); #endif From 21407c3394b53968bcd45c119cd78e1a3b858ffd Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sat, 22 Oct 2022 16:06:57 -0500 Subject: [PATCH 29/65] Update sp/src/game/server/particle_system.cpp Co-authored-by: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> --- sp/src/game/server/particle_system.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index a8f576a7..53ce7778 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -264,11 +264,11 @@ void CParticleSystem::ReadControlPointEnts(void) for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { if (UsesCoordinates()) { - float vecCoords[3]; + Vector vecCoords; // cast str to vector, add vector to array const char* pszVector = STRING(m_iszControlPointNames[i]); - UTIL_StringToVector(vecCoords, pszVector); - m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); + UTIL_StringToVector(vecCoords.Base(), pszVector); + m_vControlPointVecs.Set(i, vecCoords); } else{ if (m_iszControlPointNames[i] == NULL_STRING) From 9db4259f187fcf1f89b17e70558074e0fc32436c Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 24 Oct 2022 13:32:08 -0500 Subject: [PATCH 30/65] Update .github/workflows/mapbase_build-base-dispatch.yml Co-authored-by: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> --- .github/workflows/mapbase_build-base-dispatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mapbase_build-base-dispatch.yml b/.github/workflows/mapbase_build-base-dispatch.yml index bd461597..f7275435 100644 --- a/.github/workflows/mapbase_build-base-dispatch.yml +++ b/.github/workflows/mapbase_build-base-dispatch.yml @@ -60,7 +60,7 @@ on: jobs: build_manual: - uses: mapbase-source/source-sdk-2013/.github/workflows/mapbase_build-base.yml@feature/github-workflows + uses: ./.github/workflows/mapbase_build-base.yml with: configuration: '${{ github.event.inputs.configuration }}' branch: '${{ github.event.inputs.branch }}' From 8039c9befa81b106f2271864507551badd9f538d Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 24 Oct 2022 13:35:31 -0500 Subject: [PATCH 31/65] Update mapbase_pr.yml --- .github/workflows/mapbase_pr.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/mapbase_pr.yml b/.github/workflows/mapbase_pr.yml index f06982e4..87c2b0e2 100644 --- a/.github/workflows/mapbase_pr.yml +++ b/.github/workflows/mapbase_pr.yml @@ -2,7 +2,6 @@ # MAPBASE REPO AUTOMATION # # Automatically labels pull requests according to changed file paths. -# See mapbase_triage-pr.yml for more information. # # https://github.com/actions/labeler From 12742b7815cf0bf8f3e1b6f4605a3344a3a0456c Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 13:37:59 -0500 Subject: [PATCH 32/65] Fix spacing in particle system files --- sp/src/game/client/c_particle_system.cpp | 192 +++++++++-------- sp/src/game/server/particle_system.cpp | 264 ++++++++++++----------- sp/src/game/server/particle_system.h | 46 ++-- 3 files changed, 254 insertions(+), 248 deletions(-) diff --git a/sp/src/game/client/c_particle_system.cpp b/sp/src/game/client/c_particle_system.cpp index 4986bccd..a42fae76 100644 --- a/sp/src/game/client/c_particle_system.cpp +++ b/sp/src/game/client/c_particle_system.cpp @@ -19,15 +19,15 @@ //----------------------------------------------------------------------------- class C_ParticleSystem : public C_BaseEntity { - DECLARE_CLASS(C_ParticleSystem, C_BaseEntity); + DECLARE_CLASS( C_ParticleSystem, C_BaseEntity ); public: DECLARE_CLIENTCLASS(); C_ParticleSystem(); - void PreDataUpdate(DataUpdateType_t updateType); - void PostDataUpdate(DataUpdateType_t updateType); - void ClientThink(void); + void PreDataUpdate( DataUpdateType_t updateType ); + void PostDataUpdate( DataUpdateType_t updateType ); + void ClientThink( void ); protected: int m_iEffectIndex; @@ -40,7 +40,7 @@ protected: enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me - + EHANDLE m_hControlPointEnts[kMAXCONTROLPOINTS]; Vector m_vControlPointVecs[kMAXCONTROLPOINTS]; // SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), @@ -51,24 +51,24 @@ protected: IMPLEMENT_CLIENTCLASS(C_ParticleSystem, DT_ParticleSystem, CParticleSystem); -BEGIN_RECV_TABLE_NOBASE(C_ParticleSystem, DT_ParticleSystem) -RecvPropVector(RECVINFO_NAME(m_vecNetworkOrigin, m_vecOrigin)), -RecvPropEHandle(RECVINFO(m_hOwnerEntity)), -RecvPropInt(RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent), -RecvPropInt(RECVINFO(m_iParentAttachment)), -RecvPropQAngles(RECVINFO_NAME(m_angNetworkAngles, m_angRotation)), +BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem ) + RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ), + RecvPropEHandle( RECVINFO(m_hOwnerEntity) ), + RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ), + RecvPropInt( RECVINFO( m_iParentAttachment ) ), + RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ), -RecvPropInt(RECVINFO(m_iEffectIndex)), -RecvPropBool(RECVINFO(m_bActive)), + RecvPropInt( RECVINFO( m_iEffectIndex ) ), + RecvPropBool( RECVINFO( m_bActive ) ), #ifdef MAPBASE -RecvPropBool(RECVINFO(m_bDestroyImmediately)), + RecvPropBool( RECVINFO( m_bDestroyImmediately ) ), #endif -RecvPropFloat(RECVINFO(m_flStartTime)), + RecvPropFloat( RECVINFO( m_flStartTime ) ), -RecvPropArray3(RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle(RECVINFO(m_hControlPointEnts[0]))), -RecvPropArray3(RECVINFO_ARRAY(m_vControlPointVecs), RecvPropVector(RECVINFO(m_vControlPointVecs[0]))), -RecvPropArray3(RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt(RECVINFO(m_iControlPointParents[0]))), -RecvPropBool(RECVINFO(m_bWeatherEffect)), + RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ), + RecvPropArray3( RECVINFO_ARRAY(m_vControlPointVecs), RecvPropVector( RECVINFO( m_vControlPointVecs[0] ) ) ), + RecvPropArray3( RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt( RECVINFO(m_iControlPointParents[0]))), + RecvPropBool( RECVINFO( m_bWeatherEffect ) ), END_RECV_TABLE(); //----------------------------------------------------------------------------- @@ -82,38 +82,38 @@ C_ParticleSystem::C_ParticleSystem() //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::PreDataUpdate(DataUpdateType_t updateType) +void C_ParticleSystem::PreDataUpdate( DataUpdateType_t updateType ) { m_bOldActive = m_bActive; - BaseClass::PreDataUpdate(updateType); + BaseClass::PreDataUpdate( updateType ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::PostDataUpdate(DataUpdateType_t updateType) +void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) { - BaseClass::PostDataUpdate(updateType); + BaseClass::PostDataUpdate( updateType ); // Always restart if just created and updated // FIXME: Does this play fairly with PVS? - if (updateType == DATA_UPDATE_CREATED) + if ( updateType == DATA_UPDATE_CREATED ) { - if (m_bActive) + if ( m_bActive ) { // Delayed here so that we don't get invalid abs queries on level init with active particle systems - SetNextClientThink(gpGlobals->curtime); + SetNextClientThink( gpGlobals->curtime ); } } else { - if (m_bOldActive != m_bActive) + if ( m_bOldActive != m_bActive ) { - if (m_bActive) + if ( m_bActive ) { // Delayed here so that we don't get invalid abs queries on level init with active particle systems - SetNextClientThink(gpGlobals->curtime); + SetNextClientThink( gpGlobals->curtime ); } else #ifdef MAPBASE @@ -125,8 +125,8 @@ void C_ParticleSystem::PostDataUpdate(DataUpdateType_t updateType) } #else { - ParticleProp()->StopEmission(); - } + ParticleProp()->StopEmission(); + } #endif } } @@ -135,28 +135,30 @@ void C_ParticleSystem::PostDataUpdate(DataUpdateType_t updateType) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::ClientThink(void) +void C_ParticleSystem::ClientThink( void ) { - if (m_bActive) + if ( m_bActive ) { - const char *pszName = GetParticleSystemNameFromIndex(m_iEffectIndex); - if (pszName && pszName[0]) + const char *pszName = GetParticleSystemNameFromIndex( m_iEffectIndex ); + if ( pszName && pszName[0] ) { - if (!GameRules()->AllowMapParticleEffect(pszName)) + if ( !GameRules()->AllowMapParticleEffect( pszName ) ) return; - if (m_bWeatherEffect && !GameRules()->AllowWeatherParticles()) + if ( m_bWeatherEffect && !GameRules()->AllowWeatherParticles() ) return; - CNewParticleEffect *pEffect = ParticleProp()->Create(pszName, PATTACH_ABSORIGIN_FOLLOW); - AssertMsg1(pEffect, "Particle system couldn't make %s", pszName); + CNewParticleEffect *pEffect = ParticleProp()->Create( pszName, PATTACH_ABSORIGIN_FOLLOW ); + AssertMsg1( pEffect, "Particle system couldn't make %s", pszName ); if (pEffect) { - if (m_vControlPointVecs[0] != GetAbsOrigin() && m_hControlPointEnts[0] == NULL){ + if (m_vControlPointVecs[0] != GetAbsOrigin() && m_hControlPointEnts[0] == NULL) + { // we are using info_particle_system_coordinate for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { ParticleProp()->AddControlPoint(pEffect, i + 1, this, PATTACH_WORLDORIGIN, 0, m_vControlPointVecs[i] - GetAbsOrigin()); + AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS, "Particle system specified bogus control point parent (%d) for point %d.", m_iControlPointParents[i], i); @@ -167,21 +169,23 @@ void C_ParticleSystem::ClientThink(void) } } } - else{ - for (int i = 0; i < kMAXCONTROLPOINTS; ++i) + else + { + for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i ) { - CBaseEntity* pOnEntity = m_hControlPointEnts[i].Get(); - if (pOnEntity) + CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get(); + if ( pOnEntity ) { - ParticleProp()->AddControlPoint(pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW); + ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW ); } - AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS, + + AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS , "Particle system specified bogus control point parent (%d) for point %d.", - m_iControlPointParents[i], i); + m_iControlPointParents[i], i ); if (m_iControlPointParents[i] != 0) { - pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]); + pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]); } } } @@ -190,14 +194,14 @@ void C_ParticleSystem::ClientThink(void) // already past the end of it, denoting that we're finished. In that case, just destroy us and be done. -- jdw // TODO: This can go when the SkipToTime code below goes - ParticleProp()->OnParticleSystemUpdated(pEffect, 0.0f); + ParticleProp()->OnParticleSystemUpdated( pEffect, 0.0f ); // Skip the effect ahead if we're restarting it float flTimeDelta = gpGlobals->curtime - m_flStartTime; - if (flTimeDelta > 0.01f) + if ( flTimeDelta > 0.01f ) { - VPROF_BUDGET("C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation"); - pEffect->SkipToTime(flTimeDelta); + VPROF_BUDGET( "C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation" ); + pEffect->SkipToTime( flTimeDelta ); } } } @@ -211,79 +215,79 @@ void C_ParticleSystem::ClientThink(void) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void ParticleEffectCallback(const CEffectData &data) +void ParticleEffectCallback( const CEffectData &data ) { - if (SuppressingParticleEffects()) + if ( SuppressingParticleEffects() ) return; // this needs to be before using data.m_nHitBox, since that may be a serialized value that's past the end of the current particle system string table - const char *pszName = GetParticleSystemNameFromIndex(data.m_nHitBox); + const char *pszName = GetParticleSystemNameFromIndex( data.m_nHitBox ); CSmartPtr pEffect = NULL; - if (data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY) + if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) { - if (data.m_hEntity.Get()) + if ( data.m_hEntity.Get() ) { - C_BaseEntity *pEnt = C_BaseEntity::Instance(data.m_hEntity); - if (pEnt && !pEnt->IsDormant()) + C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); + if ( pEnt && !pEnt->IsDormant() ) { - if (data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES) + if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES ) { pEnt->ParticleProp()->StopEmission(); } - pEffect = pEnt->ParticleProp()->Create(pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex); - AssertMsg2(pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", - C_BaseEntity::Instance(data.m_hEntity)->GetDebugName(), pszName); - if (pEffect.IsValid() && pEffect->IsValid()) + pEffect = pEnt->ParticleProp()->Create( pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex ); + AssertMsg2( pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", + C_BaseEntity::Instance( data.m_hEntity )->GetDebugName(), pszName ); + if ( pEffect.IsValid() && pEffect->IsValid() ) { - if ((ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN) + if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN ) { - pEffect->SetSortOrigin(data.m_vOrigin); - pEffect->SetControlPoint(0, data.m_vOrigin); - pEffect->SetControlPoint(1, data.m_vStart); + pEffect->SetSortOrigin( data.m_vOrigin ); + pEffect->SetControlPoint( 0, data.m_vOrigin ); + pEffect->SetControlPoint( 1, data.m_vStart ); Vector vecForward, vecRight, vecUp; - AngleVectors(data.m_vAngles, &vecForward, &vecRight, &vecUp); - pEffect->SetControlPointOrientation(0, vecForward, vecRight, vecUp); + AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); + pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); } } } } - } + } else { - if (GameRules()) + if ( GameRules() ) { - pszName = GameRules()->TranslateEffectForVisionFilter("particles", pszName); + pszName = GameRules()->TranslateEffectForVisionFilter( "particles", pszName ); } - pEffect = CNewParticleEffect::Create(NULL, pszName); - if (pEffect->IsValid()) + pEffect = CNewParticleEffect::Create( NULL, pszName ); + if ( pEffect->IsValid() ) { - pEffect->SetSortOrigin(data.m_vOrigin); - pEffect->SetControlPoint(0, data.m_vOrigin); - pEffect->SetControlPoint(1, data.m_vStart); + pEffect->SetSortOrigin( data.m_vOrigin ); + pEffect->SetControlPoint( 0, data.m_vOrigin ); + pEffect->SetControlPoint( 1, data.m_vStart ); Vector vecForward, vecRight, vecUp; - AngleVectors(data.m_vAngles, &vecForward, &vecRight, &vecUp); - pEffect->SetControlPointOrientation(0, vecForward, vecRight, vecUp); + AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); + pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); } } - if (pEffect.IsValid() && pEffect->IsValid()) + if ( pEffect.IsValid() && pEffect->IsValid() ) { - if (data.m_bCustomColors) + if ( data.m_bCustomColors ) { - pEffect->SetControlPoint(CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1); - pEffect->SetControlPoint(CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2); + pEffect->SetControlPoint( CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1 ); + pEffect->SetControlPoint( CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2 ); } - if (data.m_bControlPoint1) + if ( data.m_bControlPoint1 ) { - pEffect->SetControlPoint(1, data.m_ControlPoint1.m_vecOffset); + pEffect->SetControlPoint( 1, data.m_ControlPoint1.m_vecOffset ); } } } -DECLARE_CLIENT_EFFECT("ParticleEffect", ParticleEffectCallback); +DECLARE_CLIENT_EFFECT( "ParticleEffect", ParticleEffectCallback ); //====================================================================================================================== @@ -292,16 +296,16 @@ DECLARE_CLIENT_EFFECT("ParticleEffect", ParticleEffectCallback); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void ParticleEffectStopCallback(const CEffectData &data) +void ParticleEffectStopCallback( const CEffectData &data ) { - if (data.m_hEntity.Get()) + if ( data.m_hEntity.Get() ) { - C_BaseEntity *pEnt = C_BaseEntity::Instance(data.m_hEntity); - if (pEnt) + C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); + if ( pEnt ) { - pEnt->ParticleProp()->StopEmission(); + pEnt->ParticleProp()->StopEmission(); + } } } -} -DECLARE_CLIENT_EFFECT("ParticleEffectStop", ParticleEffectStopCallback); +DECLARE_CLIENT_EFFECT( "ParticleEffectStop", ParticleEffectStopCallback ); diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index 53ce7778..23e98eaf 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -12,128 +12,127 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -extern void SendProxy_Origin(const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); -extern void SendProxy_Angles(const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); +extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); // Stripped down CBaseEntity send table IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleSystem, DT_ParticleSystem) -SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin), -SendPropEHandle(SENDINFO(m_hOwnerEntity)), -SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent)), -SendPropInt(SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), -SendPropQAngles(SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles), + SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), + SendPropEHandle (SENDINFO(m_hOwnerEntity)), + SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), + SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), + SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), -SendPropInt(SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED), -SendPropBool(SENDINFO(m_bActive)), + SendPropInt( SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED ), + SendPropBool( SENDINFO(m_bActive) ), #ifdef MAPBASE -SendPropBool(SENDINFO(m_bDestroyImmediately)), + SendPropBool( SENDINFO(m_bDestroyImmediately) ), #endif -SendPropFloat(SENDINFO(m_flStartTime)), + SendPropFloat( SENDINFO(m_flStartTime) ), -SendPropArray3(SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle(SENDINFO_ARRAY(m_hControlPointEnts))), -SendPropArray3(SENDINFO_ARRAY3(m_vControlPointVecs), SendPropVector(SENDINFO_ARRAY(m_vControlPointVecs))), -SendPropArray3(SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt(SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED)), -SendPropBool(SENDINFO(m_bWeatherEffect)), + SendPropArray3( SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle( SENDINFO_ARRAY(m_hControlPointEnts) ) ), + SendPropArray3( SENDINFO_ARRAY3(m_vControlPointVecs), SendPropVector( SENDINFO_ARRAY(m_vControlPointVecs) ) ), + SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), + SendPropBool( SENDINFO(m_bWeatherEffect) ), END_SEND_TABLE() -BEGIN_DATADESC(CParticleSystem) -DEFINE_KEYFIELD(m_bStartActive, FIELD_BOOLEAN, "start_active"), -DEFINE_KEYFIELD(m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather"), -DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), +BEGIN_DATADESC( CParticleSystem ) + DEFINE_KEYFIELD( m_bStartActive, FIELD_BOOLEAN, "start_active" ), + DEFINE_KEYFIELD( m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather" ), + DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), #ifdef MAPBASE -DEFINE_FIELD(m_bDestroyImmediately, FIELD_BOOLEAN), + DEFINE_FIELD( m_bDestroyImmediately, FIELD_BOOLEAN ), #endif -DEFINE_FIELD(m_flStartTime, FIELD_TIME), -DEFINE_KEYFIELD(m_iszEffectName, FIELD_STRING, "effect_name"), -//DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. + DEFINE_FIELD( m_flStartTime, FIELD_TIME ), + DEFINE_KEYFIELD( m_iszEffectName, FIELD_STRING, "effect_name" ), + //DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. -DEFINE_KEYFIELD(m_iszControlPointNames[0], FIELD_STRING, "cpoint1"), -DEFINE_KEYFIELD(m_iszControlPointNames[1], FIELD_STRING, "cpoint2"), -DEFINE_KEYFIELD(m_iszControlPointNames[2], FIELD_STRING, "cpoint3"), -DEFINE_KEYFIELD(m_iszControlPointNames[3], FIELD_STRING, "cpoint4"), -DEFINE_KEYFIELD(m_iszControlPointNames[4], FIELD_STRING, "cpoint5"), -DEFINE_KEYFIELD(m_iszControlPointNames[5], FIELD_STRING, "cpoint6"), -DEFINE_KEYFIELD(m_iszControlPointNames[6], FIELD_STRING, "cpoint7"), -DEFINE_KEYFIELD(m_iszControlPointNames[7], FIELD_STRING, "cpoint8"), -DEFINE_KEYFIELD(m_iszControlPointNames[8], FIELD_STRING, "cpoint9"), -DEFINE_KEYFIELD(m_iszControlPointNames[9], FIELD_STRING, "cpoint10"), -DEFINE_KEYFIELD(m_iszControlPointNames[10], FIELD_STRING, "cpoint11"), -DEFINE_KEYFIELD(m_iszControlPointNames[11], FIELD_STRING, "cpoint12"), -DEFINE_KEYFIELD(m_iszControlPointNames[12], FIELD_STRING, "cpoint13"), -DEFINE_KEYFIELD(m_iszControlPointNames[13], FIELD_STRING, "cpoint14"), -DEFINE_KEYFIELD(m_iszControlPointNames[14], FIELD_STRING, "cpoint15"), -DEFINE_KEYFIELD(m_iszControlPointNames[15], FIELD_STRING, "cpoint16"), -DEFINE_KEYFIELD(m_iszControlPointNames[16], FIELD_STRING, "cpoint17"), -DEFINE_KEYFIELD(m_iszControlPointNames[17], FIELD_STRING, "cpoint18"), -DEFINE_KEYFIELD(m_iszControlPointNames[18], FIELD_STRING, "cpoint19"), -DEFINE_KEYFIELD(m_iszControlPointNames[19], FIELD_STRING, "cpoint20"), -DEFINE_KEYFIELD(m_iszControlPointNames[20], FIELD_STRING, "cpoint21"), -DEFINE_KEYFIELD(m_iszControlPointNames[21], FIELD_STRING, "cpoint22"), -DEFINE_KEYFIELD(m_iszControlPointNames[22], FIELD_STRING, "cpoint23"), -DEFINE_KEYFIELD(m_iszControlPointNames[23], FIELD_STRING, "cpoint24"), -DEFINE_KEYFIELD(m_iszControlPointNames[24], FIELD_STRING, "cpoint25"), -DEFINE_KEYFIELD(m_iszControlPointNames[25], FIELD_STRING, "cpoint26"), -DEFINE_KEYFIELD(m_iszControlPointNames[26], FIELD_STRING, "cpoint27"), -DEFINE_KEYFIELD(m_iszControlPointNames[27], FIELD_STRING, "cpoint28"), -DEFINE_KEYFIELD(m_iszControlPointNames[28], FIELD_STRING, "cpoint29"), -DEFINE_KEYFIELD(m_iszControlPointNames[29], FIELD_STRING, "cpoint30"), -DEFINE_KEYFIELD(m_iszControlPointNames[30], FIELD_STRING, "cpoint31"), -DEFINE_KEYFIELD(m_iszControlPointNames[31], FIELD_STRING, "cpoint32"), -DEFINE_KEYFIELD(m_iszControlPointNames[32], FIELD_STRING, "cpoint33"), -DEFINE_KEYFIELD(m_iszControlPointNames[33], FIELD_STRING, "cpoint34"), -DEFINE_KEYFIELD(m_iszControlPointNames[34], FIELD_STRING, "cpoint35"), -DEFINE_KEYFIELD(m_iszControlPointNames[35], FIELD_STRING, "cpoint36"), -DEFINE_KEYFIELD(m_iszControlPointNames[36], FIELD_STRING, "cpoint37"), -DEFINE_KEYFIELD(m_iszControlPointNames[37], FIELD_STRING, "cpoint38"), -DEFINE_KEYFIELD(m_iszControlPointNames[38], FIELD_STRING, "cpoint39"), -DEFINE_KEYFIELD(m_iszControlPointNames[39], FIELD_STRING, "cpoint40"), -DEFINE_KEYFIELD(m_iszControlPointNames[40], FIELD_STRING, "cpoint41"), -DEFINE_KEYFIELD(m_iszControlPointNames[41], FIELD_STRING, "cpoint42"), -DEFINE_KEYFIELD(m_iszControlPointNames[42], FIELD_STRING, "cpoint43"), -DEFINE_KEYFIELD(m_iszControlPointNames[43], FIELD_STRING, "cpoint44"), -DEFINE_KEYFIELD(m_iszControlPointNames[44], FIELD_STRING, "cpoint45"), -DEFINE_KEYFIELD(m_iszControlPointNames[45], FIELD_STRING, "cpoint46"), -DEFINE_KEYFIELD(m_iszControlPointNames[46], FIELD_STRING, "cpoint47"), -DEFINE_KEYFIELD(m_iszControlPointNames[47], FIELD_STRING, "cpoint48"), -DEFINE_KEYFIELD(m_iszControlPointNames[48], FIELD_STRING, "cpoint49"), -DEFINE_KEYFIELD(m_iszControlPointNames[49], FIELD_STRING, "cpoint50"), -DEFINE_KEYFIELD(m_iszControlPointNames[50], FIELD_STRING, "cpoint51"), -DEFINE_KEYFIELD(m_iszControlPointNames[51], FIELD_STRING, "cpoint52"), -DEFINE_KEYFIELD(m_iszControlPointNames[52], FIELD_STRING, "cpoint53"), -DEFINE_KEYFIELD(m_iszControlPointNames[53], FIELD_STRING, "cpoint54"), -DEFINE_KEYFIELD(m_iszControlPointNames[54], FIELD_STRING, "cpoint55"), -DEFINE_KEYFIELD(m_iszControlPointNames[55], FIELD_STRING, "cpoint56"), -DEFINE_KEYFIELD(m_iszControlPointNames[56], FIELD_STRING, "cpoint57"), -DEFINE_KEYFIELD(m_iszControlPointNames[57], FIELD_STRING, "cpoint58"), -DEFINE_KEYFIELD(m_iszControlPointNames[58], FIELD_STRING, "cpoint59"), -DEFINE_KEYFIELD(m_iszControlPointNames[59], FIELD_STRING, "cpoint60"), -DEFINE_KEYFIELD(m_iszControlPointNames[60], FIELD_STRING, "cpoint61"), -DEFINE_KEYFIELD(m_iszControlPointNames[61], FIELD_STRING, "cpoint62"), -DEFINE_KEYFIELD(m_iszControlPointNames[62], FIELD_STRING, "cpoint63"), + DEFINE_KEYFIELD( m_iszControlPointNames[0], FIELD_STRING, "cpoint1" ), + DEFINE_KEYFIELD( m_iszControlPointNames[1], FIELD_STRING, "cpoint2" ), + DEFINE_KEYFIELD( m_iszControlPointNames[2], FIELD_STRING, "cpoint3" ), + DEFINE_KEYFIELD( m_iszControlPointNames[3], FIELD_STRING, "cpoint4" ), + DEFINE_KEYFIELD( m_iszControlPointNames[4], FIELD_STRING, "cpoint5" ), + DEFINE_KEYFIELD( m_iszControlPointNames[5], FIELD_STRING, "cpoint6" ), + DEFINE_KEYFIELD( m_iszControlPointNames[6], FIELD_STRING, "cpoint7" ), + DEFINE_KEYFIELD( m_iszControlPointNames[7], FIELD_STRING, "cpoint8" ), + DEFINE_KEYFIELD( m_iszControlPointNames[8], FIELD_STRING, "cpoint9" ), + DEFINE_KEYFIELD( m_iszControlPointNames[9], FIELD_STRING, "cpoint10" ), + DEFINE_KEYFIELD( m_iszControlPointNames[10], FIELD_STRING, "cpoint11" ), + DEFINE_KEYFIELD( m_iszControlPointNames[11], FIELD_STRING, "cpoint12" ), + DEFINE_KEYFIELD( m_iszControlPointNames[12], FIELD_STRING, "cpoint13" ), + DEFINE_KEYFIELD( m_iszControlPointNames[13], FIELD_STRING, "cpoint14" ), + DEFINE_KEYFIELD( m_iszControlPointNames[14], FIELD_STRING, "cpoint15" ), + DEFINE_KEYFIELD( m_iszControlPointNames[15], FIELD_STRING, "cpoint16" ), + DEFINE_KEYFIELD( m_iszControlPointNames[16], FIELD_STRING, "cpoint17" ), + DEFINE_KEYFIELD( m_iszControlPointNames[17], FIELD_STRING, "cpoint18" ), + DEFINE_KEYFIELD( m_iszControlPointNames[18], FIELD_STRING, "cpoint19" ), + DEFINE_KEYFIELD( m_iszControlPointNames[19], FIELD_STRING, "cpoint20" ), + DEFINE_KEYFIELD( m_iszControlPointNames[20], FIELD_STRING, "cpoint21" ), + DEFINE_KEYFIELD( m_iszControlPointNames[21], FIELD_STRING, "cpoint22" ), + DEFINE_KEYFIELD( m_iszControlPointNames[22], FIELD_STRING, "cpoint23" ), + DEFINE_KEYFIELD( m_iszControlPointNames[23], FIELD_STRING, "cpoint24" ), + DEFINE_KEYFIELD( m_iszControlPointNames[24], FIELD_STRING, "cpoint25" ), + DEFINE_KEYFIELD( m_iszControlPointNames[25], FIELD_STRING, "cpoint26" ), + DEFINE_KEYFIELD( m_iszControlPointNames[26], FIELD_STRING, "cpoint27" ), + DEFINE_KEYFIELD( m_iszControlPointNames[27], FIELD_STRING, "cpoint28" ), + DEFINE_KEYFIELD( m_iszControlPointNames[28], FIELD_STRING, "cpoint29" ), + DEFINE_KEYFIELD( m_iszControlPointNames[29], FIELD_STRING, "cpoint30" ), + DEFINE_KEYFIELD( m_iszControlPointNames[30], FIELD_STRING, "cpoint31" ), + DEFINE_KEYFIELD( m_iszControlPointNames[31], FIELD_STRING, "cpoint32" ), + DEFINE_KEYFIELD( m_iszControlPointNames[32], FIELD_STRING, "cpoint33" ), + DEFINE_KEYFIELD( m_iszControlPointNames[33], FIELD_STRING, "cpoint34" ), + DEFINE_KEYFIELD( m_iszControlPointNames[34], FIELD_STRING, "cpoint35" ), + DEFINE_KEYFIELD( m_iszControlPointNames[35], FIELD_STRING, "cpoint36" ), + DEFINE_KEYFIELD( m_iszControlPointNames[36], FIELD_STRING, "cpoint37" ), + DEFINE_KEYFIELD( m_iszControlPointNames[37], FIELD_STRING, "cpoint38" ), + DEFINE_KEYFIELD( m_iszControlPointNames[38], FIELD_STRING, "cpoint39" ), + DEFINE_KEYFIELD( m_iszControlPointNames[39], FIELD_STRING, "cpoint40" ), + DEFINE_KEYFIELD( m_iszControlPointNames[40], FIELD_STRING, "cpoint41" ), + DEFINE_KEYFIELD( m_iszControlPointNames[41], FIELD_STRING, "cpoint42" ), + DEFINE_KEYFIELD( m_iszControlPointNames[42], FIELD_STRING, "cpoint43" ), + DEFINE_KEYFIELD( m_iszControlPointNames[43], FIELD_STRING, "cpoint44" ), + DEFINE_KEYFIELD( m_iszControlPointNames[44], FIELD_STRING, "cpoint45" ), + DEFINE_KEYFIELD( m_iszControlPointNames[45], FIELD_STRING, "cpoint46" ), + DEFINE_KEYFIELD( m_iszControlPointNames[46], FIELD_STRING, "cpoint47" ), + DEFINE_KEYFIELD( m_iszControlPointNames[47], FIELD_STRING, "cpoint48" ), + DEFINE_KEYFIELD( m_iszControlPointNames[48], FIELD_STRING, "cpoint49" ), + DEFINE_KEYFIELD( m_iszControlPointNames[49], FIELD_STRING, "cpoint50" ), + DEFINE_KEYFIELD( m_iszControlPointNames[50], FIELD_STRING, "cpoint51" ), + DEFINE_KEYFIELD( m_iszControlPointNames[51], FIELD_STRING, "cpoint52" ), + DEFINE_KEYFIELD( m_iszControlPointNames[52], FIELD_STRING, "cpoint53" ), + DEFINE_KEYFIELD( m_iszControlPointNames[53], FIELD_STRING, "cpoint54" ), + DEFINE_KEYFIELD( m_iszControlPointNames[54], FIELD_STRING, "cpoint55" ), + DEFINE_KEYFIELD( m_iszControlPointNames[55], FIELD_STRING, "cpoint56" ), + DEFINE_KEYFIELD( m_iszControlPointNames[56], FIELD_STRING, "cpoint57" ), + DEFINE_KEYFIELD( m_iszControlPointNames[57], FIELD_STRING, "cpoint58" ), + DEFINE_KEYFIELD( m_iszControlPointNames[58], FIELD_STRING, "cpoint59" ), + DEFINE_KEYFIELD( m_iszControlPointNames[59], FIELD_STRING, "cpoint60" ), + DEFINE_KEYFIELD( m_iszControlPointNames[60], FIELD_STRING, "cpoint61" ), + DEFINE_KEYFIELD( m_iszControlPointNames[61], FIELD_STRING, "cpoint62" ), + DEFINE_KEYFIELD( m_iszControlPointNames[62], FIELD_STRING, "cpoint63" ), -DEFINE_KEYFIELD(m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent"), -DEFINE_KEYFIELD(m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent"), -DEFINE_KEYFIELD(m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent"), -DEFINE_KEYFIELD(m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent"), -DEFINE_KEYFIELD(m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent"), -DEFINE_KEYFIELD(m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent"), -DEFINE_KEYFIELD(m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent"), + DEFINE_KEYFIELD( m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent" ), + DEFINE_KEYFIELD( m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent" ), + DEFINE_KEYFIELD( m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent" ), + DEFINE_KEYFIELD( m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent" ), + DEFINE_KEYFIELD( m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent" ), + DEFINE_KEYFIELD( m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent" ), + DEFINE_KEYFIELD( m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent" ), + + DEFINE_AUTO_ARRAY( m_hControlPointEnts, FIELD_EHANDLE ), -DEFINE_AUTO_ARRAY(m_hControlPointEnts, FIELD_EHANDLE), -DEFINE_AUTO_ARRAY(m_vControlPointVecs, FIELD_VECTOR), - -DEFINE_INPUTFUNC(FIELD_VOID, "Start", InputStart), -DEFINE_INPUTFUNC(FIELD_VOID, "Stop", InputStop), + DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), + DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), #ifdef MAPBASE -DEFINE_INPUTFUNC(FIELD_VOID, "DestroyImmediately", InputDestroyImmediately), + DEFINE_INPUTFUNC( FIELD_VOID, "DestroyImmediately", InputDestroyImmediately ), #endif -DEFINE_THINKFUNC(StartParticleSystemThink), + DEFINE_THINKFUNC( StartParticleSystemThink ), END_DATADESC() -LINK_ENTITY_TO_CLASS(info_particle_system, CParticleSystem); -LINK_ENTITY_TO_CLASS(info_particle_system_coordinate, CParticleSystemCoordinate); +LINK_ENTITY_TO_CLASS( info_particle_system, CParticleSystem ); +LINK_ENTITY_TO_CLASS( info_particle_system_coordinate, CParticleSystemCoordinate ); //----------------------------------------------------------------------------- // Purpose: @@ -146,22 +145,22 @@ CParticleSystem::CParticleSystem() //----------------------------------------------------------------------------- // Precache //----------------------------------------------------------------------------- -void CParticleSystem::Precache(void) +void CParticleSystem::Precache( void ) { - const char *pParticleSystemName = STRING(m_iszEffectName); - if (pParticleSystemName == NULL || pParticleSystemName[0] == '\0') + const char *pParticleSystemName = STRING( m_iszEffectName ); + if ( pParticleSystemName == NULL || pParticleSystemName[0] == '\0' ) { - Warning("info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr()); + Warning( "info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr() ); } - PrecacheParticleSystem(pParticleSystemName); + PrecacheParticleSystem( pParticleSystemName ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::Spawn(void) +void CParticleSystem::Spawn( void ) { BaseClass::Spawn(); @@ -172,14 +171,14 @@ void CParticleSystem::Spawn(void) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::Activate(void) +void CParticleSystem::Activate( void ) { BaseClass::Activate(); // Find our particle effect index - m_iEffectIndex = GetParticleSystemIndex(STRING(m_iszEffectName)); + m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) ); - if (m_bStartActive) + if ( m_bStartActive ) { m_bStartActive = false; StartParticleSystem(); @@ -189,7 +188,7 @@ void CParticleSystem::Activate(void) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystemThink(void) +void CParticleSystem::StartParticleSystemThink( void ) { StartParticleSystem(); } @@ -199,22 +198,22 @@ void CParticleSystem::StartParticleSystemThink(void) //----------------------------------------------------------------------------- int CParticleSystem::UpdateTransmitState() { - return SetTransmitState(FL_EDICT_ALWAYS); + return SetTransmitState( FL_EDICT_ALWAYS ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystem(void) +void CParticleSystem::StartParticleSystem( void ) { - if (m_bActive == false) + if ( m_bActive == false ) { m_flStartTime = gpGlobals->curtime; m_bActive = true; #ifdef MAPBASE m_bDestroyImmediately = false; #endif - + // Setup our control points at this time (in case our targets weren't around at spawn time) ReadControlPointEnts(); } @@ -223,7 +222,7 @@ void CParticleSystem::StartParticleSystem(void) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StopParticleSystem(void) +void CParticleSystem::StopParticleSystem( void ) { m_bActive = false; } @@ -231,7 +230,7 @@ void CParticleSystem::StopParticleSystem(void) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputStart(inputdata_t &inputdata) +void CParticleSystem::InputStart( inputdata_t &inputdata ) { StartParticleSystem(); } @@ -239,7 +238,7 @@ void CParticleSystem::InputStart(inputdata_t &inputdata) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputStop(inputdata_t &inputdata) +void CParticleSystem::InputStop( inputdata_t &inputdata ) { StopParticleSystem(); } @@ -248,7 +247,7 @@ void CParticleSystem::InputStop(inputdata_t &inputdata) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputDestroyImmediately(inputdata_t &inputdata) +void CParticleSystem::InputDestroyImmediately( inputdata_t &inputdata ) { m_bDestroyImmediately = true; StopParticleSystem(); @@ -257,31 +256,34 @@ void CParticleSystem::InputDestroyImmediately(inputdata_t &inputdata) //----------------------------------------------------------------------------- // Purpose: Find each entity referred to by m_iszControlPointNames and -// resolve it into the corresponding slot in m_vControlPointVecs +// resolve it into the corresponding slot in m_hControlPointEnts //----------------------------------------------------------------------------- -void CParticleSystem::ReadControlPointEnts(void) +void CParticleSystem::ReadControlPointEnts( void ) { - for (int i = 0; i < kMAXCONTROLPOINTS; ++i) + for ( int i = 0 ; i < kMAXCONTROLPOINTS; ++i ) { - if (UsesCoordinates()) { + if (UsesCoordinates()) + { Vector vecCoords; // cast str to vector, add vector to array const char* pszVector = STRING(m_iszControlPointNames[i]); UTIL_StringToVector(vecCoords.Base(), pszVector); m_vControlPointVecs.Set(i, vecCoords); } - else{ - if (m_iszControlPointNames[i] == NULL_STRING) + else + { + if ( m_iszControlPointNames[i] == NULL_STRING ) continue; - CBaseEntity *pPointEnt = gEntList.FindEntityGeneric(NULL, STRING(m_iszControlPointNames[i]), this); - Assert(pPointEnt != NULL); - if (pPointEnt == NULL) + + CBaseEntity *pPointEnt = gEntList.FindEntityGeneric( NULL, STRING( m_iszControlPointNames[i] ), this ); + Assert( pPointEnt != NULL ); + if ( pPointEnt == NULL ) { - Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr()); + Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr() ); continue; } - m_hControlPointEnts.Set(i, pPointEnt); + m_hControlPointEnts.Set( i, pPointEnt ); } } } diff --git a/sp/src/game/server/particle_system.h b/sp/src/game/server/particle_system.h index d9ed3fe6..42e213f5 100644 --- a/sp/src/game/server/particle_system.h +++ b/sp/src/game/server/particle_system.h @@ -17,52 +17,52 @@ //----------------------------------------------------------------------------- class CParticleSystem : public CBaseEntity { - DECLARE_CLASS(CParticleSystem, CBaseEntity); + DECLARE_CLASS( CParticleSystem, CBaseEntity ); public: DECLARE_SERVERCLASS(); DECLARE_DATADESC(); CParticleSystem(); - virtual void Precache(void); - virtual void Spawn(void); - virtual void Activate(void); + virtual void Precache( void ); + virtual void Spawn( void ); + virtual void Activate( void ); virtual int UpdateTransmitState(void); - void StartParticleSystem(void); - void StopParticleSystem(void); + void StartParticleSystem( void ); + void StopParticleSystem( void ); - void InputStart(inputdata_t &inputdata); - void InputStop(inputdata_t &inputdata); + void InputStart( inputdata_t &inputdata ); + void InputStop( inputdata_t &inputdata ); #ifdef MAPBASE - void InputDestroyImmediately(inputdata_t &inputdata); + void InputDestroyImmediately( inputdata_t &inputdata ); #endif - void StartParticleSystemThink(void); + void StartParticleSystemThink( void ); enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me - virtual bool UsesCoordinates(void) { return false; } + virtual bool UsesCoordinates( void ) { return false; } protected: /// Load up and resolve the entities that are supposed to be the control points - virtual void ReadControlPointEnts(void); + void ReadControlPointEnts( void ); bool m_bStartActive; string_t m_iszEffectName; - - CNetworkVar(bool, m_bActive); + + CNetworkVar( bool, m_bActive ); #ifdef MAPBASE - CNetworkVar(bool, m_bDestroyImmediately); + CNetworkVar( bool, m_bDestroyImmediately ); #endif - CNetworkVar(int, m_iEffectIndex) - CNetworkVar(float, m_flStartTime); // Time at which this effect was started. This is used after restoring an active effect. + CNetworkVar( int, m_iEffectIndex ) + CNetworkVar( float, m_flStartTime ); // Time at which this effect was started. This is used after restoring an active effect. string_t m_iszControlPointNames[kMAXCONTROLPOINTS]; - CNetworkArray(EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS); - CNetworkArray(Vector, m_vControlPointVecs, kMAXCONTROLPOINTS); - CNetworkArray(unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS); - CNetworkVar(bool, m_bWeatherEffect); + CNetworkArray( EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS ); + CNetworkArray( Vector, m_vControlPointVecs, kMAXCONTROLPOINTS ); + CNetworkArray( unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS ); + CNetworkVar( bool, m_bWeatherEffect ); }; //----------------------------------------------------------------------------- @@ -70,9 +70,9 @@ protected: //----------------------------------------------------------------------------- class CParticleSystemCoordinate : public CParticleSystem { - DECLARE_CLASS(CParticleSystemCoordinate, CParticleSystem); + DECLARE_CLASS( CParticleSystemCoordinate, CParticleSystem ); public: - virtual bool UsesCoordinates(void) { return true; } + virtual bool UsesCoordinates( void ) { return true; } }; #endif // PARTICLE_SYSTEM_H From fd4133485abc771ab36236c9d563926cd735fc3b Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 13:38:28 -0500 Subject: [PATCH 33/65] Fix uninitialized variable in math_clamp --- sp/src/game/server/logicentities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp/src/game/server/logicentities.cpp b/sp/src/game/server/logicentities.cpp index 2197baff..aa838a35 100644 --- a/sp/src/game/server/logicentities.cpp +++ b/sp/src/game/server/logicentities.cpp @@ -4385,7 +4385,7 @@ void CMathClamp::ClampValue(variant_t var, inputdata_t *inputdata) { // Don't convert up here in case of invalid type - int nBounds; + int nBounds = 0; switch (var.FieldType()) { From 8d25fb72b1ec9d4a657509a7d5e46e0511f6c39c Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 13:39:43 -0500 Subject: [PATCH 34/65] Updated README --- README | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/README b/README index 47b56b08..924ffc67 100644 --- a/README +++ b/README @@ -1,10 +1,24 @@ -//=================================================================================================================================================== +//========================================================================================================================= - Mapbase v7.1 - Source 2013 - https://github.com/mapbase-source/source-sdk-2013 - https://www.moddb.com/mods/mapbase +

+ +

+

+ + + + +

+

+ + + + + + +

-//=================================================================================================================================================== +//========================================================================================================================= This repository contains code from Mapbase, a modification of the Source 2013 SDK which serves as a combined package of general-purpose improvements, fixes, and utility features for mods. @@ -23,7 +37,7 @@ Mapbase's main content in this repository may include: For more information, view this page: https://github.com/mapbase-source/source-sdk-2013/wiki/Introduction-to-Mapbase -//=================================================================================================================================================== +//========================================================================================================================= Mapbase is an open-source project and its contents can be distributed and used at the discretion of its users. However, this project contains content from a vast number of different sources which have their own licensing or attribution requirements. We try to handle most of that ourselves, but users who plan on @@ -32,7 +46,7 @@ distributing Mapbase content are expected to comply with certain rules. Up-to-date information about Mapbase content usage and credit are addressed in this article on Mapbase's wiki: https://github.com/mapbase-source/source-sdk-2013/wiki/Using-Mapbase-Content -//=================================================================================================================================================== +//========================================================================================================================= >>>>>>>> EXTERNAL CONTENT USED IN MAPBASE <<<<<<<< @@ -69,7 +83,7 @@ including radial fog, rope code, and treesway) - https://github.com/entropy-zero/source-sdk-2013 (skill_changed game event) - https://github.com/Nbc66/source-sdk-2013-ce/tree/v142 (Base for VS2019 toolset support) -//--------------------------------------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------------- Valve Developer Community (VDC) sources: @@ -97,7 +111,7 @@ interchangeable arms; this may change in the future) - https://developer.valvesoftware.com/wiki/Func_clip_vphysics ("Start Disabled" keyvalue fix) - https://developer.valvesoftware.com/wiki/Importing_CSS_Weapons_Into_HL2 (CS:S viewmodel chirality) -//--------------------------------------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------------- Direct contributions: @@ -130,6 +144,7 @@ Direct contributions: =-- https://github.com/mapbase-source/source-sdk-2013/pull/148 (Minor fixup) =-- https://github.com/mapbase-source/source-sdk-2013/pull/167 (Security fixes) =-- https://github.com/mapbase-source/source-sdk-2013/pull/168 (Squirrel update) +=-- https://github.com/mapbase-source/source-sdk-2013/pull/169 (VScript VGUI) =-- https://github.com/mapbase-source/source-sdk-2013/pull/171 (VScript documentation sorting) =-- https://github.com/mapbase-source/source-sdk-2013/pull/173 (VScript fixes and optimizations) =-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes) @@ -154,7 +169,7 @@ Direct contributions: =-- https://github.com/mapbase-source/source-sdk-2013/pull/185 (Fix enemyfinders becoming visible when they wake) =-- https://github.com/mapbase-source/source-sdk-2013/pull/186 (Fix for brightly glowing teeth) -//--------------------------------------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------------- Other sources: @@ -172,11 +187,11 @@ Other sources: - Vortigaunt LOS fix originally created by dky.tehkingd.u for HL2:CE - https://combineoverwiki.net/wiki/File:Combine_main_symbol.svg ("icon_combine" instructor icon in "materials/vgui/hud/gameinstructor_hl2_1"; This is asset-based and not reflected in the code) -//--------------------------------------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------------- If there is anything missing from this list, please contact Blixibon. -//=================================================================================================================================================== +//========================================================================================================================= Aside from the content list above, Mapbase has more descriptive and up-to-date credits on this wiki article: https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits @@ -185,11 +200,11 @@ Other relevant articles: * https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Disclaimers * https://github.com/mapbase-source/source-sdk-2013/wiki/Frequently-Asked-Questions-(FAQ) -//--------------------------------------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------------- In memory of Holly Liberatore (moofemp) -//=================================================================================================================================================== +//========================================================================================================================= Please see the Source SDK 2013 license below: From 15f321d4e9d6d18f510327721a59aaecd158173b Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 13:44:39 -0500 Subject: [PATCH 35/65] Updated README --- README | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/README b/README index 924ffc67..6bae76ac 100644 --- a/README +++ b/README @@ -1,22 +1,8 @@ //========================================================================================================================= -

- -

-

- - - - -

-

- - - - - - -

+ Mapbase v7.1 - Source 2013 + https://github.com/mapbase-source/source-sdk-2013 + https://www.moddb.com/mods/mapbase //========================================================================================================================= From 5cc53c10eefe75685bfc73c2f03c67c96e7dfcd1 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 22:09:32 -0500 Subject: [PATCH 36/65] Fix Combine dropships not dropping APCs correctly after save/load --- sp/src/game/server/hl2/npc_combinedropship.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sp/src/game/server/hl2/npc_combinedropship.cpp b/sp/src/game/server/hl2/npc_combinedropship.cpp index b39dad9f..bc6067f2 100644 --- a/sp/src/game/server/hl2/npc_combinedropship.cpp +++ b/sp/src/game/server/hl2/npc_combinedropship.cpp @@ -999,7 +999,11 @@ void CNPC_CombineDropship::Spawn( void ) IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); if ( pPhysicsObject ) { +#ifdef MAPBASE + pPhysicsObject->SetShadow( 1e4, 1e4, true, true ); // (allowing physics movement and rotation) +#else pPhysicsObject->SetShadow( 1e4, 1e4, false, false ); +#endif } m_hContainer->SetParent(this, 0); From a7c90b042d721781813455e43755f3f86868e7e9 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 23:01:50 -0500 Subject: [PATCH 37/65] Fix hand viewmodel issues on death/respawn --- sp/src/game/server/player.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sp/src/game/server/player.cpp b/sp/src/game/server/player.cpp index c53cb6ad..a68bf982 100644 --- a/sp/src/game/server/player.cpp +++ b/sp/src/game/server/player.cpp @@ -645,8 +645,14 @@ void CBasePlayer::CreateHandModel(int index, int iOtherVm) { Assert(index >= 0 && index < MAX_VIEWMODELS && iOtherVm >= 0 && iOtherVm < MAX_VIEWMODELS ); - if (GetViewModel(index)) + if (GetViewModel( index )) + { + // This can happen if the player respawns + // Don't draw unless we're already using a hands weapon + if ( !GetActiveWeapon() || !GetActiveWeapon()->UsesHands() ) + GetViewModel( index )->AddEffects( EF_NODRAW ); return; + } CBaseViewModel *vm = (CBaseViewModel *)CreateEntityByName("hand_viewmodel"); if (vm) @@ -1719,6 +1725,15 @@ void CBasePlayer::RemoveAllItems( bool removeSuit ) RemoveAllWeapons(); RemoveAllAmmo(); +#ifdef MAPBASE + // Hide hand viewmodel + CBaseViewModel *vm = GetViewModel( 1 ); + if ( vm ) + { + vm->AddEffects( EF_NODRAW ); + } +#endif + if ( removeSuit ) { RemoveSuit(); From 9b3977e30d00e8a81866787af84fd319b174f9d2 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 23:02:46 -0500 Subject: [PATCH 38/65] Fix crash with player use animations --- sp/src/game/server/hl2/hl2_player.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sp/src/game/server/hl2/hl2_player.cpp b/sp/src/game/server/hl2/hl2_player.cpp index 6720ff10..1cd610bb 100644 --- a/sp/src/game/server/hl2/hl2_player.cpp +++ b/sp/src/game/server/hl2/hl2_player.cpp @@ -1393,7 +1393,8 @@ Activity CHL2_Player::Weapon_TranslateActivity( Activity baseAct, bool *pRequire #if EXPANDED_HL2DM_ACTIVITIES // +USE activities - if ( m_hUseEntity && player_use_anim_enabled.GetBool() ) + // HACKHACK: Make sure m_hUseEntity is a pickup controller first + if ( m_hUseEntity && m_hUseEntity->ClassMatches("player_pickup") && player_use_anim_enabled.GetBool()) { CBaseEntity* pHeldEnt = GetPlayerHeldEntity( this ); float flMass = pHeldEnt ? From 74faeaeb04024a1c1c9f9463f47e2d8707f2fbd6 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 23:05:28 -0500 Subject: [PATCH 39/65] Added GetCurrentBetaName and IsAppInstalled to VScript Steam API --- .../shared/mapbase/vscript_singletons.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 3ed85eb3..2732c801 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -3240,6 +3240,31 @@ public: return ret; } + const char *GetCurrentBetaName() + { + if ( !steamapicontext || !steamapicontext->SteamApps() ) + return NULL; + + static char ret[16]; + steamapicontext->SteamApps()->GetCurrentBetaName( ret, sizeof( ret ) ); + return ret; + } +#if 0 + bool IsSubscribedApp( int nAppID ) + { + if ( !steamapicontext || !steamapicontext->SteamApps() ) + return false; + + return steamapicontext->SteamApps()->BIsSubscribedApp( nAppID ); + } +#endif + bool IsAppInstalled( int nAppID ) + { + if ( !steamapicontext || !steamapicontext->SteamApps() ) + return false; + + return steamapicontext->SteamApps()->BIsAppInstalled( nAppID ); + } } g_ScriptSteamAPI; @@ -3250,6 +3275,9 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptSteamAPI, "CSteamAPI", SCRIPT_SINGLETON "" ) DEFINE_SCRIPTFUNC( GetCurrentBatteryPower, "Return the amount of battery power left in the current system in % [0..100], 255 for being on AC power" ) //DEFINE_SCRIPTFUNC( GetIPCountry, "Returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database)" ) DEFINE_SCRIPTFUNC( GetCurrentGameLanguage, "Gets the current language that the user has set as API language code. This falls back to the Steam UI language if the user hasn't explicitly picked a language for the title." ) + DEFINE_SCRIPTFUNC( GetCurrentBetaName, "Gets the name of the user's current beta branch. In Source SDK Base 2013 Singleplayer, this will usually return 'upcoming'." ) + //DEFINE_SCRIPTFUNC( IsSubscribedApp, "Returns true if the user is subscribed to the specified app ID." ) + DEFINE_SCRIPTFUNC( IsAppInstalled, "Returns true if the user has the specified app ID installed on their computer." ) END_SCRIPTDESC(); #endif // !NO_STEAM From 0aca548e1575292a8fd7195a932597747b4c4087 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 23:05:59 -0500 Subject: [PATCH 40/65] Updated CONTRIBUTING.md --- .github/CONTRIBUTING.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 07391b88..4c9b35dc 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -35,6 +35,9 @@ All contributions must follow the following rules: * Code contributions are not obliged to follow Mapbase's preprocessor conventions (e.g. #ifdef MAPBASE), although following them is usually acceptable. + * Code contributions which modify or add onto existing code should generally match its syntax and shouldn't + change the spacing unless necessary. + * If you are contributing a file you created yourself specifically for Mapbase, you are required to use the custom "Mapbase - Source 2013" header used in other Mapbase files as of Mapbase v5.0. You are encouraged to append an "Author(s)" part to that header in your file in order to clarify who wrote it. @@ -51,8 +54,8 @@ contributions to make sure they compile properly. The code is compiled separatel and on both Debug and Release configurations. If these workflows fail, don't freak out! Accidents can happen frequently due to compiler syntax differences and conflicts -from other contributions. You can look at a failed workflow's log by clicking "Details", which will include the build's output. -Any errors must be resolved by you and/or by code reviewers before a pull request can be merged. +from other contributions. You can look at a failed workflow's log by clicking "Details", which will include the build's output +in the "Build" step(s). Any errors must be resolved by you and/or by code reviewers before a pull request can be merged. If your contribution is accepted, you may be listed in Mapbase's credits and the README's external content list: https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits#Contributors From 0b70acff089fd34a8ec403f4a719728c99bf219f Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 26 Oct 2022 23:14:16 -0500 Subject: [PATCH 41/65] Added mapbase_build-master.yml workflow --- .github/workflows/mapbase_build-master.yml | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/mapbase_build-master.yml diff --git a/.github/workflows/mapbase_build-master.yml b/.github/workflows/mapbase_build-master.yml new file mode 100644 index 00000000..ccbab0a6 --- /dev/null +++ b/.github/workflows/mapbase_build-master.yml @@ -0,0 +1,32 @@ +# +# MAPBASE SOURCE 2013 CI +# +# Builds all projects when a pull request to the master branch is opened. +# If you're using a fork of Mapbase, feel free to configure this to meet your repository's needs. +# +# The "mapbase_build-sp" set of workflows can build specific projects depending on what files are changed. +# They are designed around a "develop" branch, but can be configured to target "master" and replace this +# instead (or target a similar branch with a different name) +# +# See mapbase_build-base.yml for more information on how this works. + +name: Build All Projects #(SP Release) + +on: + pull_request: + branches: + - master + +jobs: + games: + strategy: + matrix: + configuration: [Release, Debug] + uses: ./.github/workflows/mapbase_build-base.yml + with: + configuration: ${{ matrix.configuration }} + branch: 'sp' + game: 'episodic' # Change this if your mod is not using HL2/Episodic game projects + project-group: 'all' + solution-name: 'everything' + build-on-linux: true # Disable this if you don't want to compile for Linux From 221430169474703005ed062ade4872f49cc6a93a Mon Sep 17 00:00:00 2001 From: Blixibon Date: Thu, 27 Oct 2022 01:26:32 -0500 Subject: [PATCH 42/65] Updated mapbase_build-base.yml --- .github/workflows/mapbase_build-base.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mapbase_build-base.yml b/.github/workflows/mapbase_build-base.yml index b5542f6e..0eca4ee0 100644 --- a/.github/workflows/mapbase_build-base.yml +++ b/.github/workflows/mapbase_build-base.yml @@ -142,7 +142,7 @@ jobs: # -------------------------------------------------------------------- - name: Publish Windows game DLLs - if: inputs.project-group == 'all' || inputs.project-group == 'game' + if: inputs.project-group == 'game' uses: actions/upload-artifact@v3 with: name: 'Windows Game DLLs (server & client.dll) [${{ inputs.configuration }}]' @@ -254,12 +254,16 @@ jobs: # ${{inputs.branch}}/game/bin/vrad_dll.so # if-no-files-found: error + # For now, don't publish the .dbg files even though we publish .pdb files on Windows + # (they're too big) - name: Publish everything (Linux) if: inputs.project-group == 'all' uses: actions/upload-artifact@v3 with: name: 'Everything (Linux) [${{ inputs.configuration }}]' path: | - ${{inputs.branch}}/game/bin - ${{inputs.branch}}/game/mod_*/bin + ${{inputs.branch}}/game/bin/*.so + !${{inputs.branch}}/game/bin/*_srv.so + ${{inputs.branch}}/game/mod_*/bin/*.so + !${{inputs.branch}}/game/mod_*/bin/*_srv.so if-no-files-found: error From 6ceb808f93694328d053c8dc03e82bb1fe7c408a Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 30 Oct 2022 13:30:02 -0500 Subject: [PATCH 43/65] Added more convenient way to hide HUD elements from clientside VScript --- sp/src/game/client/hud.cpp | 13 +++++++ sp/src/game/client/mapbase/vscript_vgui.cpp | 35 +++++++++++++++++++ .../shared/mapbase/vscript_consts_shared.cpp | 19 ++++++++++ 3 files changed, 67 insertions(+) diff --git a/sp/src/game/client/hud.cpp b/sp/src/game/client/hud.cpp index a7d77a32..11aab40c 100644 --- a/sp/src/game/client/hud.cpp +++ b/sp/src/game/client/hud.cpp @@ -947,6 +947,11 @@ float CHud::GetFOVSensitivityAdjust() { return m_flFOVSensitivityAdjust; } + +#ifdef MAPBASE_VSCRIPT +extern int g_iVScriptHideHUD; +#endif + //----------------------------------------------------------------------------- // Purpose: Return true if the passed in sections of the HUD shouldn't be drawn //----------------------------------------------------------------------------- @@ -968,6 +973,14 @@ bool CHud::IsHidden( int iHudFlags ) iHideHud = hidehud.GetInt(); } +#ifdef MAPBASE_VSCRIPT + // Hide elements hidden by scripts + if ( g_iVScriptHideHUD ) + { + iHideHud |= g_iVScriptHideHUD; + } +#endif + // Everything hidden? if ( iHideHud & HIDEHUD_ALL ) return true; diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp index 61354093..27e9eb53 100644 --- a/sp/src/game/client/mapbase/vscript_vgui.cpp +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -143,6 +143,10 @@ CUtlVector< int > g_ScriptTextureIDs; CUtlLinkedList< IScriptVGUIObject*, unsigned short > g_ScriptPanels; +// Used in hud.cpp to help scripts hide HUD elements +int g_iVScriptHideHUD = 0; + + // Boundary is not checked in Surface, keep count manually to sanitise user input. static int g_nFontCount = 0; @@ -3403,6 +3407,9 @@ void CScriptVGUI::LevelShutdownPostEntity() surface()->DestroyTextureID( g_ScriptTextureIDs[i] ); } g_ScriptTextureIDs.Purge(); + + // Reset HUD hidden bits + g_iVScriptHideHUD = 0; } void CScriptVGUI::Shutdown() @@ -3690,6 +3697,29 @@ vgui::HFont GetScriptFont( const char *name, bool proportional ) return script_surface.GetFont( name, proportional, NULL ); } +//----------------------------------------------------------------------------- +// Control which HUD elements on the screen are hidden. +//----------------------------------------------------------------------------- +static int ScriptGetHUDHiddenBits() +{ + return g_iVScriptHideHUD; +} + +static void ScriptSetHUDHiddenBits( int iBits ) +{ + g_iVScriptHideHUD = iBits; +} + +static void ScriptAddHUDHiddenBits( int iBits ) +{ + g_iVScriptHideHUD |= iBits; +} + +static void ScriptClearHUDHiddenBits( int iBits ) +{ + g_iVScriptHideHUD &= ~(iBits); +} + void RegisterScriptVGUI() { @@ -3702,6 +3732,11 @@ void RegisterScriptVGUI() ScriptRegisterFunction( g_pScriptVM, ScreenToRay, "Get a ray from screen pixel position to world space." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get world position normalised in screen space. Return true if on screen." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptGetHUDHiddenBits, "GetHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptSetHUDHiddenBits, "SetHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptAddHUDHiddenBits, "AddHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptClearHUDHiddenBits, "ClearHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); + g_pScriptVM->Run( g_Script_vgui_init ); g_pScriptVM->RegisterInstance( &script_surface, "surface" ); diff --git a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp index 2ced7086..f9b9d233 100644 --- a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp +++ b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp @@ -604,6 +604,25 @@ void RegisterSharedScriptConstants() ScriptRegisterConstant( g_pScriptVM, D_NU, "Denotes a 'Neutral' relationship. Used by NPCs and players for relationship disposition." ); #endif +#ifdef CLIENT_DLL + // + // HUD + // + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_WEAPONSELECTION, "Hide ammo count & weapon selection" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_FLASHLIGHT, "" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_ALL, "" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_HEALTH, "Hide health & armor / suit battery" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_PLAYERDEAD, "Hide when local player's dead" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_NEEDSUIT, "Hide when the local player doesn't have the HEV suit" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_MISCSTATUS, "Hide miscellaneous status elements (trains, pickup history, death notices, etc)" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_CHAT, "Hide all communication elements (saytext, voice icon, etc)" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_CROSSHAIR, "Hide crosshairs" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_VEHICLE_CROSSHAIR, "Hide vehicle crosshair" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_INVEHICLE, "" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_BONUS_PROGRESS, "Hide bonus progress display (for bonus map challenges)" ); + ScriptRegisterConstant( g_pScriptVM, HIDEHUD_BITCOUNT, "" ); +#endif + // // Misc. General // From db6305fceeb0891e5ded55654a37e01d5af39374 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 30 Oct 2022 13:31:52 -0500 Subject: [PATCH 44/65] Removed prototype "addon manifest" implementation added in v7.0 (superceded by mapspawn_addon and near-unusable for Steam Workshop) --- sp/src/game/shared/mapbase/mapbase_shared.cpp | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index 43790ca5..79c4f51e 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -35,7 +35,6 @@ #include "tier0/memdbgon.h" #define GENERIC_MANIFEST_FILE "scripts/mapbase_default_manifest.txt" -#define GENERIC_MANIFEST_FILE_ADDON "scripts/mapbase_default_manifest_addon.txt" #ifdef CLIENT_DLL #define AUTOLOADED_MANIFEST_FILE VarArgs("maps/%s_manifest.txt", g_MapName) @@ -53,8 +52,6 @@ ConVar mapbase_load_default_manifest("mapbase_load_default_manifest", "1", FCVAR // This constant should change with each Mapbase update ConVar mapbase_version( "mapbase_version", MAPBASE_VERSION, FCVAR_NONE, "The version of Mapbase currently being used in this mod's server.dll" ); -ConVar mapbase_load_addon_manifest( "mapbase_load_addon_manifest", "0", FCVAR_NONE, "Allows manifests from \"addon\" path IDs to be loaded." ); - ConVar mapbase_flush_talker("mapbase_flush_talker", "1", FCVAR_NONE, "Normally, when a map with custom talker files is unloaded, the response system resets to rid itself of the custom file(s). Turn this convar off to prevent that from happening."); extern void MapbaseGameLog_Init(); @@ -70,8 +67,6 @@ static bool g_bMapContainsCustomTalker; // This constant should change with each Mapbase update ConVar mapbase_version_client( "mapbase_version_client", MAPBASE_VERSION, FCVAR_NONE, "The version of Mapbase currently being used in this mod's client.dll" ); -ConVar mapbase_load_addon_manifest( "mapbase_load_addon_manifest_client", "0", FCVAR_NONE, "Allows manifests from \"addon\" path IDs to be loaded on the client." ); - // This is from the vgui_controls library extern vgui::HScheme g_iCustomClientSchemeOverride; @@ -276,37 +271,6 @@ public: ParseGenericManifest(); } - // Load addon manifests if we should - if (mapbase_load_addon_manifest.GetBool()) - { - char searchPaths[4096]; - filesystem->GetSearchPath( "ADDON", true, searchPaths, sizeof( searchPaths ) ); - - for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) ) - { - char pathName[MAX_PATH]; - V_StripTrailingSlash( path ); - V_FileBase( path, pathName, sizeof( pathName ) ); - - KeyValues *pKV = new KeyValues( "DefaultAddonManifest" ); - - char manifestName[MAX_PATH]; - V_snprintf( manifestName, sizeof( manifestName ), "%s_mapbase_manifest.txt", pathName ); - if (filesystem->FileExists( manifestName, "ADDON" )) - { - if (pKV->LoadFromFile( filesystem, manifestName )) - AddManifestFile( pKV, pathName, false ); - } - else - { - if (pKV->LoadFromFile( filesystem, GENERIC_MANIFEST_FILE_ADDON )) - AddManifestFile( pKV, pathName, true ); - } - - pKV->deleteThis(); - } - } - #ifdef GAME_DLL MapbaseGameLog_Init(); #endif From 8da7734c0da0d1d04b9acf9c25db5e0c957f9116 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 30 Oct 2022 13:32:55 -0500 Subject: [PATCH 45/65] Fixed mapspawn_addon on Linux and made related console messages more verbose --- sp/src/game/shared/vscript_shared.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/sp/src/game/shared/vscript_shared.cpp b/sp/src/game/shared/vscript_shared.cpp index ec41c566..9f1d610c 100644 --- a/sp/src/game/shared/vscript_shared.cpp +++ b/sp/src/game/shared/vscript_shared.cpp @@ -62,7 +62,11 @@ HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing ) const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' ); if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 ) { +#ifdef MAPBASE_VSCRIPT + CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type (\"%s\", from \"%s\") does not match VM type (\"%s\")\n", pszIncomingExtension, pszScriptName, pszVMExtension ); +#else CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type does not match VM type\n" ); +#endif return NULL; } @@ -187,8 +191,16 @@ HSCRIPT VScriptCompileScriptAbsolute( const char *pszScriptName, bool bWarnMissi const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' ); if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 ) { - CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type does not match VM type\n" ); - return NULL; + // Account for cases where there is no extension and the folder names just have dots (e.g. ".local") + if ( strchr( pszIncomingExtension, CORRECT_PATH_SEPARATOR ) ) + { + pszIncomingExtension = NULL; + } + else + { + CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type (\"%s\", from \"%s\") does not match VM type (\"%s\")\n", pszIncomingExtension, pszScriptName, pszVMExtension ); + return NULL; + } } CFmtStr scriptPath; From f5cf90dbc313488511a6d02e66250509bf1407d0 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sun, 30 Oct 2022 13:33:43 -0500 Subject: [PATCH 46/65] Updated GitHub workflows --- .github/workflows/mapbase_build-base-dispatch.yml | 2 ++ .github/workflows/mapbase_build-base.yml | 2 +- .github/workflows/mapbase_build-master.yml | 3 +-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mapbase_build-base-dispatch.yml b/.github/workflows/mapbase_build-base-dispatch.yml index f7275435..d29e30d5 100644 --- a/.github/workflows/mapbase_build-base-dispatch.yml +++ b/.github/workflows/mapbase_build-base-dispatch.yml @@ -64,5 +64,7 @@ jobs: with: configuration: '${{ github.event.inputs.configuration }}' branch: '${{ github.event.inputs.branch }}' + game: '${{ github.event.inputs.game }}' project-group: '${{ github.event.inputs.project-group }}' solution-name: '${{ github.event.inputs.solution-name }}' + build-on-linux: '${{ github.event.inputs.build-on-linux }}' diff --git a/.github/workflows/mapbase_build-base.yml b/.github/workflows/mapbase_build-base.yml index 0eca4ee0..e5619bfc 100644 --- a/.github/workflows/mapbase_build-base.yml +++ b/.github/workflows/mapbase_build-base.yml @@ -212,7 +212,7 @@ jobs: - name: Create project files working-directory: '${{inputs.branch}}/src' - run: sudo ./create${{inputs.project-group}}projects + run: ./create${{inputs.project-group}}projects # -------------------------------------------------------------------- diff --git a/.github/workflows/mapbase_build-master.yml b/.github/workflows/mapbase_build-master.yml index ccbab0a6..9f70451b 100644 --- a/.github/workflows/mapbase_build-master.yml +++ b/.github/workflows/mapbase_build-master.yml @@ -18,7 +18,7 @@ on: - master jobs: - games: + everything: strategy: matrix: configuration: [Release, Debug] @@ -26,7 +26,6 @@ jobs: with: configuration: ${{ matrix.configuration }} branch: 'sp' - game: 'episodic' # Change this if your mod is not using HL2/Episodic game projects project-group: 'all' solution-name: 'everything' build-on-linux: true # Disable this if you don't want to compile for Linux From 2b612a28f425833a2c039773b2acd53c0620e56a Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:50:04 +0300 Subject: [PATCH 47/65] Revert "Added more convenient way to hide HUD elements from clientside VScript" This reverts commit 6ceb808f93694328d053c8dc03e82bb1fe7c408a. --- sp/src/game/client/hud.cpp | 13 ------- sp/src/game/client/mapbase/vscript_vgui.cpp | 35 ------------------- .../shared/mapbase/vscript_consts_shared.cpp | 19 ---------- 3 files changed, 67 deletions(-) diff --git a/sp/src/game/client/hud.cpp b/sp/src/game/client/hud.cpp index 11aab40c..a7d77a32 100644 --- a/sp/src/game/client/hud.cpp +++ b/sp/src/game/client/hud.cpp @@ -947,11 +947,6 @@ float CHud::GetFOVSensitivityAdjust() { return m_flFOVSensitivityAdjust; } - -#ifdef MAPBASE_VSCRIPT -extern int g_iVScriptHideHUD; -#endif - //----------------------------------------------------------------------------- // Purpose: Return true if the passed in sections of the HUD shouldn't be drawn //----------------------------------------------------------------------------- @@ -973,14 +968,6 @@ bool CHud::IsHidden( int iHudFlags ) iHideHud = hidehud.GetInt(); } -#ifdef MAPBASE_VSCRIPT - // Hide elements hidden by scripts - if ( g_iVScriptHideHUD ) - { - iHideHud |= g_iVScriptHideHUD; - } -#endif - // Everything hidden? if ( iHideHud & HIDEHUD_ALL ) return true; diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp index 27e9eb53..61354093 100644 --- a/sp/src/game/client/mapbase/vscript_vgui.cpp +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -143,10 +143,6 @@ CUtlVector< int > g_ScriptTextureIDs; CUtlLinkedList< IScriptVGUIObject*, unsigned short > g_ScriptPanels; -// Used in hud.cpp to help scripts hide HUD elements -int g_iVScriptHideHUD = 0; - - // Boundary is not checked in Surface, keep count manually to sanitise user input. static int g_nFontCount = 0; @@ -3407,9 +3403,6 @@ void CScriptVGUI::LevelShutdownPostEntity() surface()->DestroyTextureID( g_ScriptTextureIDs[i] ); } g_ScriptTextureIDs.Purge(); - - // Reset HUD hidden bits - g_iVScriptHideHUD = 0; } void CScriptVGUI::Shutdown() @@ -3697,29 +3690,6 @@ vgui::HFont GetScriptFont( const char *name, bool proportional ) return script_surface.GetFont( name, proportional, NULL ); } -//----------------------------------------------------------------------------- -// Control which HUD elements on the screen are hidden. -//----------------------------------------------------------------------------- -static int ScriptGetHUDHiddenBits() -{ - return g_iVScriptHideHUD; -} - -static void ScriptSetHUDHiddenBits( int iBits ) -{ - g_iVScriptHideHUD = iBits; -} - -static void ScriptAddHUDHiddenBits( int iBits ) -{ - g_iVScriptHideHUD |= iBits; -} - -static void ScriptClearHUDHiddenBits( int iBits ) -{ - g_iVScriptHideHUD &= ~(iBits); -} - void RegisterScriptVGUI() { @@ -3732,11 +3702,6 @@ void RegisterScriptVGUI() ScriptRegisterFunction( g_pScriptVM, ScreenToRay, "Get a ray from screen pixel position to world space." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get world position normalised in screen space. Return true if on screen." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptGetHUDHiddenBits, "GetHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptSetHUDHiddenBits, "SetHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptAddHUDHiddenBits, "AddHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptClearHUDHiddenBits, "ClearHUDHiddenBits", "Use with 'HIDEHUD_' constants." ); - g_pScriptVM->Run( g_Script_vgui_init ); g_pScriptVM->RegisterInstance( &script_surface, "surface" ); diff --git a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp index f9b9d233..2ced7086 100644 --- a/sp/src/game/shared/mapbase/vscript_consts_shared.cpp +++ b/sp/src/game/shared/mapbase/vscript_consts_shared.cpp @@ -604,25 +604,6 @@ void RegisterSharedScriptConstants() ScriptRegisterConstant( g_pScriptVM, D_NU, "Denotes a 'Neutral' relationship. Used by NPCs and players for relationship disposition." ); #endif -#ifdef CLIENT_DLL - // - // HUD - // - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_WEAPONSELECTION, "Hide ammo count & weapon selection" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_FLASHLIGHT, "" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_ALL, "" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_HEALTH, "Hide health & armor / suit battery" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_PLAYERDEAD, "Hide when local player's dead" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_NEEDSUIT, "Hide when the local player doesn't have the HEV suit" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_MISCSTATUS, "Hide miscellaneous status elements (trains, pickup history, death notices, etc)" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_CHAT, "Hide all communication elements (saytext, voice icon, etc)" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_CROSSHAIR, "Hide crosshairs" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_VEHICLE_CROSSHAIR, "Hide vehicle crosshair" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_INVEHICLE, "" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_BONUS_PROGRESS, "Hide bonus progress display (for bonus map challenges)" ); - ScriptRegisterConstant( g_pScriptVM, HIDEHUD_BITCOUNT, "" ); -#endif - // // Misc. General // From 760e1e6dd5233f439d86ef5b496b715b992cbb55 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:28:00 +0300 Subject: [PATCH 48/65] Add vscript SetHudElementVisible --- sp/src/game/client/hudelement.h | 3 + sp/src/game/client/mapbase/vscript_vgui.cpp | 99 +++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/sp/src/game/client/hudelement.h b/sp/src/game/client/hudelement.h index b903de5d..824cb975 100644 --- a/sp/src/game/client/hudelement.h +++ b/sp/src/game/client/hudelement.h @@ -58,6 +58,9 @@ public: // Hidden bits. // HIDEHUD_ flags that note when this element should be hidden in the HUD virtual void SetHiddenBits( int iBits ); +#ifdef MAPBASE_VSCRIPT + int GetHiddenBits() const { return m_iHiddenBits; } +#endif bool IsParentedToClientDLLRootPanel() const; void SetParentedToClientDLLRootPanel( bool parented ); diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp index 61354093..bed046f0 100644 --- a/sp/src/game/client/mapbase/vscript_vgui.cpp +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -49,6 +49,8 @@ #include "view.h" +#include "hudelement.h" + #include "vscript_vgui.h" #include "vscript_vgui.nut" @@ -3329,6 +3331,18 @@ END_SCRIPTDESC() //============================================================== +struct hudelementcache_t +{ + CUtlConstString name; + int bits; +}; +CUtlVector< hudelementcache_t > m_HudElementCache; + +// Check if hud elements were changed in this level to shortcut on level shutdown +bool m_bHudVisiblityChangedThisLevel = false; + + + class CScriptVGUI : public CAutoGameSystem { public: @@ -3403,6 +3417,26 @@ void CScriptVGUI::LevelShutdownPostEntity() surface()->DestroyTextureID( g_ScriptTextureIDs[i] ); } g_ScriptTextureIDs.Purge(); + + // + // Reset hud element visibility + // + if ( m_bHudVisiblityChangedThisLevel ) + { + m_bHudVisiblityChangedThisLevel = false; + + FOR_EACH_VEC( m_HudElementCache, i ) + { + const hudelementcache_t &cache = m_HudElementCache[i]; + Assert( !cache.name.IsEmpty() ); + CHudElement *elem = gHUD.FindElement( cache.name ); + Assert( elem ); + if ( elem ) + { + elem->SetHiddenBits( cache.bits ); + } + } + } } void CScriptVGUI::Shutdown() @@ -3426,9 +3460,72 @@ void CScriptVGUI::Shutdown() } g_ScriptFonts.Purge(); + + m_HudElementCache.Purge(); } +void SetHudElementVisible( const char *name, bool state ) +{ + CHudElement *elem = gHUD.FindElement( name ); + if ( !elem ) + return; + + int iOldBits = -2; + + FOR_EACH_VEC( m_HudElementCache, i ) + { + const hudelementcache_t &cache = m_HudElementCache[i]; + if ( !V_stricmp( cache.name, name ) ) + { + iOldBits = cache.bits; + break; + } + } + + if ( iOldBits == -2 ) + { + if ( state ) // no change + return; + + // First time setting the visibility of this element, save the original bits + hudelementcache_t &cache = m_HudElementCache.Element( m_HudElementCache.AddToTail() ); + cache.name.Set( name ); + cache.bits = elem->GetHiddenBits(); + } + + elem->SetHiddenBits( state ? iOldBits : -1 ); + + m_bHudVisiblityChangedThisLevel = true; +} + +#ifdef _DEBUG +CON_COMMAND( dump_hud_elements, "" ) +{ + int size = gHUD.m_HudList.Size(); + + CUtlVector< const char* > list( 0, size ); + + for ( int i = 0; i < size; i++ ) + { + list.AddToTail( gHUD.m_HudList[i]->GetName() ); + } + + struct _cmp + { + static int __cdecl fn( const char * const *a, const char * const *b ) { return strcmp( *a, *b ); } + }; + + list.Sort( _cmp::fn ); + + for ( int i = 0; i < size; i++ ) + { + Msg( "%s\n", list[i] ); + } +} +#endif + + class CScriptIInput { public: @@ -3693,6 +3790,8 @@ vgui::HFont GetScriptFont( const char *name, bool proportional ) void RegisterScriptVGUI() { + ScriptRegisterFunction( g_pScriptVM, SetHudElementVisible, "" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptXRES, "XRES", "" ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptYRES, "YRES", "" ); From da2315cfe748eec3167153a67196ef02f04fa1a4 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Fri, 4 Nov 2022 12:44:22 +0300 Subject: [PATCH 49/65] Update vscript_vgui --- sp/src/game/client/mapbase/vscript_vgui.cpp | 192 ++++++++++++++------ sp/src/game/client/mapbase/vscript_vgui.nut | 9 +- 2 files changed, 141 insertions(+), 60 deletions(-) diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp index bed046f0..8d08e8be 100644 --- a/sp/src/game/client/mapbase/vscript_vgui.cpp +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -40,7 +40,9 @@ #include //#include -//#include "bitmap/tgaloader.h" +#if VGUI_TGA_IMAGE_PANEL +#include "bitmap/tgaloader.h" +#endif #if !defined(NO_STEAM) #include "steam/steam_api.h" @@ -48,8 +50,8 @@ #endif #include "view.h" - #include "hudelement.h" +//#include "iclientmode.h" // g_pClientMode->GetViewport() #include "vscript_vgui.h" #include "vscript_vgui.nut" @@ -85,11 +87,16 @@ //============================================================================= -// When enabled, script panels will be parented to custom script root panels. +// When enabled, script panels will be parented to custom root panels. // When disabled, script panels will be parented to engine root panels, and allow Z values for script panels to be interplaced amongst non-script panels. // Changing this is not backwards compatible, as existing top level script panel depth would then change relative to non-script panels. #define SCRIPT_ENGINE_ROOT_PANELS 1 +// NOTE: causes rendering issues +#define ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL 0 + +#define ALLOW_SCRIPT_GAMEUI_ROOT_PANEL 0 + // On level transitions Restore is called up to 4 times in a row (due to .hl? client state files), each time // trying to restore script panels from pre and post transitions, failing every time because script panels are // destroyed on level shutdown but after client state files are written. @@ -102,6 +109,9 @@ // This code is left here for testing. #define SCRIPT_VGUI_SAVERESTORE 0 +#define SCRIPT_VGUI_SIGNAL_INTERFACE 0 + + #ifdef _DEBUG #define DebugMsg(...) ConColorMsg( Color(196, 196, 156, 255), __VA_ARGS__ ) @@ -119,15 +129,6 @@ -using namespace vgui; -class IScriptVGUIObject; -struct FontData_t; -template< typename T > class CCopyableUtlVectorConservative; - -// Aliases contain only one font definition unless 'yres' was defined -typedef CCopyableUtlVectorConservative< FontData_t > fontalias_t; -typedef CUtlDict< fontalias_t > CFontDict; - template< typename T > class CCopyableUtlVectorConservative : public CUtlVectorConservative< T > { @@ -139,6 +140,14 @@ public: }; +using namespace vgui; +class IScriptVGUIObject; +struct FontData_t; + +// Aliases contain only one font definition unless 'yres' was defined +typedef CCopyableUtlVectorConservative< FontData_t > fontalias_t; +typedef CUtlDict< fontalias_t > CFontDict; + CFontDict g_ScriptFonts( k_eDictCompareTypeCaseSensitive ); CUtlVector< int > g_ScriptTextureIDs; @@ -315,7 +324,7 @@ public: // Ideally script fonts would be loaded along with others in engine. // In that case CScriptRootPanel would be removed, and // g_pScriptRootPanel would be CScriptRootDLLPanel inside #if SCRIPT_ENGINE_ROOT_PANELS - void OnScreenSizeChanged( int, int ) + void OnScreenSizeChanged( int w, int t ) { // Reload fonts in the next vgui frame ivgui()->AddTickSignal( GetVPanel() ); @@ -324,6 +333,8 @@ public: // Invalidate cached values if ( g_pScriptVM ) g_pScriptVM->Run( "ISurface.__OnScreenSizeChanged()" ); + + Panel::OnScreenSizeChanged( w, t ); } private: @@ -435,7 +446,6 @@ public: void DrawOutlinedRect( int x0, int y0, int width, int height, int thickness ); void DrawLine( int x0, int y0, int x1, int y1 ); void DrawOutlinedCircle( int x, int y, int radius, int segments ); - //void DrawColoredCircle( int x, int y, int radius, int r, int g, int b, int a ); void SetTextColor( int r, int g, int b, int a ); void SetTextPos( int x, int y ); @@ -450,10 +460,10 @@ public: void CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional ); bool AddCustomFontFile( const char *fontFileName ); + int GetTextureID( char const *filename ); int ValidateTexture( const char *filename, bool hardwareFilter, bool forceReload, bool procedural ); void SetTextureFile( int id, const char *filename, bool hardwareFilter ); - //int ValidateMaterial( const char *materialName, const char *textureGroupName ); int GetTextureWide( int id ); int GetTextureTall( int id ); void SetTexture( int id ); @@ -843,7 +853,34 @@ void CScriptSurface::SetTextureFile( int id, const char *filename, bool hardware } #endif } +#if 0 +void CScriptSurface::SetTextureMaterial( int id, HSCRIPT hMaterial ) +{ + IMaterial *pMaterial = (IMaterial*)HScriptToClass< IScriptMaterial >( hMaterial ); + if ( !IsValid( pMaterial ) ) + return; + if ( g_ScriptTextureIDs.HasElement(id) ) + { + Assert( surface()->IsTextureIDValid(id) ); + MatSystemSurface()->DrawSetTextureMaterial( id, pMaterial ); + + DebugMsg( "Set texture [%i]%s\n", id, pMaterial->GetName() ); + } + +#ifdef _DEBUG + if ( !g_ScriptTextureIDs.HasElement(id) && surface()->IsTextureIDValid(id) ) + { + DebugWarning( "Tried to set non-script created texture! [%i]\n", id ); + } + + if ( !surface()->IsTextureIDValid(id) ) + { + DebugWarning( "Tried to set invalid texture id! [%i]\n", id ); + } +#endif +} +#endif int CScriptSurface::GetTextureWide( int id ) { int w, t; @@ -1306,7 +1343,7 @@ public: g_ScriptPanels.AddToTail( this ); - // Script specified engine root panel. + // Script specified root panel - a cheap alternative to registering uneditable panel instances. // Match the values to vscript_vgui.nut. // // This parameter is hidden in script, and is defined by the return value of dummy functions. @@ -1324,6 +1361,14 @@ public: case 2: vparent = VGUI_GetScriptRootPanel( PANEL_CLIENTDLL ); break; +#if ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL + // Hud viewport + case 10: + Assert( g_pClientMode && g_pClientMode->GetViewport() ); + vparent = g_pClientMode->GetViewport()->GetVPanel(); + break; +#endif + default: UNREACHABLE(); // Invalid parent panel } _base->SetParent( vparent ); @@ -1355,7 +1400,7 @@ public: { ivgui()->AddTickSignal( this->GetVPanel(), i ); } -#if VGUI_SIGNAL_INTERFACE +#if SCRIPT_VGUI_SIGNAL_INTERFACE void AddActionSignalTarget( HSCRIPT messageTarget ) { IScriptVGUIObject *obj = ToScriptVGUIObj( messageTarget ); @@ -1386,15 +1431,16 @@ public: #ifdef _DEBUG // Is my parent one of the root panels? - bool b = false; + bool bRootParent = false; #if SCRIPT_ENGINE_ROOT_PANELS - if ( parent == g_pScriptRootPanel->GetVPanel() || -#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL - (g_pScriptGameUIDLLPanel && parent == g_pScriptGameUIDLLPanel->GetVPanel()) || -#endif - (g_pScriptClientDLLPanel && parent == g_pScriptClientDLLPanel->GetVPanel()) ) + if ( ( parent == g_pScriptRootPanel->GetVPanel() ) + #if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL + || ( g_pScriptGameUIDLLPanel && parent == g_pScriptGameUIDLLPanel->GetVPanel() ) + #endif + || ( g_pScriptClientDLLPanel && parent == g_pScriptClientDLLPanel->GetVPanel() ) + ) { - b = true; + bRootParent = true; } else #endif @@ -1402,13 +1448,16 @@ public: { if ( parent == enginevgui->GetPanel( (VGuiPanel_t)i ) ) { - b = true; + bRootParent = true; break; } } - +#if ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL + if ( g_pClientMode && g_pClientMode->GetViewport() && ( parent == g_pClientMode->GetViewport()->GetVPanel() ) ) + bRootParent = true; +#endif // My parent wasn't registered. - AssertMsg1( b, "'%s'", ipanel()->GetName(parent) ); + AssertMsg1( bRootParent, "'%s'", ipanel()->GetName(parent) ); #endif return NULL; @@ -1447,8 +1496,7 @@ public: { g_pScriptVM->ArrayAppend( arr, obj->GetScriptInstance() ); } - // UNDONE: Register C++ created children of script created panels. - // It is safe to do so because their lifetime depends on their script parents. + // Beware of dangling pointers if C++ created children are to be registered } } @@ -1917,15 +1965,11 @@ public: CLASS_HELPER_INTERFACE( Button, Label ) { public: - // NOTE: This is used if DoClick() callback is not implemented in CScript_Button. - // This changes where and how button command is processed - - // whether in the button { DoClick() } or in an external panel { OnCommand(cmd) }. - // It is fine to always use DoClick() instead of vgui messages - // because of the dynamic nature of script closures. -#if VGUI_SIGNAL_INTERFACE +#if SCRIPT_VGUI_SIGNAL_INTERFACE + // Sets the command message to send to the action signal target when the button is pressed void SetCommand( const char *command ) { - if ( !V_strncmp( command, "url ", 4 ) ) + if ( !V_strnicmp( command, "url ", 4 ) ) { __base()->SetCommand( (KeyValues*)NULL ); @@ -1970,12 +2014,7 @@ public: { __base()->ForceDepressed(state); } -#if 0 - void SetBlink( bool state ) - { - __base()->SetBlink(state); - } -#endif + void SetMouseClickEnabled( int code, bool state ) { __base()->SetMouseClickEnabled( (MouseCode)code, state ); @@ -2005,12 +2044,7 @@ public: { __base()->SetDepressedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); } -#if 0 - void SetBlinkColor( int r, int g, int b, int a ) - { - __base()->SetBlinkColor( Color(r, g, b, a) ); - } -#endif + void SetArmedSound( const char *sound ) { __base()->SetArmedSound( sound ); @@ -2400,7 +2434,7 @@ public: #endif //-------------------------------------------------------------- //-------------------------------------------------------------- -#if 0 +#if VGUI_TGA_IMAGE_PANEL CLASS_HELPER_INTERFACE( TGAImagePanel, Panel ) { public: @@ -2437,10 +2471,12 @@ public: //============================================================== -#define SetHScript( var, val ) \ - if ( var && g_pScriptVM ) \ - g_pScriptVM->ReleaseScript( var ); \ +static inline void SetHScript( HSCRIPT &var, HSCRIPT val ) +{ + if ( var && g_pScriptVM ) + g_pScriptVM->ReleaseScript( var ); var = val; +} #define CheckCallback(s)\ if ( FStrEq( cb, #s ) )\ @@ -2479,6 +2515,9 @@ private: HSCRIPT m_hfnOnKeyCodePressed; HSCRIPT m_hfnOnKeyCodeReleased; HSCRIPT m_hfnOnKeyCodeTyped; +#if SCRIPT_VGUI_SIGNAL_INTERFACE + HSCRIPT m_hfnOnCommand; +#endif public: CScript_Panel( Panel *parent, const char *name ) : @@ -2504,6 +2543,10 @@ public: m_hfnOnKeyCodePressed(NULL), m_hfnOnKeyCodeReleased(NULL), m_hfnOnKeyCodeTyped(NULL) +#if SCRIPT_VGUI_SIGNAL_INTERFACE + , + m_hfnOnCommand(NULL) +#endif {} void Shutdown() @@ -2530,6 +2573,9 @@ public: SetHScript( m_hfnOnKeyCodePressed, NULL ); SetHScript( m_hfnOnKeyCodeReleased, NULL ); SetHScript( m_hfnOnKeyCodeTyped, NULL ); +#if SCRIPT_VGUI_SIGNAL_INTERFACE + SetHScript( m_hfnOnCommand, NULL ); +#endif } public: @@ -2580,7 +2626,7 @@ public: g_pScriptVM->ExecuteFunction( m_hfnOnScreenSizeChanged, args, 2, NULL, NULL, true ); } } -#if VGUI_SIGNAL_INTERFACE +#if SCRIPT_VGUI_SIGNAL_INTERFACE void OnCommand( const char *command ) { if ( m_hfnOnCommand ) @@ -2705,6 +2751,7 @@ public: BaseClass::OnKeyCodeTyped( code ); } + public: void SetCallback( const char* cb, HSCRIPT fn ) { @@ -2728,6 +2775,9 @@ public: CheckCallback( OnKeyCodePressed ); CheckCallback( OnKeyCodeReleased ); CheckCallback( OnKeyCodeTyped ); +#if SCRIPT_VGUI_SIGNAL_INTERFACE + CheckCallback( OnCommand ); +#endif g_pScriptVM->RaiseException("invalid callback"); } @@ -2760,6 +2810,9 @@ private: HSCRIPT m_hfnOnKeyCodePressed; HSCRIPT m_hfnOnKeyCodeReleased; HSCRIPT m_hfnOnKeyCodeTyped; +#if SCRIPT_VGUI_SIGNAL_INTERFACE + HSCRIPT m_hfnOnCommand; +#endif public: CScript_Frame( Panel *parent, const char *name ) : @@ -2786,6 +2839,10 @@ public: m_hfnOnKeyCodePressed(NULL), m_hfnOnKeyCodeReleased(NULL), m_hfnOnKeyCodeTyped(NULL) +#if SCRIPT_VGUI_SIGNAL_INTERFACE + , + m_hfnOnCommand(NULL) +#endif { SetFadeEffectDisableOverride( true ); } @@ -2809,6 +2866,9 @@ public: SetHScript( m_hfnOnKeyCodePressed, NULL ); SetHScript( m_hfnOnKeyCodeReleased, NULL ); SetHScript( m_hfnOnKeyCodeTyped, NULL ); +#if SCRIPT_VGUI_SIGNAL_INTERFACE + SetHScript( m_hfnOnCommand, NULL ); +#endif } public: @@ -2854,7 +2914,22 @@ public: g_pScriptVM->ExecuteFunction( m_hfnOnScreenSizeChanged, args, 2, NULL, NULL, true ); } } +#if SCRIPT_VGUI_SIGNAL_INTERFACE + void OnCommand( const char *command ) + { + if ( m_hfnOnCommand ) + { + ScriptVariant_t ret, arg = command; + g_pScriptVM->ExecuteFunction( m_hfnOnCommand, &arg, 1, &ret, NULL, true ); + // Return true to swallow + if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) + return; + } + + BaseClass::OnCommand( command ); + } +#endif void OnCursorEntered() { if ( m_hfnOnCursorEntered ) @@ -2974,6 +3049,7 @@ public: BaseClass::OnKeyCodeTyped( code ); } } + public: void SetCallback( const char* cb, HSCRIPT fn ) { @@ -2996,6 +3072,9 @@ public: CheckCallback( OnKeyCodePressed ); CheckCallback( OnKeyCodeReleased ); CheckCallback( OnKeyCodeTyped ); +#if SCRIPT_VGUI_SIGNAL_INTERFACE + CheckCallback( OnCommand ); +#endif g_pScriptVM->RaiseException("invalid callback"); } @@ -3144,7 +3223,7 @@ public: #endif //-------------------------------------------------------------- //-------------------------------------------------------------- -#if 0 +#if VGUI_TGA_IMAGE_PANEL class CTGAImagePanel : public Panel { DECLARE_SCRIPTVGUI_CLASS_EX( CTGAImagePanel, Panel ); @@ -3313,7 +3392,7 @@ END_SCRIPTDESC() #endif //-------------------------------------------------------------- //-------------------------------------------------------------- -#if 0 +#if VGUI_TGA_IMAGE_PANEL BEGIN_VGUI_HELPER_EX( TGAImagePanel, CTGAImagePanel ) END_VGUI_HELPER() @@ -3387,6 +3466,9 @@ HSCRIPT CScriptVGUI::CreatePanel( const char* panelClass, HSCRIPT parent, const #if !defined(NO_STEAM) Check( AvatarImage ); #endif +#if VGUI_TGA_IMAGE_PANEL + Check( TGAImagePanel ); +#endif g_pScriptVM->RaiseException("invalid vgui class"); return NULL; diff --git a/sp/src/game/client/mapbase/vscript_vgui.nut b/sp/src/game/client/mapbase/vscript_vgui.nut index df0285eb..a4452705 100644 --- a/sp/src/game/client/mapbase/vscript_vgui.nut +++ b/sp/src/game/client/mapbase/vscript_vgui.nut @@ -91,7 +91,7 @@ local _FontTall = {} local DoGetFont = ISurface.DoGetFont <- ISurface.GetFont; local DoGetFontTall = ISurface.GetFontTall; -ISurface.GetFont <- function( name, proportional = false, sch = "" ) +ISurface.GetFont <- function( name, proportional, sch = "" ) { if ( sch in _Schemes ) { @@ -101,6 +101,8 @@ ISurface.GetFont <- function( name, proportional = false, sch = "" ) } else { + if ( typeof sch != "string" ) + throw "invalid parameter 'scheme'"; _Schemes[sch] <- [{}, {}]; } @@ -152,6 +154,7 @@ ISurface.GetTextureID <- function( name ) IVGui.GetRootPanel <- function() { return 1000 } //IVGui.GetGameUIRootPanel <- function() { return 1001 } IVGui.GetClientDLLRootPanel <- function() { return 1002 } +//IVGui.GetHudViewportPanel <- function() { return 1010 } local CreatePanel = IVGui.CreatePanel; IVGui.CreatePanel <- function( type, parent, name ) @@ -169,10 +172,6 @@ IVGui.CreatePanel <- function( type, parent, name ) root = 0; break; - case 1001: - root = 1; - break; - case 1002: root = 2; break; From e843aed912dd94f4272945471db8d0db2320c2c5 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Thu, 17 Nov 2022 08:28:20 +0300 Subject: [PATCH 50/65] Debug assertion on SquirrelVM::GetValue() --- sp/src/vscript/vscript_squirrel.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sp/src/vscript/vscript_squirrel.cpp b/sp/src/vscript/vscript_squirrel.cpp index ddb8069e..5efb2314 100644 --- a/sp/src/vscript/vscript_squirrel.cpp +++ b/sp/src/vscript/vscript_squirrel.cpp @@ -2970,6 +2970,14 @@ int SquirrelVM::GetKeyValue(HSCRIPT hScope, int nIterator, ScriptVariant_t* pKey bool SquirrelVM::GetValue(HSCRIPT hScope, const char* pszKey, ScriptVariant_t* pValue) { +#ifdef _DEBUG + AssertMsg( pszKey, "FATAL: cannot get NULL" ); + + // Don't crash on debug + if ( !pszKey ) + return GetValue( hScope, ScriptVariant_t(0), pValue ); +#endif + SquirrelSafeCheck safeCheck(vm_); Assert(pValue); From ac45061b36740550557d5c011345ecfc506e12f8 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Thu, 17 Nov 2022 08:28:26 +0300 Subject: [PATCH 51/65] Add debug cvar script_net_debug --- sp/src/game/shared/mapbase/vscript_singletons.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 2732c801..c5cca45b 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -1277,9 +1277,11 @@ CNetMsgScriptHelper *g_ScriptNetMsg = &scriptnetmsg; #ifdef _DEBUG #ifdef GAME_DLL -#define DebugNetMsg( l, ... ) do { extern ConVar developer; if (developer.GetInt() >= l) ConColorMsg( Color(100, 225, 255, 255), __VA_ARGS__ ); } while (0); +ConVar script_net_debug("script_net_debug", "0"); +#define DebugNetMsg( l, ... ) do { if (script_net_debug.GetInt() >= l) ConColorMsg( Color(100, 225, 255, 255), __VA_ARGS__ ); } while (0); #else -#define DebugNetMsg( l, ... ) do { extern ConVar developer; if (developer.GetInt() >= l) ConColorMsg( Color(100, 225, 175, 255), __VA_ARGS__ ); } while (0); +ConVar script_net_debug("script_net_debug_client", "0"); +#define DebugNetMsg( l, ... ) do { if (script_net_debug.GetInt() >= l) ConColorMsg( Color(100, 225, 175, 255), __VA_ARGS__ ); } while (0); #endif #define DebugWarning(...) Warning( __VA_ARGS__ ) #else @@ -1428,7 +1430,7 @@ void CNetMsgScriptHelper::ReceiveMessage( bf_read &msg ) m_MsgIn.StartReading( msg.m_pData, msg.m_nDataBytes ); #endif - DebugNetMsg( 2, DLL_LOC_STR " %s()", __FUNCTION__ ); + DebugNetMsg( 2, DLL_LOC_STR " %s()\n", __FUNCTION__ ); // Don't do anything if there's no VM here. This can happen if a message from the server goes to a VM-less client, or vice versa. if ( !g_pScriptVM ) From c3e2ab338529ec991a2850bfe5932ee174257162 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Thu, 17 Nov 2022 08:47:55 +0300 Subject: [PATCH 52/65] Add missing vscript const FCVAR_CHEAT --- sp/src/vscript/vscript_bindings_base.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sp/src/vscript/vscript_bindings_base.cpp b/sp/src/vscript/vscript_bindings_base.cpp index 69ca2187..4f20234a 100644 --- a/sp/src/vscript/vscript_bindings_base.cpp +++ b/sp/src/vscript/vscript_bindings_base.cpp @@ -539,11 +539,12 @@ void RegisterBaseBindings( IScriptVM *pVM ) 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_CHEAT, "Only useable in singleplayer / debug / multiplayer & sv_cheats" ); 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_REPLICATED, "If this convar flag is set, it will enforce a serverside value on any clientside counterparts. (also known as FCVAR_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." ); From 713c8e8cf3d9b15cd93fedf2bc5551adf59de849 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Thu, 17 Nov 2022 08:48:06 +0300 Subject: [PATCH 53/65] Optimise 3D skybox rotation --- sp/src/game/client/viewrender.cpp | 77 ++++++++----------------------- 1 file changed, 18 insertions(+), 59 deletions(-) diff --git a/sp/src/game/client/viewrender.cpp b/sp/src/game/client/viewrender.cpp index c88858d5..2acc9d91 100644 --- a/sp/src/game/client/viewrender.cpp +++ b/sp/src/game/client/viewrender.cpp @@ -409,10 +409,6 @@ protected: void Enable3dSkyboxFog( void ); void DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostRender, ITexture *pRenderTarget, ITexture *pDepthTarget ); -#ifdef MAPBASE - void CalculateSkyAngles( const QAngle &angAngles ); -#endif - sky3dparams_t * PreRender3dSkyboxWorld( SkyboxVisibility_t nSkyboxVisible ); sky3dparams_t *m_pSky3dParams; @@ -5400,10 +5396,16 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR // Re-use the x coordinate to determine if we shuld do this with angles if (m_pSky3dParams->angles.GetX() != 0) { - CalculateSkyAngles( m_pSky3dParams->skycamera->GetAbsAngles() ); + const matrix3x4_t &matSky = m_pSky3dParams->skycamera->EntityToWorldTransform(); + matrix3x4_t matView; + AngleMatrix( angles, origin, matView ); + ConcatTransforms( matSky, matView, matView ); + MatrixAngles( matView, angles, origin ); + } + else + { + VectorAdd( origin, m_pSky3dParams->skycamera->GetAbsOrigin(), origin ); } - - VectorAdd( origin, m_pSky3dParams->skycamera->GetAbsOrigin(), origin ); } else { @@ -5411,10 +5413,16 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR m_pSky3dParams->angles.GetY() != 0 || m_pSky3dParams->angles.GetZ() != 0) { - CalculateSkyAngles( m_pSky3dParams->angles.Get() ); + matrix3x4_t matSky, matView; + AngleMatrix( m_pSky3dParams->angles, m_pSky3dParams->origin, matSky ); + AngleMatrix( angles, origin, matView ); + ConcatTransforms( matSky, matView, matView ); + MatrixAngles( matView, angles, origin ); + } + else + { + VectorAdd( origin, m_pSky3dParams->origin, origin ); } - - VectorAdd( origin, m_pSky3dParams->origin, origin ); } #else VectorAdd( origin, m_pSky3dParams->origin, origin ); @@ -5531,55 +5539,6 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR #endif } -#ifdef MAPBASE -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CSkyboxView::CalculateSkyAngles( const QAngle &angAngles ) -{ - // Unfortunately, it's not as simple as "angles += m_pSky3dParams->angles". - // This stuff took a long time to figure out. I'm glad I got it working. - - // First, create a matrix for the sky's angles. - matrix3x4_t matSkyAngles; - AngleMatrix( angAngles, matSkyAngles ); - - // The code in between the lines below was mostly lifted from projected texture screenspace code and was a huge lifesaver. - // The comments are my attempt at explaining the little I understand of what's going on here. - // ---------------------------------------------------------------------- - - // These are the vectors that would eventually become our final angle directions. - Vector vecSkyForward, vecSkyRight, vecSkyUp; - - // Get vectors from our original angles. - Vector vPlayerForward, vPlayerRight, vPlayerUp; - AngleVectors( angles, &vPlayerForward, &vPlayerRight, &vPlayerUp ); - - // Transform them from our sky angles matrix and put the results in those vectors we declared earlier. - VectorTransform( vPlayerForward, matSkyAngles, vecSkyForward ); - VectorTransform( vPlayerRight, matSkyAngles, vecSkyRight ); - VectorTransform( vPlayerUp, matSkyAngles, vecSkyUp ); - - // Normalize them. - VectorNormalize( vecSkyForward ); - VectorNormalize( vecSkyRight ); - VectorNormalize( vecSkyUp ); - - // Now do a bit of quaternion magic and apply that to our original angles. - // This works perfectly, so I'm not gonna touch it. - Quaternion quat; - BasisToQuaternion( vecSkyForward, vecSkyRight, vecSkyUp, quat ); - QuaternionAngles( quat, angles ); - - // End of code mostly lifted from projected texture screenspace stuff - // ---------------------------------------------------------------------- - - // Now just rotate our origin with that matrix. - // We create a copy of the origin since VectorRotate doesn't want in1 to be the same variable as the destination. - VectorRotate(Vector(origin), matSkyAngles, origin); -} -#endif - //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- From cc0c90693d123174d31bc81a5816c634ecb41311 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Thu, 17 Nov 2022 08:48:10 +0300 Subject: [PATCH 54/65] Optimise func_fake_worldportal render code Consistent and descriptive variable names, simplified calculations. --- .../mapbase/c_func_fake_worldportal.cpp | 90 +++-------- .../client/mapbase/c_func_fake_worldportal.h | 4 +- sp/src/game/client/viewrender.cpp | 143 +++++++----------- sp/src/game/client/viewrender.h | 2 +- 4 files changed, 70 insertions(+), 169 deletions(-) diff --git a/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp b/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp index 1cae8ebe..3a5751d1 100644 --- a/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp +++ b/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp @@ -58,70 +58,11 @@ bool C_FuncFakeWorldPortal::ShouldDraw() } -//----------------------------------------------------------------------------- -// Do we have a fake world portal in view? -//----------------------------------------------------------------------------- -C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane ) -{ - // Early out if no cameras - C_FuncFakeWorldPortal *pReflectiveGlass = GetFakeWorldPortalList(); - if ( !pReflectiveGlass ) - return NULL; - - Frustum_t frustum; - GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum ); - - cplane_t localPlane; - Vector vecOrigin, vecWorld, vecDelta, vecForward; - AngleVectors( view.angles, &vecForward, NULL, NULL ); - - for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext ) - { - if ( pReflectiveGlass->IsDormant() ) - continue; - - if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) ) - continue; - - Vector vecMins, vecMaxs; - pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs ); - if ( R_CullBox( vecMins, vecMaxs, frustum ) ) - continue; - - const model_t *pModel = pReflectiveGlass->GetModel(); - const matrix3x4_t& mat = pReflectiveGlass->EntityToWorldTransform(); - - int nCount = modelinfo->GetBrushModelPlaneCount( pModel ); - for ( int i = 0; i < nCount; ++i ) - { - modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin ); - - MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space - VectorTransform( vecOrigin, mat, vecWorld ); - - if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane - continue; - - VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull - if ( vecDelta.Dot( plane.normal ) >= 0 ) - continue; - - // Must have valid plane - if ( !pReflectiveGlass->m_hTargetPlane ) - continue; - - return pReflectiveGlass; - } - } - - return NULL; -} - //----------------------------------------------------------------------------- // Iterates through fake world portals instead of just picking one //----------------------------------------------------------------------------- C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, - cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum ) + Vector &vecAbsPlaneNormal, Vector &vecPlaneLocalOrigin, const Frustum_t &frustum ) { // Early out if no cameras C_FuncFakeWorldPortal *pReflectiveGlass = NULL; @@ -130,8 +71,9 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const else pReflectiveGlass = pStart->m_pNext; - cplane_t localPlane; - Vector vecOrigin, vecWorld, vecDelta; + cplane_t localPlane, worldPlane; + Vector vecMins, vecMaxs, vecLocalOrigin, vecAbsOrigin, vecDelta; + for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext ) { if ( pReflectiveGlass->IsDormant() ) @@ -140,7 +82,10 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) ) continue; - Vector vecMins, vecMaxs; + // Must have valid plane + if ( !pReflectiveGlass->m_hTargetPlane ) + continue; + pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs ); if ( R_CullBox( vecMins, vecMaxs, frustum ) ) continue; @@ -151,23 +96,22 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const int nCount = modelinfo->GetBrushModelPlaneCount( pModel ); for ( int i = 0; i < nCount; ++i ) { - modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin ); + modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecLocalOrigin ); - MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space - VectorTransform( vecOrigin, mat, vecWorld ); + MatrixTransformPlane( mat, localPlane, worldPlane ); // Transform to world space - if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane + if ( view.origin.Dot( worldPlane.normal ) <= worldPlane.dist ) // Check for view behind plane continue; - VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull - if ( vecDelta.Dot( plane.normal ) >= 0 ) + VectorTransform( vecLocalOrigin, mat, vecAbsOrigin ); + VectorSubtract( vecAbsOrigin, view.origin, vecDelta ); + + if ( vecDelta.Dot( worldPlane.normal ) >= 0 ) // Backface cull continue; - // Must have valid plane - if ( !pReflectiveGlass->m_hTargetPlane ) - continue; + vecPlaneLocalOrigin = vecLocalOrigin; + vecAbsPlaneNormal = worldPlane.normal; - vecPlaneOrigin = vecOrigin; return pReflectiveGlass; } } diff --git a/sp/src/game/client/mapbase/c_func_fake_worldportal.h b/sp/src/game/client/mapbase/c_func_fake_worldportal.h index 1bae2de0..7912e2cb 100644 --- a/sp/src/game/client/mapbase/c_func_fake_worldportal.h +++ b/sp/src/game/client/mapbase/c_func_fake_worldportal.h @@ -53,10 +53,8 @@ public: //----------------------------------------------------------------------------- // Do we have reflective glass in view? If so, what's the reflection plane? //----------------------------------------------------------------------------- -C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane ); - C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, - cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum ); + Vector &vecAbsPlaneNormal, Vector &vecPlaneOrigin, const Frustum_t &frustum ); #endif // C_FUNC_FAKE_WORLDPORTAL diff --git a/sp/src/game/client/viewrender.cpp b/sp/src/game/client/viewrender.cpp index 2acc9d91..e77bb1ea 100644 --- a/sp/src/game/client/viewrender.cpp +++ b/sp/src/game/client/viewrender.cpp @@ -2106,20 +2106,18 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT Frustum_t frustum; GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum ); - cplane_t portalPlane; - Vector vecPlaneOrigin; - //C_FuncFakeWorldPortal *pPortalEnt = IsFakeWorldPortalInView( view, portalPlane ); - //if ( pPortalEnt ) - C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, vecPlaneOrigin, frustum ); + Vector vecAbsPlaneNormal; + Vector vecPlaneLocalOrigin; + C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, vecAbsPlaneNormal, vecPlaneLocalOrigin, frustum ); while ( pPortalEnt != NULL ) { ITexture *pCameraTarget = pPortalEnt->RenderTarget(); int width = pCameraTarget->GetActualWidth(); int height = pCameraTarget->GetActualHeight(); - DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane, vecPlaneOrigin ); + DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, vecAbsPlaneNormal, vecPlaneLocalOrigin ); - pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, vecPlaneOrigin, frustum ); + pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, vecAbsPlaneNormal, vecPlaneLocalOrigin, frustum ); } #endif } @@ -3537,8 +3535,6 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin } #ifdef MAPBASE -ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0"); - //----------------------------------------------------------------------------- // Purpose: Sets up scene and renders WIP fake world portal view. // Based on code from monitors, mirrors, and logic_measure_movement. @@ -3555,7 +3551,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0"); //----------------------------------------------------------------------------- bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer, int x, int y, int width, int height, - const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin ) + const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, const Vector &vecPlaneLocalOrigin ) { #ifdef USE_MONITORS VPROF_INCREMENT_COUNTER( "cameras rendered", 1 ); @@ -3586,85 +3582,52 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP } } - monitorView.width = width; - monitorView.height = height; monitorView.x = x; monitorView.y = y; - - monitorView.origin = mainView.origin; - monitorView.angles = mainView.angles; - - // Debug stuff - static float flLastDebugTime = 0.0f; - bool bDebug = r_fakeworldportal_debug.GetBool() && gpGlobals->curtime > flLastDebugTime; - - // - // Calculate the angles for the fake portal plane - // - QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles; - QAngle angFakePortalAngles; - - // Get vectors from our original angles. - Vector vOurForward, vOurRight, vOurUp; - AngleVectors( pCameraEnt->GetAbsAngles(), &vOurForward, &vOurRight, &vOurUp ); - - Quaternion quat; - BasisToQuaternion( ourPlane.normal, vOurRight, vOurUp, quat ); - QuaternionAngles( quat, angFakePortalAngles ); - - if (bDebug) - { - // RED - Initial player origin - debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f ); - - // YELLOW - Portal origin - debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angFakePortalAngles, 255, 224, 0, 128, 10.0f ); - } - - // - // Translate the actual portal view position to be relative to the target - // - matrix3x4_t matPlayer, matPortal, matPlayerToPortal; - AngleIMatrix( monitorView.angles, monitorView.origin, matPlayer ); - AngleMatrix( angFakePortalAngles, pCameraEnt->GetAbsOrigin(), matPortal ); - ConcatTransforms( matPlayer, matPortal, matPlayerToPortal ); - - // Apply the scale factor - if ( pCameraEnt->m_flScale > 0 ) - { - Vector vecTranslation; - MatrixGetColumn( matPlayerToPortal, 3, vecTranslation ); - vecTranslation /= pCameraEnt->m_flScale; - MatrixSetColumn( vecTranslation, 3, matPlayerToPortal ); - } - - matrix3x4_t matTarget; - AngleMatrix( angTargetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), matTarget ); - - // Now apply the new matrix to the new reference point - matrix3x4_t matPortalToPlayer, matNewPlayerPosition; - MatrixInvert( matPlayerToPortal, matPortalToPlayer ); - - ConcatTransforms( matTarget, matPortalToPlayer, matNewPlayerPosition ); - - MatrixAngles( matNewPlayerPosition, monitorView.angles, monitorView.origin ); - - if (bDebug) - { - // BLUE - Target origin - debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angTargetAngles, 0, 0, 255, 128, 10.0f ); - - // GREEN - Final origin - debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 255, 0, 128, 10.0f ); - - flLastDebugTime = gpGlobals->curtime + 5.0f; - } - - monitorView.fov = mainView.fov; + monitorView.width = width; + monitorView.height = height; monitorView.m_bOrtho = mainView.m_bOrtho; + monitorView.fov = mainView.fov; monitorView.m_flAspectRatio = mainView.m_flAspectRatio; monitorView.m_bViewToProjectionOverride = false; + matrix3x4_t worldToView; + AngleIMatrix( mainView.angles, mainView.origin, worldToView ); + + matrix3x4_t targetToWorld; + { + // NOTE: m_PlaneAngles is angle offset + QAngle targetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles; + AngleMatrix( targetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), targetToWorld ); + } + + matrix3x4_t portalToWorld; + { + Vector left, up; + VectorVectors( vecAbsPlaneNormal, left, up ); + VectorNegate( left ); + portalToWorld.Init( vecAbsPlaneNormal, left, up, pCameraEnt->GetAbsOrigin() ); + } + + matrix3x4_t portalToView; + ConcatTransforms( worldToView, portalToWorld, portalToView ); + + if ( pCameraEnt->m_flScale > 0.0f ) + { + portalToView[0][3] /= pCameraEnt->m_flScale; + portalToView[1][3] /= pCameraEnt->m_flScale; + portalToView[2][3] /= pCameraEnt->m_flScale; + } + + matrix3x4_t viewToPortal; + MatrixInvert( portalToView, viewToPortal ); + + matrix3x4_t newViewToWorld; + ConcatTransforms( targetToWorld, viewToPortal, newViewToWorld ); + + MatrixAngles( newViewToWorld, monitorView.angles, monitorView.origin ); + + // @MULTICORE (toml 8/11/2006): this should be a renderer.... int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL); bool bDrew3dSkybox = false; @@ -3687,21 +3650,17 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP SafeRelease( pSkyView ); } - // - // Make a clipping plane for the target view - // Vector4D plane; - Vector vecAnglesNormal; - AngleVectors( angTargetAngles, &vecAnglesNormal ); - VectorNormalize( vecAnglesNormal ); - VectorCopy( -vecAnglesNormal, plane.AsVector3D() ); + MatrixGetColumn( targetToWorld, 0, plane.AsVector3D() ); + VectorNormalize( plane.AsVector3D() ); + VectorNegate( plane.AsVector3D() ); // The portal plane's distance from the actual brush's origin - float flPlaneDist = vecPlaneOrigin.Length(); + float flPlaneDist = vecPlaneLocalOrigin.Length(); // The target's distance from world origin - plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * vecAnglesNormal).Length() + flPlaneDist) + 0.1f; + plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * plane.AsVector3D()).Length() + flPlaneDist) + 0.1f; CMatRenderContextPtr pRenderContext( materials ); pRenderContext->PushCustomClipPlane( plane.Base() ); diff --git a/sp/src/game/client/viewrender.h b/sp/src/game/client/viewrender.h index 936a282b..0aa24db6 100644 --- a/sp/src/game/client/viewrender.h +++ b/sp/src/game/client/viewrender.h @@ -454,7 +454,7 @@ private: #ifdef MAPBASE bool DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer, int x, int y, int width, int height, - const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin ); + const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, const Vector &vecPlaneOrigin ); #endif // Drawing primitives From 1ca7558421d9b43af42c934968886ee7ba747fed Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Thu, 17 Nov 2022 08:48:12 +0300 Subject: [PATCH 55/65] Fix func_fake_worldportal clip plane --- .../mapbase/c_func_fake_worldportal.cpp | 4 ++-- .../client/mapbase/c_func_fake_worldportal.h | 2 +- sp/src/game/client/viewrender.cpp | 20 +++++++++---------- sp/src/game/client/viewrender.h | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp b/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp index 3a5751d1..703d5a88 100644 --- a/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp +++ b/sp/src/game/client/mapbase/c_func_fake_worldportal.cpp @@ -62,7 +62,7 @@ bool C_FuncFakeWorldPortal::ShouldDraw() // Iterates through fake world portals instead of just picking one //----------------------------------------------------------------------------- C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, - Vector &vecAbsPlaneNormal, Vector &vecPlaneLocalOrigin, const Frustum_t &frustum ) + Vector &vecAbsPlaneNormal, float &flLocalPlaneDist, const Frustum_t &frustum ) { // Early out if no cameras C_FuncFakeWorldPortal *pReflectiveGlass = NULL; @@ -109,7 +109,7 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const if ( vecDelta.Dot( worldPlane.normal ) >= 0 ) // Backface cull continue; - vecPlaneLocalOrigin = vecLocalOrigin; + flLocalPlaneDist = localPlane.dist; vecAbsPlaneNormal = worldPlane.normal; return pReflectiveGlass; diff --git a/sp/src/game/client/mapbase/c_func_fake_worldportal.h b/sp/src/game/client/mapbase/c_func_fake_worldportal.h index 7912e2cb..bc1d9e61 100644 --- a/sp/src/game/client/mapbase/c_func_fake_worldportal.h +++ b/sp/src/game/client/mapbase/c_func_fake_worldportal.h @@ -54,7 +54,7 @@ public: // Do we have reflective glass in view? If so, what's the reflection plane? //----------------------------------------------------------------------------- C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, - Vector &vecAbsPlaneNormal, Vector &vecPlaneOrigin, const Frustum_t &frustum ); + Vector &vecAbsPlaneNormal, float &flLocalPlaneDist, const Frustum_t &frustum ); #endif // C_FUNC_FAKE_WORLDPORTAL diff --git a/sp/src/game/client/viewrender.cpp b/sp/src/game/client/viewrender.cpp index e77bb1ea..6bcff8da 100644 --- a/sp/src/game/client/viewrender.cpp +++ b/sp/src/game/client/viewrender.cpp @@ -2107,17 +2107,17 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum ); Vector vecAbsPlaneNormal; - Vector vecPlaneLocalOrigin; - C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, vecAbsPlaneNormal, vecPlaneLocalOrigin, frustum ); + float flLocalPlaneDist; + C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, vecAbsPlaneNormal, flLocalPlaneDist, frustum ); while ( pPortalEnt != NULL ) { ITexture *pCameraTarget = pPortalEnt->RenderTarget(); int width = pCameraTarget->GetActualWidth(); int height = pCameraTarget->GetActualHeight(); - DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, vecAbsPlaneNormal, vecPlaneLocalOrigin ); + DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, vecAbsPlaneNormal, flLocalPlaneDist ); - pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, vecAbsPlaneNormal, vecPlaneLocalOrigin, frustum ); + pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, vecAbsPlaneNormal, flLocalPlaneDist, frustum ); } #endif } @@ -3551,7 +3551,7 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin //----------------------------------------------------------------------------- bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer, int x, int y, int width, int height, - const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, const Vector &vecPlaneLocalOrigin ) + const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, float flLocalPlaneDist ) { #ifdef USE_MONITORS VPROF_INCREMENT_COUNTER( "cameras rendered", 1 ); @@ -3652,15 +3652,15 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP Vector4D plane; + // target direction MatrixGetColumn( targetToWorld, 0, plane.AsVector3D() ); VectorNormalize( plane.AsVector3D() ); VectorNegate( plane.AsVector3D() ); - // The portal plane's distance from the actual brush's origin - float flPlaneDist = vecPlaneLocalOrigin.Length(); - - // The target's distance from world origin - plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * plane.AsVector3D()).Length() + flPlaneDist) + 0.1f; + plane.w = + MatrixColumnDotProduct( targetToWorld, 3, plane.AsVector3D() ) // target clip plane distance + - flLocalPlaneDist // portal plane distance on the brush. This distance needs to be accounted for while placing the exit target + - 0.1; CMatRenderContextPtr pRenderContext( materials ); pRenderContext->PushCustomClipPlane( plane.Base() ); diff --git a/sp/src/game/client/viewrender.h b/sp/src/game/client/viewrender.h index 0aa24db6..3ba6cd9f 100644 --- a/sp/src/game/client/viewrender.h +++ b/sp/src/game/client/viewrender.h @@ -454,7 +454,7 @@ private: #ifdef MAPBASE bool DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer, int x, int y, int width, int height, - const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, const Vector &vecPlaneOrigin ); + const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, float flLocalPlaneDist ); #endif // Drawing primitives From 76d981838d2ee6784d773211dbb1e71b4bbcf159 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 21 Nov 2022 00:46:32 -0600 Subject: [PATCH 56/65] Fixed PickupWeaponInstant input crash on Linux --- sp/src/game/server/basecombatcharacter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp/src/game/server/basecombatcharacter.cpp b/sp/src/game/server/basecombatcharacter.cpp index 1f7e5331..7d45ec4e 100644 --- a/sp/src/game/server/basecombatcharacter.cpp +++ b/sp/src/game/server/basecombatcharacter.cpp @@ -4228,7 +4228,7 @@ void CBaseCombatCharacter::InputPickupWeaponInstant( inputdata_t &inputdata ) } else { - Warning("%s received PickupWeaponInstant with invalid entity %s\n", GetDebugName(), inputdata.value.Entity() ? "null" : inputdata.value.Entity()->GetDebugName()); + Warning("%s received PickupWeaponInstant with invalid entity %s\n", GetDebugName(), inputdata.value.Entity() ? inputdata.value.Entity()->GetDebugName() : "<>"); } } From d6f4ea38a2d679ac8481c82cfe6d58ec569952f7 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 21 Nov 2022 00:47:05 -0600 Subject: [PATCH 57/65] Fixed typo in weapon_sniperrifle.cpp --- sp/src/game/server/hl2/weapon_sniperrifle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp/src/game/server/hl2/weapon_sniperrifle.cpp b/sp/src/game/server/hl2/weapon_sniperrifle.cpp index f2939fcc..89887507 100644 --- a/sp/src/game/server/hl2/weapon_sniperrifle.cpp +++ b/sp/src/game/server/hl2/weapon_sniperrifle.cpp @@ -76,7 +76,7 @@ public: void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); -#ifdef MAPBSAE +#ifdef MAPBASE virtual acttable_t *GetBackupActivityList() { return GetAR2Acttable(); } virtual int GetBackupActivityListCount() { return GetAR2ActtableCount(); } #endif From a2e91759e00478ea1e04ee944370a28501a18050 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 21 Nov 2022 00:48:21 -0600 Subject: [PATCH 58/65] Added "DUAL_PISTOLS" as new category of optional unused HL2 weapon activities --- sp/src/game/server/ai_activity.cpp | 38 ++++++++++++++++++++++++++ sp/src/game/shared/activitylist.cpp | 38 ++++++++++++++++++++++++++ sp/src/game/shared/ai_activity.h | 41 ++++++++++++++++++++++++++++- 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/sp/src/game/server/ai_activity.cpp b/sp/src/game/server/ai_activity.cpp index 5362249d..da12eabe 100644 --- a/sp/src/game/server/ai_activity.cpp +++ b/sp/src/game/server/ai_activity.cpp @@ -2462,6 +2462,32 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SNIPER_RIFLE_STIMULATED ); ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SNIPER_RIFLE_STIMULATED ); ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SNIPER_RIFLE_STIMULATED ); + + ADD_ACTIVITY_TO_SR( ACT_IDLE_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_WALK_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_RUN_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_RELOAD_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_DUAL_PISTOLS_LOW ); + ADD_ACTIVITY_TO_SR( ACT_RELOAD_DUAL_PISTOLS_LOW ); + ADD_ACTIVITY_TO_SR( ACT_COVER_DUAL_PISTOLS_LOW ); + ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_DUAL_PISTOLS_LOW ); + ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_DUAL_PISTOLS ); + + ADD_ACTIVITY_TO_SR( ACT_IDLE_DUAL_PISTOLS_RELAXED ); + ADD_ACTIVITY_TO_SR( ACT_IDLE_DUAL_PISTOLS_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_WALK_DUAL_PISTOLS_RELAXED ); + ADD_ACTIVITY_TO_SR( ACT_RUN_DUAL_PISTOLS_RELAXED ); + ADD_ACTIVITY_TO_SR( ACT_WALK_DUAL_PISTOLS_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_RUN_DUAL_PISTOLS_STIMULATED ); + + ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_DUAL_PISTOLS_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_DUAL_PISTOLS_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_DUAL_PISTOLS_STIMULATED ); #endif #if EXPANDED_NAVIGATION_ACTIVITIES @@ -2507,6 +2533,8 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_HMG1_MED ); ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SNIPER_RIFLE_MED ); ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SNIPER_RIFLE_MED ); + ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_DUAL_PISTOLS_MED ); + ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_DUAL_PISTOLS_MED ); #endif ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R ); @@ -2620,6 +2648,16 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SNIPER_RIFLE ); + + ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS ); + ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_DUAL_PISTOLS ); #endif ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_USE ); diff --git a/sp/src/game/shared/activitylist.cpp b/sp/src/game/shared/activitylist.cpp index e8191ed0..0b415d75 100644 --- a/sp/src/game/shared/activitylist.cpp +++ b/sp/src/game/shared/activitylist.cpp @@ -2578,6 +2578,32 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_SNIPER_RIFLE_STIMULATED ); REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_SNIPER_RIFLE_STIMULATED ); REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_SNIPER_RIFLE_STIMULATED ); + + REGISTER_SHARED_ACTIVITY( ACT_IDLE_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_RELOAD_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_DUAL_PISTOLS_LOW ); + REGISTER_SHARED_ACTIVITY( ACT_RELOAD_DUAL_PISTOLS_LOW ); + REGISTER_SHARED_ACTIVITY( ACT_COVER_DUAL_PISTOLS_LOW ); + REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_DUAL_PISTOLS_LOW ); + REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_DUAL_PISTOLS ); + + REGISTER_SHARED_ACTIVITY( ACT_IDLE_DUAL_PISTOLS_RELAXED ); + REGISTER_SHARED_ACTIVITY( ACT_IDLE_DUAL_PISTOLS_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_DUAL_PISTOLS_RELAXED ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_DUAL_PISTOLS_RELAXED ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_DUAL_PISTOLS_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_DUAL_PISTOLS_STIMULATED ); + + REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_DUAL_PISTOLS_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_DUAL_PISTOLS_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_DUAL_PISTOLS_STIMULATED ); #endif #if EXPANDED_NAVIGATION_ACTIVITIES @@ -2623,6 +2649,8 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_HMG1_MED ); REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_SNIPER_RIFLE_MED ); REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SNIPER_RIFLE_MED ); + REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_DUAL_PISTOLS_MED ); + REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_DUAL_PISTOLS_MED ); #endif REGISTER_SHARED_ACTIVITY( ACT_COVER_WALL_R ); @@ -2736,6 +2764,16 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SNIPER_RIFLE ); + + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_RUN_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_CROUCH_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_CROUCH_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS ); + REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_DUAL_PISTOLS ); #endif REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_USE ); diff --git a/sp/src/game/shared/ai_activity.h b/sp/src/game/shared/ai_activity.h index 4cf3ca22..c8bf150a 100644 --- a/sp/src/game/shared/ai_activity.h +++ b/sp/src/game/shared/ai_activity.h @@ -45,7 +45,7 @@ // This enables a bunch of new activities for unused Half-Life 2 weapons, particularly those which exist in the SDK, but are deactivated by default. // This essentially just means mods which restore those weapons have the option of using custom activities for them. // Mapbase's backup activity system would allow them to fall back to other weapons if the relevant activities do not exist. -// Also includes activity names for the "AR3" and "SMG3", which were never used in HL2, but may be useful when additional animation sets are needed. +// Also includes activity names for "AR3", "SMG3", and "DUAL_PISTOLS", which were never used in HL2, but may be useful when additional animation sets are needed. #define EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES 0 // EXPANDED NAVIGATION ACTIVITIES @@ -2478,6 +2478,33 @@ typedef enum ACT_IDLE_AIM_SNIPER_RIFLE_STIMULATED, ACT_WALK_AIM_SNIPER_RIFLE_STIMULATED, ACT_RUN_AIM_SNIPER_RIFLE_STIMULATED, + + // Dual Pistols + ACT_IDLE_DUAL_PISTOLS, + ACT_IDLE_ANGRY_DUAL_PISTOLS, + ACT_WALK_DUAL_PISTOLS, + ACT_RUN_DUAL_PISTOLS, + ACT_WALK_AIM_DUAL_PISTOLS, + ACT_RUN_AIM_DUAL_PISTOLS, + ACT_RANGE_ATTACK_DUAL_PISTOLS, + ACT_RELOAD_DUAL_PISTOLS, + ACT_RANGE_ATTACK_DUAL_PISTOLS_LOW, + ACT_RELOAD_DUAL_PISTOLS_LOW, + ACT_COVER_DUAL_PISTOLS_LOW, + ACT_RANGE_AIM_DUAL_PISTOLS_LOW, + ACT_GESTURE_RANGE_ATTACK_DUAL_PISTOLS, + ACT_GESTURE_RELOAD_DUAL_PISTOLS, + + ACT_IDLE_DUAL_PISTOLS_RELAXED, + ACT_IDLE_DUAL_PISTOLS_STIMULATED, + ACT_WALK_DUAL_PISTOLS_RELAXED, + ACT_RUN_DUAL_PISTOLS_RELAXED, + ACT_WALK_DUAL_PISTOLS_STIMULATED, + ACT_RUN_DUAL_PISTOLS_STIMULATED, + + ACT_IDLE_AIM_DUAL_PISTOLS_STIMULATED, + ACT_WALK_AIM_DUAL_PISTOLS_STIMULATED, + ACT_RUN_AIM_DUAL_PISTOLS_STIMULATED, #endif #if EXPANDED_NAVIGATION_ACTIVITIES @@ -2525,6 +2552,8 @@ typedef enum ACT_RANGE_ATTACK_HMG1_MED, ACT_RANGE_AIM_SNIPER_RIFLE_MED, ACT_RANGE_ATTACK_SNIPER_RIFLE_MED, + ACT_RANGE_AIM_DUAL_PISTOLS_MED, + ACT_RANGE_ATTACK_DUAL_PISTOLS_MED, #endif // Wall Cover (for use in custom cover hints) @@ -2640,6 +2669,16 @@ typedef enum ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE, ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE, ACT_HL2MP_JUMP_SNIPER_RIFLE, + + ACT_HL2MP_IDLE_DUAL_PISTOLS, + ACT_HL2MP_RUN_DUAL_PISTOLS, + ACT_HL2MP_WALK_DUAL_PISTOLS, + ACT_HL2MP_IDLE_CROUCH_DUAL_PISTOLS, + ACT_HL2MP_WALK_CROUCH_DUAL_PISTOLS, + ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS, + ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS, + ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS, + ACT_HL2MP_JUMP_DUAL_PISTOLS, #endif ACT_HL2MP_IDLE_USE, From b2110d035420085cb6042e80e863d86f554f4188 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 21 Nov 2022 00:51:54 -0600 Subject: [PATCH 59/65] Added NPC PVS checking for point_cameras --- sp/src/game/server/ai_basenpc.cpp | 7 ++++ sp/src/game/server/point_camera.cpp | 52 +++++++++++++++++++++++++++++ sp/src/game/server/point_camera.h | 5 +++ 3 files changed, 64 insertions(+) diff --git a/sp/src/game/server/ai_basenpc.cpp b/sp/src/game/server/ai_basenpc.cpp index c503a09c..299aa5c4 100644 --- a/sp/src/game/server/ai_basenpc.cpp +++ b/sp/src/game/server/ai_basenpc.cpp @@ -98,6 +98,7 @@ #ifdef MAPBASE #include "mapbase/matchers.h" #include "items.h" +#include "point_camera.h" #endif #ifdef MAPBASE_VSCRIPT @@ -4301,6 +4302,12 @@ bool CAI_BaseNPC::CheckPVSCondition() { bool bInPVS = ( UTIL_FindClientInPVS( edict() ) != NULL ) || (UTIL_ClientPVSIsExpanded() && UTIL_FindClientInVisibilityPVS( edict() )); +#ifdef MAPBASE + // We can be in a player's PVS if there is an active point_camera nearby (fixes issues with choreo) + if (!bInPVS && UTIL_FindRTCameraInEntityPVS( edict() )) + bInPVS = true; +#endif + if ( bInPVS ) SetCondition( COND_IN_PVS ); else diff --git a/sp/src/game/server/point_camera.cpp b/sp/src/game/server/point_camera.cpp index 626bc61b..72a40b26 100644 --- a/sp/src/game/server/point_camera.cpp +++ b/sp/src/game/server/point_camera.cpp @@ -28,6 +28,58 @@ CPointCamera* GetPointCameraList() return g_PointCameraList.m_pClassList; } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: Returns true if a camera is in the PVS of the specified entity +//----------------------------------------------------------------------------- +edict_t *UTIL_FindRTCameraInEntityPVS( edict_t *pEdict ) +{ + CBaseEntity *pe = GetContainingEntity( pEdict ); + if ( !pe ) + return NULL; + + bool bGotPVS = false; + Vector org; + static byte pvs[ MAX_MAP_CLUSTERS/8 ]; + static int pvssize = sizeof( pvs ); + + for ( CPointCamera *pCameraEnt = GetPointCameraList(); pCameraEnt != NULL; pCameraEnt = pCameraEnt->m_pNext ) + { + if (!pCameraEnt->IsActive()) + continue; + + if (!bGotPVS) + { + // Getting the PVS during the loop like this makes sure we only get the PVS if there's actually an active camera in the level + org = pe->EyePosition(); + int clusterIndex = engine->GetClusterForOrigin( org ); + Assert( clusterIndex >= 0 ); + engine->GetPVSForCluster( clusterIndex, pvssize, pvs ); + bGotPVS = true; + } + + Vector vecCameraEye = pCameraEnt->EyePosition(); + + Vector vecCameraDirection; + pCameraEnt->GetVectors( &vecCameraDirection, NULL, NULL ); + + Vector los = (org - vecCameraEye); + float flDot = DotProduct( los, vecCameraDirection ); + + // Make sure we're in the camera's FOV before checking PVS + if ( flDot <= cos( DEG2RAD( pCameraEnt->GetFOV() / 2 ) ) ) + continue; + + if ( engine->CheckOriginInPVS( vecCameraEye, pvs, pvssize ) ) + { + return pCameraEnt->edict(); + } + } + + return NULL; +} +#endif + // These are already built into CBaseEntity // DEFINE_KEYFIELD( m_iName, FIELD_STRING, "targetname" ), // DEFINE_KEYFIELD( m_iParent, FIELD_STRING, "parentname" ), diff --git a/sp/src/game/server/point_camera.h b/sp/src/game/server/point_camera.h index c669ab82..9cb7d3c4 100644 --- a/sp/src/game/server/point_camera.h +++ b/sp/src/game/server/point_camera.h @@ -42,6 +42,7 @@ public: void InputSetRenderTarget( inputdata_t &inputdata ) { m_iszRenderTarget = inputdata.value.StringID(); } float GetFOV() const { return m_FOV; } + bool IsActive() const { return m_bIsOn; } #endif private: @@ -117,4 +118,8 @@ private: #endif CPointCamera *GetPointCameraList(); + +#ifdef MAPBASE +edict_t *UTIL_FindRTCameraInEntityPVS( edict_t *pEdict ); +#endif #endif // CAMERA_H From 390dd80e41b3b8fd9f570d98bbfcf4113220f7d0 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Mon, 21 Nov 2022 23:24:18 -0600 Subject: [PATCH 60/65] Updated README --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 6bae76ac..26f60a33 100644 --- a/README +++ b/README @@ -135,6 +135,7 @@ Direct contributions: =-- https://github.com/mapbase-source/source-sdk-2013/pull/173 (VScript fixes and optimizations) =-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes) =-- https://github.com/mapbase-source/source-sdk-2013/pull/206 (Fix CScriptNetMsgHelper::WriteEntity()) +=-- https://github.com/mapbase-source/source-sdk-2013/pull/213 (VScript HUD visibility control, optimizations for 3D skybox angles/fake worldportals) == Contributions from z33ky: =-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes) From bbd8d86f87b71e83afb4f63bbc720b2bd7561eff Mon Sep 17 00:00:00 2001 From: Blixibon Date: Tue, 22 Nov 2022 17:14:57 -0600 Subject: [PATCH 61/65] Fix metrocops using the wrong animation when pushing player with a gun --- sp/src/game/server/hl2/npc_metropolice.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sp/src/game/server/hl2/npc_metropolice.cpp b/sp/src/game/server/hl2/npc_metropolice.cpp index 5f6151c4..ed013fa3 100644 --- a/sp/src/game/server/hl2/npc_metropolice.cpp +++ b/sp/src/game/server/hl2/npc_metropolice.cpp @@ -3548,7 +3548,11 @@ Activity CNPC_MetroPolice::NPC_TranslateActivity( Activity newActivity ) // If we're shoving, see if we should be more forceful in doing so if ( newActivity == ACT_PUSH_PLAYER ) { +#ifdef MAPBASE + if ( m_nNumWarnings >= METROPOLICE_MAX_WARNINGS && Weapon_TranslateActivity( ACT_MELEE_ATTACK1, NULL ) == ACT_MELEE_ATTACK_SWING ) +#else if ( m_nNumWarnings >= METROPOLICE_MAX_WARNINGS ) +#endif return ACT_MELEE_ATTACK1; } From 81527d3be8d54e3a7ffa1fc45ec943b536b872b2 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Thu, 24 Nov 2022 12:33:27 -0600 Subject: [PATCH 62/65] Fix mapbase_build-base-dispatch.yml --- .github/workflows/mapbase_build-base-dispatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mapbase_build-base-dispatch.yml b/.github/workflows/mapbase_build-base-dispatch.yml index d29e30d5..d89d151e 100644 --- a/.github/workflows/mapbase_build-base-dispatch.yml +++ b/.github/workflows/mapbase_build-base-dispatch.yml @@ -67,4 +67,4 @@ jobs: game: '${{ github.event.inputs.game }}' project-group: '${{ github.event.inputs.project-group }}' solution-name: '${{ github.event.inputs.solution-name }}' - build-on-linux: '${{ github.event.inputs.build-on-linux }}' + build-on-linux: "${{ github.event.inputs.build-on-linux == 'true' }}" From 9df9233e5459a5ba0f20742556423d084316cdae Mon Sep 17 00:00:00 2001 From: Blixibon Date: Fri, 25 Nov 2022 15:29:45 -0600 Subject: [PATCH 63/65] Fix mapbase_pr.yml causing problems in forks --- .github/workflows/mapbase_pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/mapbase_pr.yml b/.github/workflows/mapbase_pr.yml index 87c2b0e2..c7c6a3e6 100644 --- a/.github/workflows/mapbase_pr.yml +++ b/.github/workflows/mapbase_pr.yml @@ -11,6 +11,7 @@ on: [pull_request] jobs: label: + if: github.repository_owner == 'mapbase-source' runs-on: ubuntu-latest permissions: contents: read From 2fb704a12983989c3fa6d75e2f2bb1b94cd0353a Mon Sep 17 00:00:00 2001 From: "ALLEN-PC\\acj30" Date: Wed, 30 Nov 2022 08:35:31 -0600 Subject: [PATCH 64/65] Updated README --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 26f60a33..6215f047 100644 --- a/README +++ b/README @@ -119,6 +119,7 @@ Direct contributions: - npc_vehicledriver fixes provided by CrAzY - npc_combine cover behavior patches provided by iohnnyboy - logic_playmovie icon created by URAKOLOUY5 (This is asset-based and not reflected in the code) +- Dropship APC save/load fix provided by Cvoxulary == Contributions from samisalreadytaken: =-- https://github.com/mapbase-source/source-sdk-2013/pull/47 (VScript utility/consistency changes) From af6f9fe5185c1425bac6394073c94be723489198 Mon Sep 17 00:00:00 2001 From: "ALLEN-PC\\acj30" Date: Fri, 2 Dec 2022 19:03:29 -0600 Subject: [PATCH 65/65] Added a more concrete Linux exception for Discord RPC --- sp/src/game/client/client_base.vpc | 2 +- sp/src/game/client/client_mapbase.vpc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sp/src/game/client/client_base.vpc b/sp/src/game/client/client_base.vpc index dcdb9ad3..9eae51f1 100644 --- a/sp/src/game/client/client_base.vpc +++ b/sp/src/game/client/client_base.vpc @@ -1261,7 +1261,7 @@ $Project $ImpLib steam_api // Discord integration - $Lib "$LIBPUBLIC\discord-rpc" [$MAPBASE_RPC] + $Lib "$LIBPUBLIC\discord-rpc" [$MAPBASE_RPC&&!$LINUXALL] $Lib $LIBCOMMON/libcrypto [$POSIX] diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index f8860e24..4e604314 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -10,7 +10,7 @@ $Configuration { $PreprocessorDefinitions "$BASE;ASW_PROJECTED_TEXTURES;DYNAMIC_RTT_SHADOWS;GLOWS_ENABLE" - $PreprocessorDefinitions "$BASE;MAPBASE_RPC;DISCORD_RPC;STEAM_RPC" [$MAPBASE_RPC] + $PreprocessorDefinitions "$BASE;MAPBASE_RPC;DISCORD_RPC;STEAM_RPC" [$MAPBASE_RPC&&!$LINUXALL] $PreprocessorDefinitions "$BASE;MAPBASE_VSCRIPT" [$MAPBASE_VSCRIPT] $PreprocessorDefinitions "$BASE;NEW_RESPONSE_SYSTEM" [$NEW_RESPONSE_SYSTEM] }