From c25efd6c7f35d7ee47ea7e6fdd5b7e590966b493 Mon Sep 17 00:00:00 2001 From: tupoy-ya Date: Fri, 6 Oct 2023 12:29:56 +0500 Subject: [PATCH] feat(Portal 2): Implemented `point_changelevel` entities fix(VScript): Now actually works and does not crash. fix(Triggers): Buttons unpress again. fix(Engine Debug Build): Engine now build in debug. chore(Engine): Don't print the "SOLID_VPHYSICS static prop with no vphysics model! (%s)\n" message. --- engine/cmodel.cpp | 2 + engine/staticpropmgr.cpp | 3 - game/server/baseentity.cpp | 120 ++++++++-------- game/server/baseentity.h | 2 +- game/server/cbase.cpp | 98 ++++++-------- game/server/client.cpp | 1 + game/server/entityoutput.h | 10 +- game/server/portal2/point_changelevel.cpp | 92 +++++++++++++ game/server/server_portal.vpc | 1 + game/server/triggers.cpp | 33 ++++- ivp | 2 +- public/vscript/vscript_templates.h | 158 ++++++++++++++++++---- vscript/vscript_squirrel.cpp | 7 +- wscript | 5 +- 14 files changed, 384 insertions(+), 150 deletions(-) create mode 100644 game/server/portal2/point_changelevel.cpp diff --git a/engine/cmodel.cpp b/engine/cmodel.cpp index 02b0497d..e3b11cbd 100644 --- a/engine/cmodel.cpp +++ b/engine/cmodel.cpp @@ -2965,6 +2965,7 @@ bool CM_IsFullyOccluded( const VectorAligned &p0, const VectorAligned &vExtents0 oi.m_traceMaxs.z += vExtentsScaled.z; oi.m_contents = CONTENTS_SOLID | CONTENTS_MOVEABLE; // can solid or moveable be semitransparent? oi.m_pDebugLog = NULL; +/* #ifdef _DEBUG static bool s_bDumpOcclusionPass = false; if ( s_bDumpOcclusionPass ) @@ -2975,6 +2976,7 @@ bool CM_IsFullyOccluded( const VectorAligned &p0, const VectorAligned &vExtents0 oi.m_pDebugLog->ResetPrimCount(); } #endif +*/ return CM_RecursiveOcclusionPass( oi, 0, 0.0f, 1.0f, p0, p1 ); } diff --git a/engine/staticpropmgr.cpp b/engine/staticpropmgr.cpp index fcaafeda..ab72ae52 100644 --- a/engine/staticpropmgr.cpp +++ b/engine/staticpropmgr.cpp @@ -1120,9 +1120,6 @@ void CStaticProp::InsertPropIntoKDTree() } else { - char szModel[MAX_PATH]; - Q_strncpy( szModel, m_pModel ? modelloader->GetName( m_pModel ) : "unknown model", sizeof( szModel ) ); - Warning( "SOLID_VPHYSICS static prop with no vphysics model! (%s)\n", szModel ); m_nSolidType = SOLID_NONE; return; } diff --git a/game/server/baseentity.cpp b/game/server/baseentity.cpp index fed52443..e66879e4 100644 --- a/game/server/baseentity.cpp +++ b/game/server/baseentity.cpp @@ -1346,32 +1346,6 @@ float CBaseEntity::GetMaxOutputDelay( const char *pszOutput ) //} #endif // MAPBASE_VSCRIPT -CBaseEntityOutput *CBaseEntity::FindNamedOutput( const char *pszOutput ) -{ - if ( pszOutput == NULL ) - return NULL; - - datamap_t *dmap = GetDataDescMap(); - while ( dmap ) - { - int fields = dmap->dataNumFields; - for ( int i = 0; i < fields; i++ ) - { - typedescription_t *dataDesc = &dmap->dataDesc[i]; - if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) ) - { - CBaseEntityOutput *pOutput = ( CBaseEntityOutput * )( ( int )this + ( int )dataDesc->fieldOffset[0] ); - if ( !Q_stricmp( dataDesc->externalName, pszOutput ) ) - { - return pOutput; - } - } - } - dmap = dmap->baseMap; - } - return NULL; -} - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -1388,6 +1362,32 @@ void CBaseEntity::FireNamedOutput( const char *pszOutput, variant_t variant, CBa } } +CBaseEntityOutput *CBaseEntity::FindNamedOutput( const char *pszOutput ) +{ + if ( pszOutput == NULL ) + return NULL; + + datamap_t *dmap = GetDataDescMap(); + while ( dmap ) + { + int fields = dmap->dataNumFields; + for ( int i = 0; i < fields; i++ ) + { + typedescription_t *dataDesc = &dmap->dataDesc[i]; + if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) ) + { + CBaseEntityOutput *pOutput = ( CBaseEntityOutput * )( ( intp )this + ( intp )dataDesc->fieldOffset[0] ); + if ( !Q_stricmp( dataDesc->externalName, pszOutput ) ) + { + return pOutput; + } + } + } + dmap = dmap->baseMap; + } + return NULL; +} + void CBaseEntity::Activate( void ) { #ifdef DEBUG @@ -7251,8 +7251,14 @@ bool CBaseEntity::CallScriptFunction(const char* pFunctionName, ScriptVariant_t* if (hFunc) { - m_ScriptScope.Call(hFunc, pFunctionReturn); - m_ScriptScope.ReleaseFunction(hFunc); + // Kind of a hack to make glados.nut easier to work with... + // When a script function is called by connecting the function to an entity output, + // the entity who is connected to the output and who has this function in their scope + // will be set to 'owninginstance'. In this situation, it can be a different instance than 'self'. + g_pScriptVM->SetValue( "owninginstance", ScriptVariant_t( GetScriptInstance() ) ); + m_ScriptScope.Call( hFunc, pFunctionReturn ); + m_ScriptScope.ReleaseFunction( hFunc ); + g_pScriptVM->ClearValue( "owninginstance" ); UPDATE_VMPROFILE @@ -7295,59 +7301,59 @@ bool CBaseEntity::CallScriptFunctionHandle(HSCRIPT hFunc, ScriptVariant_t* pFunc //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void CBaseEntity::ConnectOutputToScript(const char* pszOutput, const char* pszScriptFunc) +void CBaseEntity::ConnectOutputToScript( const char *pszOutput, const char *pszScriptFunc ) { - CBaseEntityOutput* pOutput = FindNamedOutput(pszOutput); - if (!pOutput) + CBaseEntityOutput *pOutput = FindNamedOutput( pszOutput ); + if ( !pOutput ) { - DevMsg(2, "Script failed to find output \"%s\"\n", pszOutput); + DevMsg( 2, "Script failed to find output \"%s\"\n", pszOutput ); return; } - string_t iszSelf = AllocPooledString("!self"); // @TODO: cache this [4/25/2008 tom] - CEventAction* pAction = pOutput->GetActionList(); - while (pAction) + string_t iszSelf = AllocPooledString( "!self" ); // @TODO: cache this [4/25/2008 tom] + CEventAction *pAction = pOutput->GetFirstAction(); + while ( pAction ) { - if (pAction->m_iTarget == iszSelf && - pAction->m_flDelay == 0 && - pAction->m_nTimesToFire == EVENT_FIRE_ALWAYS && - V_strcmp(STRING(pAction->m_iTargetInput), "CallScriptFunction") == 0 && - V_strcmp(STRING(pAction->m_iParameter), pszScriptFunc) == 0) + if ( pAction->m_iTarget == iszSelf && + pAction->m_flDelay == 0 && + pAction->m_nTimesToFire == EVENT_FIRE_ALWAYS && + V_strcmp( STRING(pAction->m_iTargetInput), "CallScriptFunction" ) == 0 && + V_strcmp( STRING(pAction->m_iParameter), pszScriptFunc ) == 0 ) { return; } pAction = pAction->m_pNext; } - pAction = new CEventAction(NULL); + pAction = new CEventAction( NULL ); pAction->m_iTarget = iszSelf; - pAction->m_iTargetInput = AllocPooledString("CallScriptFunction"); - pAction->m_iParameter = AllocPooledString(pszScriptFunc); - pOutput->AddEventAction(pAction); + pAction->m_iTargetInput = AllocPooledString( "CallScriptFunction" ); + pAction->m_iParameter = AllocPooledString( pszScriptFunc ); + pOutput->AddEventAction( pAction ); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void CBaseEntity::DisconnectOutputFromScript(const char* pszOutput, const char* pszScriptFunc) +void CBaseEntity::DisconnectOutputFromScript( const char *pszOutput, const char *pszScriptFunc ) { - CBaseEntityOutput* pOutput = FindNamedOutput(pszOutput); - if (!pOutput) + CBaseEntityOutput *pOutput = FindNamedOutput( pszOutput ); + if ( !pOutput ) { - DevMsg(2, "Script failed to find output \"%s\"\n", pszOutput); + DevMsg( 2, "Script failed to find output \"%s\"\n", pszOutput ); return; } - string_t iszSelf = AllocPooledString("!self"); // @TODO: cache this [4/25/2008 tom] - CEventAction* pAction = pOutput->GetActionList(); - while (pAction) + string_t iszSelf = AllocPooledString( "!self" ); // @TODO: cache this [4/25/2008 tom] + CEventAction *pAction = pOutput->GetFirstAction(); + while ( pAction ) { - if (pAction->m_iTarget == iszSelf && - pAction->m_flDelay == 0 && - pAction->m_nTimesToFire == EVENT_FIRE_ALWAYS && - V_strcmp(STRING(pAction->m_iTargetInput), "CallScriptFunction") == 0 && - V_strcmp(STRING(pAction->m_iParameter), pszScriptFunc) == 0) + if ( pAction->m_iTarget == iszSelf && + pAction->m_flDelay == 0 && + pAction->m_nTimesToFire == EVENT_FIRE_ALWAYS && + V_strcmp( STRING(pAction->m_iTargetInput), "CallScriptFunction" ) == 0 && + V_strcmp( STRING(pAction->m_iParameter), pszScriptFunc ) == 0 ) { - pOutput->RemoveEventAction(pAction); + pOutput->RemoveEventAction( pAction ); delete pAction; return; } diff --git a/game/server/baseentity.h b/game/server/baseentity.h index 974064e2..e899195d 100644 --- a/game/server/baseentity.h +++ b/game/server/baseentity.h @@ -2948,7 +2948,7 @@ inline const char* CBaseEntity::ScriptGetModelName(void) const do \ { \ m_pfnMoveDone = static_cast (a); \ - FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnMoveDone)))), "BaseMoveFunc" ); \ + FunctionCheck( * (inputfunc_t *)(((char *)this + ( offsetof(CBaseEntity,m_pfnMoveDone)))), "BaseMoveFunc" ); \ } while ( 0 ) #else #define SetMoveDone( a ) \ diff --git a/game/server/cbase.cpp b/game/server/cbase.cpp index 27953a71..cbc0a120 100644 --- a/game/server/cbase.cpp +++ b/game/server/cbase.cpp @@ -1,10 +1,4 @@ //========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// /* Entity Data Descriptions @@ -71,6 +65,7 @@ OUTPUTS: of an entity changes it will often fire off outputs so that map makers can hook up behaviors. e.g. A door entity would have OnDoorOpen, OnDoorClose, OnTouched, etc outputs. */ +//============================================================================= #include "cbase.h" @@ -192,6 +187,18 @@ CEventAction::CEventAction( const char *ActionData ) } } +CEventAction::CEventAction( const CEventAction &p_EventAction ) +{ + m_pNext = NULL; + m_iIDStamp = ++s_iNextIDStamp; + + m_flDelay = p_EventAction.m_flDelay; + m_iTarget = p_EventAction.m_iTarget; + m_iParameter = p_EventAction.m_iParameter; + m_iTargetInput = p_EventAction.m_iTargetInput; + m_nTimesToFire = p_EventAction.m_nTimesToFire; +} + // this memory pool stores blocks around the size of CEventAction/inputitem_t structs // can be used for other blocks; will error if to big a block is tried to be allocated @@ -289,45 +296,22 @@ void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBa #endif } - if ( ev->m_flDelay ) + if ( developer.GetBool() ) { - char szBuffer[256]; - Q_snprintf( szBuffer, - sizeof(szBuffer), - "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", -#ifdef TF_DLL - engine->GetServerTime(), -#else - gpGlobals->curtime, -#endif - pCaller ? STRING(pCaller->m_iClassname) : "NULL", - pCaller ? STRING(pCaller->GetEntityName()) : "NULL", - STRING(ev->m_iTarget), - STRING(ev->m_iTargetInput), - ev->m_flDelay, - STRING(ev->m_iParameter) ); - - CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); - } - else - { - char szBuffer[256]; - Q_snprintf( szBuffer, - sizeof(szBuffer), - "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", -#ifdef TF_DLL - engine->GetServerTime(), -#else - gpGlobals->curtime, -#endif - pCaller ? STRING(pCaller->m_iClassname) : "NULL", - pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), - STRING(ev->m_iTargetInput), - STRING(ev->m_iParameter) ); - - CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); + if ( ev->m_flDelay ) + { + char szBuffer[256]; + Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ev->m_flDelay, STRING(ev->m_iParameter) ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); + ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); + } + else + { + char szBuffer[256]; + Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), STRING(ev->m_iParameter) ); + CGMsg( 2, CON_GROUP_IO_SYSTEM, "%s", szBuffer ); + ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); + } } if ( pCaller && pCaller->m_debugOverlays & OVERLAY_MESSAGE_BIT) @@ -404,7 +388,7 @@ void CBaseEntityOutput::AddEventAction( CEventAction *pEventAction ) void CBaseEntityOutput::RemoveEventAction( CEventAction *pEventAction ) { - CEventAction *pAction = GetActionList(); + CEventAction *pAction = GetFirstAction(); CEventAction *pPrevAction = NULL; while ( pAction ) { @@ -483,6 +467,17 @@ int CBaseEntityOutput::Restore( IRestore &restore, int elementCount ) return 1; } +const CEventAction *CBaseEntityOutput::GetActionForTarget( string_t iSearchTarget ) const +{ + for ( CEventAction *ev = m_ActionList; ev != NULL; ev = ev->m_pNext ) + { + if ( ev->m_iTarget == iSearchTarget ) + return ev; + } + + return NULL; +} + int CBaseEntityOutput::NumberOfElements( void ) { int count = 0; @@ -1139,7 +1134,7 @@ void CEventQueue::CancelEventOn( CBaseEntity *pTarget, const char *sInputName ) bool bDelete = false; if (pCur->m_pEntTarget == pTarget) { - if ( !Q_strncmp( STRING(pCur->m_iTargetInput), sInputName, strlen(sInputName) ) ) + if ( StringHasPrefixCaseSensitive( STRING(pCur->m_iTargetInput), sInputName ) ) { // Found a matching event; delete it from the queue. bDelete = true; @@ -1176,7 +1171,7 @@ bool CEventQueue::HasEventPending( CBaseEntity *pTarget, const char *sInputName if ( !sInputName ) return true; - if ( !Q_strncmp( STRING(pCur->m_iTargetInput), sInputName, strlen(sInputName) ) ) + if ( StringHasPrefixCaseSensitive( STRING(pCur->m_iTargetInput), sInputName ) ) return true; } @@ -1727,8 +1722,6 @@ bool variant_t::Convert( fieldtype_t newType, CBaseEntity *pSelf, CBaseEntity *p //----------------------------------------------------------------------------- const char *variant_t::ToString( void ) const { - COMPILE_TIME_ASSERT( sizeof(string_t) == sizeof(intp) ); - static char szBuf[512]; switch (fieldType) @@ -1783,12 +1776,7 @@ const char *variant_t::ToString( void ) const case FIELD_EHANDLE: { -#ifdef MAPBASE - // This is a really bad idea. - const char *pszName = (Entity()) ? Entity()->GetDebugName() : "<>"; -#else const char *pszName = (Entity()) ? STRING(Entity()->GetEntityName()) : "<>"; -#endif Q_strncpy( szBuf, pszName, 512 ); return (szBuf); } @@ -1845,6 +1833,7 @@ typedescription_t variant_t::m_SaveVector[] = { // Just here to shut up ClassCheck // DEFINE_ARRAY( vecVal, FIELD_FLOAT, 3 ), +// DEFINE_FIELD( vecSave, FIELD_CLASSCHECK_IGNORE ) // do this or else we get a warning about multiply-defined fields DEFINE_FIELD( vecSave, FIELD_VECTOR ), }; @@ -1861,6 +1850,7 @@ struct variant_savevmatrix_t }; typedescription_t variant_t::m_SaveVMatrix[] = { +// DEFINE_FIELD( matSave, FIELD_CLASSCHECK_IGNORE ) // do this or else we get a warning about multiply-defined fields DEFINE_FIELD( matSave, FIELD_VMATRIX ), }; typedescription_t variant_t::m_SaveVMatrixWorldspace[] = diff --git a/game/server/client.cpp b/game/server/client.cpp index 8b041748..9c5fa819 100644 --- a/game/server/client.cpp +++ b/game/server/client.cpp @@ -35,6 +35,7 @@ #include "datacache/imdlcache.h" #include "basemultiplayerplayer.h" #include "voice_gamemgr.h" +#include "tier1/fmtstr.h" #ifdef TF_DLL #include "tf_player.h" diff --git a/game/server/entityoutput.h b/game/server/entityoutput.h index f150a954..d9357f30 100644 --- a/game/server/entityoutput.h +++ b/game/server/entityoutput.h @@ -29,6 +29,7 @@ class CEventAction { public: CEventAction( const char *ActionData = NULL ); + CEventAction( const CEventAction &p_EventAction ); string_t m_iTarget; // name of the entity(s) to cause the action in string_t m_iTargetInput; // the name of the action to fire @@ -79,10 +80,9 @@ public: /// Delete every single action in the action list. void DeleteAllElements( void ) ; - // Needed for ReplaceOutput, hopefully not bad - CEventAction *GetActionList() { return m_ActionList; } - void SetActionList(CEventAction *newlist) { m_ActionList = newlist; } + CEventAction *GetFirstAction() { return m_ActionList; } + const CEventAction *GetActionForTarget( string_t iSearchTarget ) const; protected: variant_t m_Value; CEventAction *m_ActionList; @@ -133,7 +133,7 @@ public: // Template specializations for type Vector, so we can implement Get, Set, and Init differently. // template<> -class CEntityOutputTemplate : public CBaseEntityOutput +class CEntityOutputTemplate< Vector, FIELD_VECTOR> : public CBaseEntityOutput { public: void Init( const Vector &value ) @@ -178,7 +178,7 @@ public: template<> -class CEntityOutputTemplate : public CBaseEntityOutput +class CEntityOutputTemplate< Vector, FIELD_POSITION_VECTOR> : public CBaseEntityOutput { public: void Init( const Vector &value ) diff --git a/game/server/portal2/point_changelevel.cpp b/game/server/portal2/point_changelevel.cpp new file mode 100644 index 00000000..44135d47 --- /dev/null +++ b/game/server/portal2/point_changelevel.cpp @@ -0,0 +1,92 @@ +//===== Copyright Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// + +#include "cbase.h" +#include "eventqueue.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" +//----------------------------------------------------------------------------- +// Context think +//----------------------------------------------------------------------------- + +#define cchMapNameMost 32 + +static char szDestinationMap[cchMapNameMost]; +static char szOriginMap[cchMapNameMost]; + +static ConVar sv_transition_fade_time( "sv_transition_fade_time", "0.5", FCVAR_DEVELOPMENTONLY); + +class CPointChangelevel : public CPointEntity +{ +public: + DECLARE_CLASS( CPointChangelevel, CPointEntity ); + DECLARE_DATADESC(); + + virtual void InputChangeLevel( inputdata_t& inputdata ); + virtual void InputChangeLevelPostFade( inputdata_t& inputdata ); + +private: + COutputEvent m_OnChangeLevel; +}; + +LINK_ENTITY_TO_CLASS( point_changelevel, CPointChangelevel ); + +BEGIN_DATADESC( CPointChangelevel ) + + DEFINE_OUTPUT( m_OnChangeLevel, "OnChangeLevel" ), + DEFINE_INPUTFUNC ( FIELD_STRING, "ChangeLevel", InputChangeLevel ), + DEFINE_INPUTFUNC ( FIELD_STRING, "ChangeLevelPostFade", InputChangeLevelPostFade ), + +END_DATADESC() + +void CPointChangelevel::InputChangeLevel( inputdata_t& inputdata ) +{ + float fade_time = sv_transition_fade_time.GetFloat(); + + g_EventQueue.AddEvent((CBaseEntity*)this, "ChangeLevelPostFade", inputdata.value, fade_time, inputdata.pActivator ,inputdata.pCaller ,inputdata.nOutputID ); +} + +void CPointChangelevel::InputChangeLevelPostFade( inputdata_t& inputdata ) +{ + m_OnChangeLevel.FireOutput(inputdata.pActivator, this, 0.0f); + const char* current_map = gpGlobals->mapname.ToCStr(); + + if(current_map == NULL) + current_map = ""; + + V_strncpy(szOriginMap, current_map, 32); + + const char* next_map; + next_map = inputdata.value.String(); + if(next_map == NULL) + next_map = ""; + V_strncpy(szDestinationMap, next_map, 32); + + engine->ChangeLevel(szDestinationMap, NULL); +} + +const char *ChangeLevel_DestinationMapName( void ) +{ + return szDestinationMap; +} +const char *ChangeLevel_OriginMapName( void ) +{ + return szDestinationMap; +} +const char *ChangeLevel_GetLandmarkName( void ) +{ + return "__p2_landmark"; +} + +class CInfoLandMark : public CPointEntity +{ +public: + DECLARE_CLASS( CInfoLandMark, CPointEntity ); +}; + +LINK_ENTITY_TO_CLASS( info_landmark_entry, CInfoLandMark ); +LINK_ENTITY_TO_CLASS( info_landmark_exit, CInfoLandMark ); diff --git a/game/server/server_portal.vpc b/game/server/server_portal.vpc index aa015c08..7b903c95 100644 --- a/game/server/server_portal.vpc +++ b/game/server/server_portal.vpc @@ -364,6 +364,7 @@ $Project "Server (Portal)" $File "portal2\prop_testchamber_door.cpp" $File "portal2\prop_floor_button.cpp" $File "portal2\prop_button.cpp" + $File "portal2\point_changelevel.cpp" $File "movie_display.cpp" diff --git a/game/server/triggers.cpp b/game/server/triggers.cpp index 10b20177..65a8df22 100644 --- a/game/server/triggers.cpp +++ b/game/server/triggers.cpp @@ -42,6 +42,12 @@ #include "ai_hint.h" #endif +#ifdef PORTAL2 +extern const char *ChangeLevel_DestinationMapName( void ); +extern const char *ChangeLevel_OriginMapName( void ); +extern const char *ChangeLevel_GetLandmarkName( void ); +#endif // PORTAL2 + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -581,7 +587,7 @@ void CBaseTrigger::EndTouch(CBaseEntity *pOther) // Didn't find one? if ( !bFoundOtherTouchee /*&& !m_bDisabled*/ ) { - m_OnEndTouchAll.FireOutput(pOther, this); + OnEndTouchAll( pOther ); } } } @@ -2031,6 +2037,31 @@ int CChangeLevel::InTransitionVolume( CBaseEntity *pEntity, const char *pVolumeN //------------------------------------------------------------------------------ int CChangeLevel::BuildChangeLevelList( levellist_t *pLevelList, int maxList ) { +#ifdef PORTAL2 + + // Get our origin and destination names + const char *lpszDestMapName = ChangeLevel_DestinationMapName(); + const char *lpszOriginMapName = ChangeLevel_OriginMapName(); + + // If these names are valid, we're opting into the streamlined level transition system + if ( lpszOriginMapName != NULL && lpszOriginMapName[0] != NULL && lpszDestMapName != NULL && lpszDestMapName[0] != NULL ) + { + // Because this is called symmetrically on both sides of the transition, we need to infer from the names which side we're on + bool bAtDestination = !Q_stricmp( STRING(gpGlobals->mapname), lpszDestMapName ); + + // Find a landmark on this end of the transition to refer to + CBaseEntity *pentLandmark = gEntList.FindEntityByClassname( NULL, (bAtDestination) ? "info_landmark_entry" : "info_landmark_exit" ); + if ( pentLandmark ) + { + // Landmarks are all named the same thing, we only allow one entry and one exit per level + const char *lpszLandmarkName = ChangeLevel_GetLandmarkName(); + if ( AddTransitionToList( pLevelList, 0, (bAtDestination) ? lpszOriginMapName : lpszDestMapName, lpszLandmarkName, pentLandmark->edict() ) ) + return 1; // Only one way to go + } + } + +#endif + int nCount = 0; CBaseEntity *pentChangelevel = gEntList.FindEntityByClassname( NULL, "trigger_changelevel" ); diff --git a/ivp b/ivp index 960c7228..4098acbb 160000 --- a/ivp +++ b/ivp @@ -1 +1 @@ -Subproject commit 960c7228f8e8d710625891991e88b1ec3aa92e45 +Subproject commit 4098acbbe3bc48320496f7533851640cc40cbb89 diff --git a/public/vscript/vscript_templates.h b/public/vscript/vscript_templates.h index 7368e701..f2664606 100644 --- a/public/vscript/vscript_templates.h +++ b/public/vscript/vscript_templates.h @@ -73,10 +73,63 @@ FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER ); //----------------------------------------------------------------------------- template -inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) +inline void* ScriptConvertFreeFuncPtrToVoid( FUNCPTR_TYPE pFunc ) { +#if defined(_PS3) || defined(POSIX) + COMPILE_TIME_ASSERT( sizeof( FUNCPTR_TYPE ) == sizeof( void* ) * 2 || sizeof( FUNCPTR_TYPE ) == sizeof( void* ) ); + + if ( sizeof( FUNCPTR_TYPE ) == 4 ) + { + union FuncPtrConvertMI + { + FUNCPTR_TYPE pFunc; + void* stype; + }; + + FuncPtrConvertMI convert; + convert.pFunc = pFunc; + return convert.stype; + } + else + { + union FuncPtrConvertMI + { + FUNCPTR_TYPE pFunc; + struct + { + void* stype; + intptr_t iToc; + } fn8; + }; + + FuncPtrConvertMI convert; + convert.fn8.iToc = 0; + convert.pFunc = pFunc; + if ( !convert.fn8.iToc ) + return convert.fn8.stype; + + Assert( 0 ); + DebuggerBreak(); + return 0; + } +#else + return ( void* ) pFunc; +#endif +} + +template +inline void* ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) +{ + typedef FUNCPTR_TYPE FuncPtr_t; + size_t funcPtrSize = sizeof( FuncPtr_t ); funcPtrSize; + +#if defined(_PS3) || defined(POSIX) + return ScriptConvertFreeFuncPtrToVoid( pFunc ); +#else + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) ) { + // simple inheritance union FuncPtrConvert { void *p; @@ -87,9 +140,11 @@ inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) convert.pFunc = pFunc; return convert.p; } -#if defined( _MSC_VER ) - else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) +#if MSVC + else if ( ( IsPlatformWindowsPC32() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) || + ( IsPlatformWindowsPC64() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) * 2 ) ) ) { + // multiple and virtual inheritance struct MicrosoftUnknownMFP { void *p; @@ -110,8 +165,10 @@ inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) } AssertMsg( 0, "Function pointer must be from primary vtable" ); } - else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) + else if ( ( IsPlatformWindowsPC32() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) || + ( IsPlatformWindowsPC64() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 4 ) ) ) ) { + // unknown_inheritance case struct MicrosoftUnknownMFP { void *p; @@ -137,25 +194,29 @@ inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) #elif defined( GNUC ) else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) { + AssertMsg( 0, "Note: This path has not been verified yet. See comments below in #else case." ); + struct GnuMFP { union { void *funcadr; // If vtable_index_2 is even, then this is the function pointer. - int vtable_index_2; // If vtable_index_2 is odd, then (vtable_index_2 - 1) * 2 is the index into the vtable. + int vtable_index_2; // If vtable_index_2 is odd, then this = vindex*2+1. }; - int delta; // Offset from this-ptr to vtable + int delta; }; - + GnuMFP *p = (GnuMFP*)&pFunc; - if ( p->delta == 0 ) + if ( p->vtable_index_2 & 1 ) + { + char **delta = (char**)p->delta; + char *pCur = *delta + (p->vtable_index_2+1)/2; + return (void*)( pCur + 4 ); + } + else { - // No need to check whether this is a direct function pointer or not, - // this gets converted back to a "proper" member-function pointer in - // ScriptConvertFuncPtrFromVoid() to get invoked return p->funcadr; } - AssertMsg( 0, "Function pointer must be from primary vtable" ); } #else #error "Need to implement code to crack non-offset member function pointer case" @@ -194,11 +255,59 @@ inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) else AssertMsg( 0, "Member function pointer not supported. Why on earth are you using virtual inheritance!?" ); return NULL; +#endif +} + +template +inline FUNCPTR_TYPE ScriptConvertFreeFuncPtrFromVoid( void* p ) +{ +#if defined(_PS3) || defined(POSIX) + COMPILE_TIME_ASSERT( sizeof( FUNCPTR_TYPE ) == sizeof(void*)*2 || sizeof( FUNCPTR_TYPE ) == sizeof(void*) ); + + if ( sizeof( FUNCPTR_TYPE ) == 4 ) + { + union FuncPtrConvertMI + { + FUNCPTR_TYPE pFunc; + void* stype; + }; + + FuncPtrConvertMI convert; + convert.pFunc = 0; + convert.stype = p; + return convert.pFunc; + } + else + { + union FuncPtrConvertMI + { + FUNCPTR_TYPE pFunc; + struct + { + void* stype; + intptr_t iToc; + } fn8; + }; + + FuncPtrConvertMI convert; + convert.pFunc = 0; + convert.fn8.stype = p; + convert.fn8.iToc = 0; + return convert.pFunc; + } + + +#else + return (FUNCPTR_TYPE) p; +#endif } template inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) { +#if defined(_PS3) || defined(POSIX) + return ScriptConvertFreeFuncPtrFromVoid( p ); +#else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) ) { union FuncPtrConvert @@ -277,11 +386,14 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) convert.mfp.delta = 0; return convert.pFunc; } +#elif defined( POSIX ) + AssertMsg( 0, "Note: This path has not been implemented yet." ); #else #error "Need to implement code to crack non-offset member function pointer case" #endif Assert( 0 ); return NULL; +#endif } //----------------------------------------------------------------------------- @@ -326,18 +438,17 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) class CNonMemberScriptBinding##N \ { \ public: \ - static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + static bool Call( void* pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ { \ Assert( nArguments == N ); \ Assert( pReturn ); \ Assert( !pContext ); \ - Assert( pFunction ); \ \ - if ( nArguments != N || pReturn || !pContext || !pFunction ) \ + if ( nArguments != N || !pReturn || pContext || !pFunction ) \ { \ return false; \ } \ - *pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \ + *pReturn = (ScriptConvertFreeFuncPtrFromVoid(pFunction))( SCRIPT_BINDING_ARGS_##N ); \ if ( pReturn->m_type == FIELD_VECTOR ) \ pReturn->m_pVector = new Vector(*pReturn->m_pVector); \ return true; \ @@ -348,18 +459,17 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) class CNonMemberScriptBinding##N \ { \ public: \ - static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + static bool Call( void* pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ { \ Assert( nArguments == N ); \ Assert( !pReturn ); \ Assert( !pContext ); \ - Assert( pFunction ); \ \ - if ( nArguments != N || pReturn || !pContext || !pFunction ) \ + if ( nArguments != N || pReturn || pContext || !pFunction ) \ { \ return false; \ } \ - ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \ + (ScriptConvertFreeFuncPtrFromVoid(pFunction))( SCRIPT_BINDING_ARGS_##N ); \ return true; \ } \ }; \ @@ -368,14 +478,13 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) class CMemberScriptBinding##N \ { \ public: \ - static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + static bool Call( void* pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ { \ Assert( nArguments == N ); \ Assert( pReturn ); \ Assert( pContext ); \ - Assert( pFunction ); \ \ - if ( nArguments != N || pReturn || !pContext || !pFunction ) \ + if ( nArguments != N || !pReturn || !pContext || !pFunction ) \ { \ return false; \ } \ @@ -390,12 +499,11 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) class CMemberScriptBinding##N \ { \ public: \ - static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + static bool Call( void* pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ { \ Assert( nArguments == N ); \ Assert( !pReturn ); \ Assert( pContext ); \ - Assert( pFunction ); \ \ if ( nArguments != N || pReturn || !pContext || !pFunction ) \ { \ diff --git a/vscript/vscript_squirrel.cpp b/vscript/vscript_squirrel.cpp index 5efb2314..a29f7eac 100644 --- a/vscript/vscript_squirrel.cpp +++ b/vscript/vscript_squirrel.cpp @@ -1403,8 +1403,11 @@ SQInteger function_stub(HSQUIRRELVM vm) sq_resetobject(&pSquirrelVM->lastError_); - (*pFunc->m_pfnBinding)(pFunc->m_pFunction, instance, params.Base(), nargs, - pFunc->m_desc.m_ReturnType == FIELD_VOID ? nullptr : &retval); + if(pFunc->m_pFunction) + { + (*pFunc->m_pfnBinding)(pFunc->m_pFunction, instance, params.Base(), nargs, + pFunc->m_desc.m_ReturnType == FIELD_VOID ? nullptr : &retval); + } if (!sq_isnull(pSquirrelVM->lastError_)) { diff --git a/wscript b/wscript index c7c30d61..e49d3861 100644 --- a/wscript +++ b/wscript @@ -442,7 +442,7 @@ def configure(conf): compiler_optional_flags = ['-w'] else: compiler_optional_flags = [ - '-Wall', + # '-Wall', '-fdiagnostics-color=always', '-Wcast-align', '-Wuninitialized', @@ -454,6 +454,9 @@ def configure(conf): '-Wno-unused-but-set-variable', '-Wno-unused-value', '-Wno-unused-variable', + '-Wno-sign-compare', + '-Wno-class-memaccess', + '-Wno-write-strings', '-faligned-new', ]