Merged dev changes 9/7/2019

- Experimental RPC stuff for the future
- Fixed players running over allies with vehicles (kind of)
- Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists)
- Fixed SDK_EyeRefract
- Fixed env_beam SetStart/EndEntity
- New "OnStateChange" output on NPCs
- scripted_face removed (use generic facing VCDs instead)
- Fixed RPC
- Miscellaneous code cleanup
This commit is contained in:
Blixibon 2019-09-07 21:05:59 +00:00
parent 3d464bc051
commit 031e383fb5
16 changed files with 132 additions and 205 deletions

View File

@ -219,6 +219,9 @@ IEngineReplay *g_pEngineReplay = NULL;
IEngineClientReplay *g_pEngineClientReplay = NULL;
IReplaySystem *g_pReplay = NULL;
#endif
#ifdef MAPBASE
IVEngineServer *serverengine = NULL;
#endif
IHaptics* haptics = NULL;// NVNT haptics system interface singleton
@ -949,6 +952,15 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
return false;
#endif
#ifdef MAPBASE
// Implements the server engine interface on the client.
// I'm extremely confused as to how this is even possible, but Saul Rennison's worldlight did it.
// If it's really this possible, why wasn't it available before?
// Hopefully there's no SP-only magic going on here, because I want to use this for RPC.
if ( (serverengine = (IVEngineServer*)appSystemFactory(INTERFACEVERSION_VENGINESERVER, NULL )) == NULL )
return false;
#endif
if (!g_pMatSystemSurface)
return false;

View File

@ -110,6 +110,9 @@ extern IReplayManager *g_pReplayManager;
extern IReplayScreenshotManager *g_pReplayScreenshotManager;
extern IEngineReplay *g_pEngineReplay;
extern IEngineClientReplay *g_pEngineClientReplay;
#ifdef MAPBASE
extern IVEngineServer *serverengine;
#endif
//=============================================================================
// HPE_BEGIN

View File

@ -1451,9 +1451,6 @@ void CClientShadowMgr::InitDepthTextureShadows()
VPROF_BUDGET( "CClientShadowMgr::InitDepthTextureShadows", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
#if defined(MAPBASE) //&& !defined(ASW_PROJECTED_TEXTURES)
// SAUL: start benchmark timer
//CFastTimer timer;
//timer.Start();
// SAUL: set m_nDepthTextureResolution to the depth resolution we want
m_nDepthTextureResolution = r_flashlightdepthres.GetInt();
#endif
@ -1525,11 +1522,6 @@ void CClientShadowMgr::InitDepthTextureShadows()
materials->EndRenderTargetAllocation();
}
#if defined(MAPBASE) && !defined(ASW_PROJECTED_TEXTURES)
//timer.End();
//DevMsg("InitDepthTextureShadows took %.2f msec\n", timer.GetDuration().GetMillisecondsF());
#endif
}
void CClientShadowMgr::ShutdownDepthTextureShadows()

View File

@ -120,6 +120,14 @@ void CWorldLights::Clear()
//-----------------------------------------------------------------------------
bool CWorldLights::Init()
{
#ifdef MAPBASE
// Moved to its own clientside interface after I found out it was possible
// (still have no idea how or why this works)
if ((g_pEngineServer = serverengine) == NULL)
return false;
return true;
#else
factorylist_t factories;
FactoryList_Retrieve(factories);
@ -127,6 +135,7 @@ bool CWorldLights::Init()
return false;
return true;
#endif
}
//-----------------------------------------------------------------------------

View File

@ -27,6 +27,9 @@ public:
// Find the brightest light source at a point
//-------------------------------------------------------------------------
bool GetBrightestLightSource(const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness);
#ifdef MAPBASE
bool GetCumulativeLightSource(const Vector &vecPosition, Vector &vecLightPos, float flMinBrightnessSqr);
#endif
// CAutoGameSystem overrides
public:

View File

@ -50,8 +50,8 @@ public:
void InputStrikeOnce( inputdata_t &inputdata );
#ifdef MAPBASE
void InputAmplitude( inputdata_t &inputdata );
void InputSetStartEntity( inputdata_t &inputdata ) { m_iszStartEntity = inputdata.value.StringID(); }
void InputSetEndEntity( inputdata_t &inputdata ) { m_iszEndEntity = inputdata.value.StringID(); }
void InputSetStartEntity( inputdata_t &inputdata ) { m_iszStartEntity = inputdata.value.StringID(); BeamUpdateVars(); }
void InputSetEndEntity( inputdata_t &inputdata ) { m_iszEndEntity = inputdata.value.StringID(); BeamUpdateVars(); }
#endif
void TurnOn( void );

View File

@ -717,9 +717,9 @@ bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info )
if ( IServerVehicle *pVehicle = info.GetAttacker()->GetServerVehicle() )
{
m_fNoDamageDecal = true;
if (pVehicle->GetPassenger() && pVehicle->GetPassenger()->IRelationType(this) != D_LI)
if (pVehicle->GetPassenger() && pVehicle->GetPassenger()->IRelationType(this) == D_LI)
{
// MAPBASE FIXME: Players could probably bail from their cars to kill NPCs with this!
// Players could bail from their cars to kill NPCs with this!
// Is there a "last passenger" variable we could use?
return false;
}
@ -4571,6 +4571,20 @@ void CAI_BaseNPC::SetState( NPC_STATE State )
// Notify the character that its state has changed.
if( fNotifyChange )
{
#ifdef MAPBASE
// Doing OnStateChange here instead of in OnStateChange() to prevent override shenanigans.
// Assume our enemy is the activator.
// States that don't have an enemy have a NULL activator, which is fine.
CBaseEntity *pActivator = GetEnemy();
// If we entered a script, use the scripted_sequence as the activator
if (m_NPCState == NPC_STATE_SCRIPT)
pActivator = m_hCine;
m_OnStateChange.Set(m_NPCState, pActivator, this);
#endif
OnStateChange( OldState, m_NPCState );
}
}
@ -11642,6 +11656,8 @@ BEGIN_DATADESC( CAI_BaseNPC )
DEFINE_INPUTFUNC( FIELD_STRING, "SetHintGroup", InputSetHintGroup ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetThinkNPC", InputSetThinkNPC ),
DEFINE_OUTPUT( m_OnStateChange, "OnStateChange" ),
#endif
// Function pointers
@ -14091,17 +14107,6 @@ void CAI_BaseNPC::ParseScriptedNPCInteractions( void )
else
{
szCriteria = UTIL_VarArgs("%s,%s:%s", szCriteria, szName, szValue);
/*
ResponseContext_t context;
context.m_iszName = AllocPooledString(szName);
context.m_iszValue = AllocPooledString(szValue);
context.m_fExpirationTime = 0.0;
DevMsg("ADDING CONTEXT: \"%s, %s\"\n", szName, szValue);
sInteraction.MiscCriteria.AddToTail(context);
*/
}
pCurNode = pCurNode->GetNextKey();

View File

@ -2059,6 +2059,8 @@ public:
COutputEHANDLE m_OnUnholsterWeapon;
COutputEHANDLE m_OnItemPickup;
COutputInt m_OnStateChange;
#endif
public:

View File

@ -1431,13 +1431,13 @@ public:
bool RedirectToFilter( CBaseEntity *pCaller, CBaseEntity *pEntity )
{
if (GetTargetFilter())
if (GetTargetFilter() && pEntity)
{
CBaseFilter *pFilter = static_cast<CBaseFilter*>(GetTargetFilter());
return pFilter->PassesFilter(pCaller, pEntity);
}
return false;
return pEntity != NULL;
}
bool RedirectToDamageFilter( CBaseEntity *pCaller, const CTakeDamageInfo &info )
@ -1448,7 +1448,7 @@ public:
return pFilter->PassesDamageFilter(pCaller, info);
}
return false;
return true;
}
virtual bool PassesDamageFilterImpl( CBaseEntity *pCaller, const CTakeDamageInfo &info )

View File

@ -1673,7 +1673,7 @@ bool CNPC_LabTurret::UpdateFacing( void )
// Update pitch
// Pitch is faster than the others, but it also kind of jiggles when targetting.
float flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.15f * MaxYawSpeed() ) );
float flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, (GetActivity() != ACT_CEILING_TURRET_CLOSE ? 0.15f : 0.1f) * MaxYawSpeed() ) );
SetPoseParameter( m_poseAim_Pitch, GetPoseParameter( m_poseAim_Pitch ) + ( flDiff * 2.0f ) );

View File

@ -89,7 +89,9 @@ void CV_InitMod()
void CVEnt_Precache(CMapbaseCVarModEntity *modent)
{
// Maybe add some security/notification stuff here later
if (Q_strstr(STRING(modent->m_target), "sv_allow_logic_convar"))
return;
CV_InitMod();
}
void CVEnt_Activate(CMapbaseCVarModEntity *modent, CBaseEntity *pActivator = UTIL_GetLocalPlayer())

View File

@ -255,7 +255,8 @@ void CGameEnd::InputGameEnd( inputdata_t &inputdata )
#ifdef MAPBASE
void CGameEnd::InputGameEndSP( inputdata_t &inputdata )
{
// Things like mapping competitions should operate with given strings for specific endings (e.g. background maps).
// This basically just acts as a shortcut for the "startupmenu force"/disconnection command.
// Things like mapping competitions could change this code based on given strings for specific endings (e.g. background maps).
CBasePlayer *pPlayer = AI_GetSinglePlayer();
if (pPlayer)
engine->ClientCommand(pPlayer->edict(), "startupmenu force");

View File

@ -2288,157 +2288,6 @@ int CAI_ScriptedSentence::StartSentence( CAI_BaseNPC *pTarget )
}
#ifdef MAPBASE
class CAI_ScriptedFace : public CPointEntity
{
public:
DECLARE_CLASS( CAI_ScriptedFace, CPointEntity );
CAI_ScriptedFace();
// Input handlers
void InputBeginFacing( inputdata_t &inputdata );
//void InputCancelFacing( inputdata_t &inputdata );
DECLARE_DATADESC();
void Begin(CBaseEntity *pActivator, CBaseEntity *pCaller);
private:
string_t m_iszFaceTarget;
// False = Entity, True = Position
bool m_bTargetType;
bool m_bGrabAll;
float m_flImportance;
float m_flDuration;
COutputEvent m_OnBeginFace;
};
BEGIN_DATADESC( CAI_ScriptedFace )
DEFINE_KEYFIELD( m_iszFaceTarget, FIELD_STRING, "SetFaceTarget" ),
DEFINE_KEYFIELD( m_bTargetType, FIELD_BOOLEAN, "TargetType" ),
DEFINE_KEYFIELD( m_bGrabAll, FIELD_BOOLEAN, "GrabAll" ),
DEFINE_KEYFIELD( m_flImportance, FIELD_FLOAT, "Importance" ),
DEFINE_KEYFIELD( m_flDuration, FIELD_FLOAT, "Duration" ),
// Inputs
DEFINE_INPUTFUNC(FIELD_VOID, "BeginFacing", InputBeginFacing),
// Outputs
DEFINE_OUTPUT(m_OnBeginFace, "OnBeginFace"),
END_DATADESC()
LINK_ENTITY_TO_CLASS( scripted_face, CAI_ScriptedFace );
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
CAI_ScriptedFace::CAI_ScriptedFace()
{
m_flDuration = 5.0f;
m_flImportance = 9999;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CAI_ScriptedFace::Begin(CBaseEntity *pActivator, CBaseEntity *pCaller)
{
Vector position;
CBaseEntity *pFaceTarget;
if (m_bTargetType)
UTIL_StringToVector(position.Base(), STRING(m_iszFaceTarget));
CBaseEntity *pTarget;
CAI_BaseNPC *pNPC;
if (m_bGrabAll)
{
pTarget = gEntList.FindEntityGeneric(NULL, STRING(m_target), this, pActivator, pCaller);
while (pTarget)
{
pNPC = pTarget->MyNPCPointer();
if (!pNPC)
{
Warning("%s tried to grab %s, but it is not a NPC!\n", GetDebugName(), pTarget->GetDebugName());
pTarget = gEntList.FindEntityGeneric(pTarget, STRING(m_target), this, pActivator, pCaller);
continue;
}
DevMsg("Grabbed one of many\n");
if (!m_bTargetType)
{
pFaceTarget = gEntList.FindEntityByNameNearest(STRING(m_iszFaceTarget), pTarget->GetLocalOrigin(), 0, this, pActivator, pCaller);
if (pFaceTarget)
{
pNPC->GetMotor()->AddFacingTarget(pFaceTarget, m_flImportance, m_flDuration);
pNPC->GetMotor()->SetIdealYawToTarget( pFaceTarget->GetAbsOrigin() );
m_OnBeginFace.FireOutput(pFaceTarget, pTarget);
}
}
else
{
pNPC->GetMotor()->AddFacingTarget(position, m_flImportance, m_flDuration);
}
pTarget = gEntList.FindEntityGeneric(pTarget, STRING(m_target), this, pActivator, pCaller);
}
}
else
{
pTarget = gEntList.FindEntityGeneric(NULL, STRING(m_target), this, pActivator, pCaller);
if (pTarget)
{
pNPC = pTarget->MyNPCPointer();
if (!pNPC)
{
Warning("%s tried to grab %s, but it is not a NPC!\n", GetDebugName(), pTarget->GetDebugName());
pTarget = gEntList.FindEntityGeneric(pTarget, STRING(m_target), this, pActivator, pCaller);
return;
}
if (!m_bTargetType)
{
pFaceTarget = gEntList.FindEntityByNameNearest(STRING(m_iszFaceTarget), pTarget->GetLocalOrigin(), 0, this, pActivator, pCaller);
if (pFaceTarget)
{
pNPC->GetMotor()->AddFacingTarget(pFaceTarget, m_flImportance, m_flDuration);
m_OnBeginFace.FireOutput(pFaceTarget, pTarget);
}
}
else
{
pNPC->GetMotor()->AddFacingTarget(position, m_flImportance, m_flDuration);
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CAI_ScriptedFace::InputBeginFacing( inputdata_t &inputdata )
{
Begin(inputdata.pActivator, inputdata.pCaller);
}
//-----------------------------------------------------------------------------
// This isn't exclusive to NPCs, so it could be moved if needed.
//-----------------------------------------------------------------------------

View File

@ -1,7 +1,6 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Carries the Mapbase CAutoGameSystem that loads manifest among other things.
// Also includes code that does not fit anywhere else.
// Purpose: Mapbase's RPC implementation.
//
// $NoKeywords: $
//=============================================================================//
@ -12,6 +11,7 @@
#ifdef STEAM_RPC
#include "clientsteamcontext.h"
#include "steam/steamclientpublic.h"
#endif
#ifdef DISCORD_RPC
@ -19,6 +19,8 @@
#include <time.h>
#endif
#include "c_playerresource.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
@ -231,6 +233,24 @@ END_DATADESC()
static ConVar cl_discord_appid("cl_discord_appid", "582595088719413250", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT);
static int64_t startTimestamp = time(0);
//
int MapbaseRPC_GetPlayerCount()
{
int iNumPlayers = 0;
if (g_PR)
{
for (; iNumPlayers <= gpGlobals->maxClients; iNumPlayers++)
{
if (!g_PR->IsConnected( iNumPlayers ))
break;
}
}
return iNumPlayers;
}
//-----------------------------------------------------------------------------
// Discord RPC handlers
//-----------------------------------------------------------------------------
@ -328,11 +348,6 @@ void MapbaseRPC_Update( int iRPCMask, int iType, const char *pMapName )
#ifdef STEAM_RPC
void MapbaseRPC_UpdateSteam( int iType, const char *pMapName )
{
if (!steamapicontext->SteamFriends())
{
DevMsg("No Friends! :(\n");
}
const char *pszStatus = NULL;
if (g_Metadata[RPC_STEAM] != NULL)
@ -376,11 +391,33 @@ void MapbaseRPC_UpdateSteam( int iType, const char *pMapName )
}
}
DevMsg("Updating Steam\n");
DevMsg( "Updating Steam\n" );
if (pszStatus)
{
steamapicontext->SteamFriends()->SetRichPresence( "gamestatus", pszStatus );
steamapicontext->SteamFriends()->SetRichPresence( "steam_display", "#SteamRPC_Status" );
if (gpGlobals->maxClients > 1)
{
// Players in server
const CSteamID *serverID = serverengine->GetGameServerSteamID();
if (serverID)
{
char szGroupID[32];
Q_snprintf(szGroupID, sizeof(szGroupID), "%i", serverID->GetAccountID());
char szGroupSize[8];
Q_snprintf(szGroupSize, sizeof(szGroupSize), "%i", MapbaseRPC_GetPlayerCount());
steamapicontext->SteamFriends()->SetRichPresence( "steam_player_group", szGroupID );
steamapicontext->SteamFriends()->SetRichPresence( "steam_player_group_size", szGroupSize );
}
else
{
DevWarning("Steam RPC cannot update player count (no server ID)\n");
}
}
}
}
#endif
@ -401,23 +438,29 @@ void MapbaseRPC_UpdateSteam( int iType, const char *pMapName )
void MapbaseRPC_GetDiscordParameters( DiscordRichPresence &discordPresence, int iType, const char *pMapName )
{
static char details[128];
static char state[128];
details[0] = '\0';
state[0] = '\0';
if (g_Metadata[RPC_DISCORD] != NULL)
{
C_MapbaseMetadata *pMetadata = static_cast<C_MapbaseMetadata*>(g_Metadata[RPC_DISCORD].Get());
if (pMetadata->m_iszRPCState[0] != NULL)
discordPresence.state = pMetadata->m_iszRPCState;
Q_strncpy( state, pMetadata->m_iszRPCState, sizeof(state) );
else
discordPresence.state = g_iszGameName;
Q_strncpy( state, g_iszGameName, sizeof(state) );
if (pMetadata->m_iszRPCDetails[0] != NULL)
discordPresence.details = pMetadata->m_iszRPCDetails;
Q_strncpy( details, pMetadata->m_iszRPCDetails, sizeof(details) );
else
{
if (engine->IsLevelMainMenuBackground())
discordPresence.details = VarArgs("Main Menu (%s)", pMapName ? pMapName : "N/A");
Q_snprintf( details, sizeof(details), "Main Menu (%s)", pMapName ? pMapName : "N/A" );
else
discordPresence.details = VarArgs("Map: %s", pMapName ? pMapName : "N/A");
Q_snprintf( details, sizeof(details), "%s", pMapName ? pMapName : "N/A" );
}
}
else
@ -427,8 +470,8 @@ void MapbaseRPC_GetDiscordParameters( DiscordRichPresence &discordPresence, int
case RPCSTATE_INIT:
case RPCSTATE_LEVEL_SHUTDOWN:
{
discordPresence.state = g_iszGameName;
discordPresence.details = "Main Menu";
Q_strncpy( state, g_iszGameName, sizeof(state) );
Q_strncpy( details, "Main Menu", sizeof(details) );
} break;
case RPCSTATE_LEVEL_INIT:
default:
@ -436,18 +479,26 @@ void MapbaseRPC_GetDiscordParameters( DiscordRichPresence &discordPresence, int
// Say we're in the main menu if it's a background map
if (engine->IsLevelMainMenuBackground())
{
discordPresence.state = g_iszGameName;
discordPresence.details = VarArgs("Main Menu (%s)", pMapName ? pMapName : "N/A");
Q_snprintf( details, sizeof(details), "Main Menu (%s)", pMapName ? pMapName : "N/A" );
}
else
{
discordPresence.state = g_iszGameName;
discordPresence.details = VarArgs("Map: %s", pMapName ? pMapName : "N/A");
Q_snprintf( details, sizeof(details), "%s", pMapName ? pMapName : "N/A" );
}
} break;
}
}
if (gpGlobals->maxClients > 1)
{
Q_snprintf( details, sizeof(details), "%s (%i/%i)", details, MapbaseRPC_GetPlayerCount(), gpGlobals->maxClients );
}
if (state[0] != '\0')
discordPresence.state = state;
if (details[0] != '\0')
discordPresence.details = details;
// Generic Mapbase logo. Specific to the Mapbase Discord application.
discordPresence.smallImageKey = "mb_logo_general";
discordPresence.smallImageText = "Mapbase";

View File

@ -485,7 +485,7 @@ float4 main( PS_INPUT i ) : COLOR
#if !defined( SHADER_MODEL_PS_2_0 )
float fogFactor = CalcPixelFogFactor( g_fPixelFogType, g_FogParams, g_vCameraPosition.xyz, i.vWorldPosition_ProjPosZ.xyz, i.vWorldPosition_ProjPosZ.w );
return FinalOutput( result, fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR );
return FinalOutputConst( result, fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR );
#else
float fogFactor = CalcPixelFogFactor( PIXEL_FOG_TYPE_NONE, g_FogParams, g_vCameraPosition.xyz, i.vWorldPosition_ProjPosZ.xyz, i.vWorldPosition_ProjPosZ.w );
return FinalOutput( result, fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR );

View File

@ -72,11 +72,9 @@ BEGIN_VS_SHADER( SDK_DecalModulate_dx9,
SHADER_DRAW
{
#ifdef MAPBASE
// TEST 1 - Check game DLL stuff since the issue is that mod2x is modding flashlight brightness because it's not gray
//
// NOTE: Maybe the decals not appearing is a SORTING issue!
// The flashlight part is transparent and overlaid on top of the decal!
//
// It is now believed the decals not appearing is a sorting issue.
// The flashlight part is transparent and overlaid on top of the decal.
// When a fix is found, this flashlight code could be removed.
bool bHasFlashlight = UsingFlashlight( params );
#endif
SHADOW_STATE