Added trigger teleport prediction
This commit is contained in:
parent
186b8c046d
commit
340eeb7e03
10 changed files with 232 additions and 19 deletions
|
@ -365,6 +365,12 @@ BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_PredictableId )
|
|||
END_RECV_TABLE()
|
||||
#endif
|
||||
|
||||
void RecvProxy_Name(const CRecvProxyData *pData, void *pStruct, void *pOut)
|
||||
{
|
||||
C_BaseEntity *entity = (C_BaseEntity *) pStruct;
|
||||
|
||||
Q_strncpy( entity->m_iName, pData->m_Value.m_pString, MAX_PATH );
|
||||
}
|
||||
|
||||
BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
|
||||
RecvPropDataTable( "AnimTimeMustBeFirst", 0, 0, &REFERENCE_RECV_TABLE(DT_AnimTimeMustBeFirst) ),
|
||||
|
@ -398,7 +404,7 @@ BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
|
|||
RecvPropInt( RECVINFO( m_iParentAttachment ) ),
|
||||
|
||||
// Receive the name
|
||||
RecvPropString(RECVINFO(m_iName)),
|
||||
RecvPropString(RECVINFO(m_iName), NULL, RecvProxy_Name),
|
||||
|
||||
RecvPropInt( "movetype", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveType ),
|
||||
RecvPropInt( "movecollide", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveCollide ),
|
||||
|
|
|
@ -175,6 +175,7 @@ $Project
|
|||
$File "css_enhanced\c_triggers_base.cpp"
|
||||
$File "css_enhanced\c_triggers.cpp"
|
||||
$File "css_enhanced\c_trigger_push.cpp"
|
||||
$File "css_enhanced\c_trigger_teleport.cpp"
|
||||
$File "css_enhanced\variant_t.cpp"
|
||||
$File "hl2\C_Func_Monitor.cpp"
|
||||
$File "geiger.cpp"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "cbase.h"
|
||||
#include "datamap.h"
|
||||
#include "dt_recv.h"
|
||||
#include "util_shared.h"
|
||||
#include "c_trigger_push.h"
|
||||
|
||||
|
@ -8,16 +9,14 @@
|
|||
|
||||
LINK_ENTITY_TO_CLASS( trigger_push, C_TriggerPush );
|
||||
|
||||
BEGIN_PREDICTION_DATA(C_TriggerPush)
|
||||
DEFINE_PRED_FIELD(m_vecPushDir, FIELD_VECTOR, FTYPEDESC_INSENDTABLE),
|
||||
DEFINE_PRED_FIELD(m_flAlternateTicksFix, FIELD_FLOAT, FTYPEDESC_INSENDTABLE),
|
||||
DEFINE_PRED_FIELD(m_flPushSpeed, FIELD_FLOAT, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_ARRAY(m_hPredictedTouchingEntities, FIELD_EHANDLE, MAX_EDICTS, FTYPEDESC_PRIVATE),
|
||||
// DEFINE_PRED_FIELD(m_iCountPredictedTouchingEntities, FIELD_INTEGER, FTYPEDESC_PRIVATE)
|
||||
END_PREDICTION_DATA();
|
||||
|
||||
// Since this is called only during creation
|
||||
// we allow a small margin for prediction errors here
|
||||
BEGIN_PREDICTION_DATA(C_TriggerPush)
|
||||
// DEFINE_PRED_FIELD(m_vecPushDir, FIELD_VECTOR, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_FIELD(m_flAlternateTicksFix, FIELD_FLOAT, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_FIELD(m_flPushSpeed, FIELD_FLOAT, FTYPEDESC_INSENDTABLE),
|
||||
END_PREDICTION_DATA();
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_TriggerPush, DT_TriggerPush, CTriggerPush)
|
||||
RecvPropVector(RECVINFO(m_vecPushDir)),
|
||||
RecvPropFloat(RECVINFO(m_flAlternateTicksFix)),
|
||||
|
|
152
game/client/css_enhanced/c_trigger_teleport.cpp
Normal file
152
game/client/css_enhanced/c_trigger_teleport.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
#include "cbase.h"
|
||||
#include "c_baseplayer.h"
|
||||
#include "datamap.h"
|
||||
#include "dt_recv.h"
|
||||
#include "entitylist_base.h"
|
||||
#include "predictable_entity.h"
|
||||
#include "util_shared.h"
|
||||
#include "c_trigger_teleport.h"
|
||||
#include "prediction.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS(trigger_teleport, C_TriggerTeleport);
|
||||
|
||||
// TODO_ENHANCED: what to do if m_iLandmark changes?
|
||||
BEGIN_PREDICTION_DATA(C_TriggerTeleport)
|
||||
// DEFINE_PRED_FIELD(m_iLandmark, FIELD_STRING, FTYPEDESC_INSENDTABLE),
|
||||
END_PREDICTION_DATA();
|
||||
|
||||
void RecvProxy_LandMark(const CRecvProxyData *pData, void *pStruct, void *pOut)
|
||||
{
|
||||
C_TriggerTeleport *entity = (C_TriggerTeleport *) pStruct;
|
||||
|
||||
Q_strncpy( entity->m_iLandmark, pData->m_Value.m_pString, MAX_PATH );
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_TriggerTeleport, DT_TriggerTeleport, CTriggerTeleport)
|
||||
RecvPropString(RECVINFO(m_iLandmark), NULL, RecvProxy_LandMark)
|
||||
END_RECV_TABLE();
|
||||
|
||||
void C_TriggerTeleport::Touch( CBaseEntity *pOther )
|
||||
{
|
||||
CBaseEntity *pentTarget = NULL;
|
||||
|
||||
if (!PassesTriggerFilters(pOther))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The activator and caller are the same
|
||||
pentTarget = UTIL_FindEntityByName( pentTarget, m_target, NULL, pOther, pOther );
|
||||
if (!pentTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// If a landmark was specified, offset the player relative to the landmark.
|
||||
//
|
||||
CBaseEntity *pentLandmark = NULL;
|
||||
Vector vecLandmarkOffset(0, 0, 0);
|
||||
|
||||
// The activator and caller are the same
|
||||
pentLandmark = UTIL_FindEntityByName(pentLandmark, m_iLandmark, NULL, pOther, pOther );
|
||||
if (pentLandmark)
|
||||
{
|
||||
vecLandmarkOffset = pOther->GetAbsOrigin() - pentLandmark->GetAbsOrigin();
|
||||
}
|
||||
|
||||
pOther->SetGroundEntity( NULL );
|
||||
|
||||
Vector tmp = pentTarget->GetAbsOrigin();
|
||||
|
||||
if (!pentLandmark && pOther->IsPlayer())
|
||||
{
|
||||
// make origin adjustments in case the teleportee is a player. (origin in center, not at feet)
|
||||
tmp.z -= pOther->WorldAlignMins().z;
|
||||
}
|
||||
|
||||
//
|
||||
// Only modify the toucher's angles and zero their velocity if no landmark was specified.
|
||||
//
|
||||
const QAngle *pAngles = NULL;
|
||||
Vector *pVelocity = NULL;
|
||||
|
||||
#ifdef HL1_DLL
|
||||
Vector vecZero(0,0,0);
|
||||
#endif
|
||||
|
||||
if (!pentLandmark && !HasSpawnFlags(SF_TELEPORT_PRESERVE_ANGLES) )
|
||||
{
|
||||
pAngles = &pentTarget->GetAbsAngles();
|
||||
|
||||
#ifdef HL1_DLL
|
||||
pVelocity = &vecZero;
|
||||
#else
|
||||
pVelocity = NULL; //BUGBUG - This does not set the player's velocity to zero!!!
|
||||
#endif
|
||||
}
|
||||
|
||||
tmp += vecLandmarkOffset;
|
||||
|
||||
UTIL_SetOrigin( pOther, tmp );
|
||||
|
||||
if (pAngles)
|
||||
{
|
||||
if (!pOther->IsPlayer())
|
||||
{
|
||||
pOther->SetLocalAngles( *pAngles );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((C_BasePlayer*)pOther == C_BasePlayer::GetLocalPlayer())
|
||||
{
|
||||
auto angles = *pAngles;
|
||||
prediction->SetViewOrigin( tmp );
|
||||
|
||||
// This needs to be set only once!
|
||||
if (prediction->IsFirstTimePredicted())
|
||||
{
|
||||
engine->SetViewAngles( angles );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO_ENHANCED: point entity can change ? If yes should be predictable... ?
|
||||
class C_PointEntity : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_PointEntity, CBaseEntity );
|
||||
DECLARE_NETWORKCLASS();
|
||||
|
||||
virtual void Spawn( void );
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
virtual bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
private:
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_PointEntity, DT_PointEntity, CPointEntity)
|
||||
END_RECV_TABLE();
|
||||
|
||||
void C_PointEntity::Spawn( void )
|
||||
{
|
||||
SetSolid( SOLID_NONE );
|
||||
// UTIL_SetSize(this, vec3_origin, vec3_origin);
|
||||
}
|
||||
|
||||
bool C_PointEntity::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "mins" ) || FStrEq( szKeyName, "maxs" ) )
|
||||
{
|
||||
Warning("Warning! Can't specify mins/maxs for point entities! (%s)\n", GetClassname() );
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_teleport_destination, C_PointEntity );
|
21
game/client/css_enhanced/c_trigger_teleport.h
Normal file
21
game/client/css_enhanced/c_trigger_teleport.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef C_TRIGGERS_TELEPORT_H
|
||||
#define C_TRIGGERS_TELEPORT_H
|
||||
|
||||
#include "c_triggers.h"
|
||||
#include "predictable_entity.h"
|
||||
|
||||
constexpr int SF_TELEPORT_PRESERVE_ANGLES = 0x20; // Preserve angles even when a local landmark is not specified
|
||||
|
||||
class C_TriggerTeleport : public C_BaseTrigger
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_TriggerTeleport, C_BaseTrigger );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
virtual void Touch( CBaseEntity *pOther );
|
||||
|
||||
char m_iLandmark[MAX_PATH];
|
||||
};
|
||||
|
||||
#endif // C_TRIGGERS_TELEPORT_H
|
|
@ -88,10 +88,11 @@ BEGIN_DATADESC( C_BaseTrigger )
|
|||
|
||||
END_DATADESC()
|
||||
|
||||
// TODO_ENHANCED: this should be predicted, but since we don't have yet proper spawn, m_target would be an empty string all the time.
|
||||
BEGIN_PREDICTION_DATA(C_BaseTrigger)
|
||||
DEFINE_PRED_FIELD(m_bDisabled, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE),
|
||||
DEFINE_PRED_FIELD(m_target, FIELD_STRING, FTYPEDESC_INSENDTABLE),
|
||||
DEFINE_PRED_FIELD(m_iFilterName, FIELD_STRING, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_FIELD(m_bDisabled, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_FIELD(m_target, FIELD_STRING, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_FIELD(m_iFilterName, FIELD_STRING, FTYPEDESC_INSENDTABLE),
|
||||
// DEFINE_PRED_ARRAY(m_hPredictedTouchingEntities, FIELD_EHANDLE, MAX_EDICTS, FTYPEDESC_PRIVATE),
|
||||
// DEFINE_PRED_FIELD(m_iCountPredictedTouchingEntities, FIELD_INTEGER, FTYPEDESC_PRIVATE)
|
||||
END_PREDICTION_DATA();
|
||||
|
@ -107,6 +108,13 @@ void RecvProxy_FilterName(const CRecvProxyData *pData, void *pStruct, void *pOut
|
|||
entity->m_hFilter = static_cast<C_BaseFilter *>(UTIL_FindEntityByName(entity->m_iFilterName));
|
||||
}
|
||||
|
||||
void RecvProxy_Target(const CRecvProxyData *pData, void *pStruct, void *pOut)
|
||||
{
|
||||
C_BaseTrigger *entity = (C_BaseTrigger *) pStruct;
|
||||
|
||||
Q_strncpy( entity->m_target, pData->m_Value.m_pString, MAX_PATH );
|
||||
}
|
||||
|
||||
// Incase server decides to change m_bDisabled
|
||||
void RecvProxy_Disabled(const CRecvProxyData *pData, void *pStruct, void *pOut)
|
||||
{
|
||||
|
@ -120,7 +128,7 @@ void RecvProxy_Disabled(const CRecvProxyData *pData, void *pStruct, void *pOut)
|
|||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_BaseTrigger, DT_BaseTrigger, CBaseTrigger)
|
||||
RecvPropInt(RECVINFO(m_bDisabled), NULL, RecvProxy_Disabled),
|
||||
RecvPropString(RECVINFO(m_target)),
|
||||
RecvPropString(RECVINFO(m_target), NULL, RecvProxy_Target),
|
||||
RecvPropString(RECVINFO(m_iFilterName), NULL, RecvProxy_FilterName),
|
||||
END_RECV_TABLE();
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE( CBaseEntity, DT_BaseEntity )
|
|||
SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED),
|
||||
|
||||
// Send the name
|
||||
SendPropString (SENDINFO(m_iName)),
|
||||
SendPropStringT (SENDINFO(m_iName)),
|
||||
|
||||
SendPropInt (SENDINFO_NAME( m_MoveType, movetype ), MOVETYPE_MAX_BITS, SPROP_UNSIGNED ),
|
||||
SendPropInt (SENDINFO_NAME( m_MoveCollide, movecollide ), MOVECOLLIDE_MAX_BITS, SPROP_UNSIGNED ),
|
||||
|
@ -3477,6 +3477,7 @@ int CBaseEntity::UpdateTransmitState()
|
|||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
// TODO_ENHANCED: this needs to be always now since teleports are predicted.
|
||||
// by default cull against PVS
|
||||
return SetTransmitState( FL_EDICT_PVSCHECK );
|
||||
}
|
||||
|
@ -4066,7 +4067,8 @@ static void TeleportEntity( CBaseEntity *pSourceEntity, TeleportListEntry_t &ent
|
|||
{
|
||||
if ( newAngles )
|
||||
{
|
||||
pTeleport->SetLocalAngles( *newAngles );
|
||||
pTeleport->SetLocalAngles(*newAngles);
|
||||
// TODO_ENHANCED: this isn't needed anymore. Should be set client side now.
|
||||
if ( pTeleport->IsPlayer() )
|
||||
{
|
||||
CBasePlayer *pPlayer = (CBasePlayer *)pTeleport;
|
||||
|
|
|
@ -2673,10 +2673,12 @@ class CPointEntity : public CBaseEntity
|
|||
{
|
||||
public:
|
||||
DECLARE_CLASS( CPointEntity, CBaseEntity );
|
||||
DECLARE_NETWORKCLASS();
|
||||
|
||||
void Spawn( void );
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
virtual bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
virtual int UpdateTransmitState( void );
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ void CPointEntity::Spawn( void )
|
|||
// UTIL_SetSize(this, vec3_origin, vec3_origin);
|
||||
}
|
||||
|
||||
int CPointEntity::UpdateTransmitState( void )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
class CNullEntity : public CBaseEntity
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "const.h"
|
||||
#include "dt_send.h"
|
||||
#include "dt_utlvector_send.h"
|
||||
#include "networkvar.h"
|
||||
#include "player.h"
|
||||
#include "predictable_entity.h"
|
||||
#include "saverestore.h"
|
||||
|
@ -2337,15 +2338,20 @@ class CTriggerTeleport : public CBaseTrigger
|
|||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTriggerTeleport, CBaseTrigger );
|
||||
DECLARE_NETWORKCLASS();
|
||||
|
||||
void Spawn( void );
|
||||
void Touch( CBaseEntity *pOther );
|
||||
|
||||
string_t m_iLandmark;
|
||||
CNetworkVar(string_t, m_iLandmark);
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CTriggerTeleport, DT_TriggerTeleport)
|
||||
SendPropStringT(SENDINFO(m_iLandmark))
|
||||
END_SEND_TABLE();
|
||||
|
||||
LINK_ENTITY_TO_CLASS( trigger_teleport, CTriggerTeleport );
|
||||
|
||||
BEGIN_DATADESC( CTriggerTeleport )
|
||||
|
@ -2394,7 +2400,7 @@ void CTriggerTeleport::Touch( CBaseEntity *pOther )
|
|||
//
|
||||
CBaseEntity *pentLandmark = NULL;
|
||||
Vector vecLandmarkOffset(0, 0, 0);
|
||||
if (m_iLandmark != NULL_STRING)
|
||||
if (m_iLandmark.Get() != NULL_STRING)
|
||||
{
|
||||
// The activator and caller are the same
|
||||
pentLandmark = gEntList.FindEntityByName(pentLandmark, m_iLandmark, NULL, pOther, pOther );
|
||||
|
@ -2435,10 +2441,22 @@ void CTriggerTeleport::Touch( CBaseEntity *pOther )
|
|||
#endif
|
||||
}
|
||||
|
||||
tmp += vecLandmarkOffset;
|
||||
pOther->Teleport( &tmp, pAngles, pVelocity );
|
||||
tmp += vecLandmarkOffset;
|
||||
|
||||
auto player = dynamic_cast<CBasePlayer*>(pOther);
|
||||
|
||||
// TODO_ENHANCED: There's better way to do this with fixangle ...
|
||||
// So we can enforce server angles ...
|
||||
if (player)
|
||||
{
|
||||
pAngles = NULL;
|
||||
}
|
||||
|
||||
pOther->Teleport(&tmp, pAngles, pVelocity);
|
||||
}
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CPointEntity, DT_PointEntity)
|
||||
END_SEND_TABLE();
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity );
|
||||
|
||||
|
|
Loading…
Reference in a new issue