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.
This commit is contained in:
tupoy-ya 2023-10-06 12:29:56 +05:00
parent bba4bb4625
commit c25efd6c7f
No known key found for this signature in database
GPG Key ID: 3541E2B1B448A2DB
14 changed files with 384 additions and 150 deletions

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -2948,7 +2948,7 @@ inline const char* CBaseEntity::ScriptGetModelName(void) const
do \
{ \
m_pfnMoveDone = static_cast <void (CBaseEntity::*)(void)> (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 ) \

View File

@ -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() : "<<null entity>>";
#else
const char *pszName = (Entity()) ? STRING(Entity()->GetEntityName()) : "<<null entity>>";
#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[] =

View File

@ -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"

View File

@ -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<class Vector, FIELD_VECTOR> : public CBaseEntityOutput
class CEntityOutputTemplate< Vector, FIELD_VECTOR> : public CBaseEntityOutput
{
public:
void Init( const Vector &value )
@ -178,7 +178,7 @@ public:
template<>
class CEntityOutputTemplate<class Vector, FIELD_POSITION_VECTOR> : public CBaseEntityOutput
class CEntityOutputTemplate< Vector, FIELD_POSITION_VECTOR> : public CBaseEntityOutput
{
public:
void Init( const Vector &value )

View File

@ -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 );

View File

@ -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"

View File

@ -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" );

2
ivp

@ -1 +1 @@
Subproject commit 960c7228f8e8d710625891991e88b1ec3aa92e45
Subproject commit 4098acbbe3bc48320496f7533851640cc40cbb89

View File

@ -73,10 +73,63 @@ FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER );
//-----------------------------------------------------------------------------
template <typename FUNCPTR_TYPE>
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 <typename FUNCPTR_TYPE>
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<FUNCPTR_TYPE>( 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 <typename FUNCPTR_TYPE>
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 <typename FUNCPTR_TYPE>
inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
{
#if defined(_PS3) || defined(POSIX)
return ScriptConvertFreeFuncPtrFromVoid<FUNCPTR_TYPE>( 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<FUNC_TYPE>(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<FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##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<FUNC_TYPE>(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<OBJECT_TYPE_PTR, FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##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 ) \
{ \

View File

@ -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_))
{

View File

@ -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',
]