Mapbase v2.0; bulk commit

- Added custom map compile tools (vbsp, vvis, vrad)
- Changed blink fix (shouldn't change anything in-game)
- Added auto-completion to ent_create, npc_create, and the main set of "npc_" debug commands
- Added ent_create_aimed, an ent_create equivalent of npc_create_aimed
- Made hunters start using the "vs. player" melee animation against smaller NPCs that look weird with the "stab" attack
- Added "explosion_sparks" convar, which fixes broken code for giving explosions sparks (disabled by default because of how different it looks)
- Made interaction code capable of being dispatched on any entity, not just combat characters
- Added npc_barnacle_ignite convar, which lets barnacles be ignited by flares
- Fixed certain NPCs getting out of the way for the player when they hate them
- Fixed auto-generated "speak" scene responses not using parameters that work on real VCDs
- Made "stop_on_nonidle" capable of being used in any mod, not just HL2 episodic mods
- Selectable color for ragdoll boogie/point_ragdollboogie
- Fixed PickupWeaponInstant not firing weapon pickup outputs
- Introduced inputs and keyvalues for "lerping" to math_counter_advanced
- Fixed ClearConsole on logic_console
- logic_convar should now detect client convars correctly
- New NormalizeAngles input on math_vector
- logic_modelinfo LookupActivity input
- math_generate fixed and expanded to be more like math_counter
- Added a WIP game logging system for playtesting maps
- Introduced logic_playerinfo, an entity that can read a player's name or ID
- Fixed some new filters not working with filter_multi
- Added radius pickup spawnflag to func_physbox
- Added "Preserve name" spawnflag to weapons
- Added cc_achievement_debug message for when an achievement doesn't exist
- Made npc_combine_s not speak while in logic_choreographed_scenes
- Fixed zombie torsos/legs/headcrabs not being serverside when zombie is forced to server ragdoll
- Expanded and cleaned up npc_zombie_custom
- Fixed func_commandredirects not cleaning up correctly and sometimes crashing the game
- Allowed player squad commands to go through +USE-held objects
- Added a bunch of I/O/KV to trigger_waterydeath for better configuration
- Changed save comment system to use the chapter title from world properties, and the ability to suppress the title popup that normally results from it
- Adjusted game_convar_mod for MP planning
- Removed the func_precipitation custom particle/splash code for now, as it was causing problems
- Fixed env_global_light not accepting lightcolor
- Added "Additional Buttons" to player_speedmod
- Added save comment to RPC
- Added env_projectedtexture attenuation
- Added scripted_sequence OnPreIdleSequence
- Added OnCrab to zombies
- Added skill_changed game event (may need further testing)
- Added a fix for viewmodels flipping under extreme FOV values
- Added code that allows mappers to change the skin on shotgunners without it usually flipping back randomly
- Fixed a very, very, very major shader performance issue
- New SetAbsOrigin/Angles inputs on all entities, analogous to SetLocalOrigin/Angles
- Code improvements for I/O involving angles
- logic_entity_position improvements/fixes, including a new OutAngles output that outputs the angles on position calls
- Alternate collision/player avoidance spawnflag obsoletion enforcement disabled
- Enable/DisableHazardLights inputs on the EP2 jalopy, equivalent to the keyvalue
- Miscellaneous shader formatting adjustments and fixes
- Fixed AlwaysDrawOff on env_projectedtexture not being a valid input
This commit is contained in:
Blixibon 2019-12-14 04:20:02 +00:00
parent a1dba884a3
commit dc7f20acc8
97 changed files with 2845 additions and 485 deletions

View File

@ -88,6 +88,11 @@ private:
int m_nSpotlightTextureFrame;
int m_nShadowQuality;
#ifdef MAPBASE
float m_flConstantAtten;
float m_flLinearAtten;
float m_flQuadraticAtten;
float m_flShadowAtten;
bool m_bAlwaysDraw;
//bool m_bProjectedTextureVersion;
#endif

View File

@ -1149,9 +1149,7 @@ void C_BaseFlex::SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightC
{
// hack in an initialization
LinkToGlobalFlexControllers( GetModelPtr() );
#ifdef MAPBASE
m_iBlink = AddGlobalFlexController( "blink" );
#else
#ifndef MAPBASE
m_iBlink = AddGlobalFlexController( "UH" );
#endif

View File

@ -33,14 +33,7 @@ Vector g_vSplashColor( 0.5, 0.5, 0.5 );
float g_flSplashScale = 0.15;
float g_flSplashLifetime = 0.5f;
float g_flSplashAlpha = 0.3f;
#ifdef MAPBASE
// Rain splash stuff based on Tony Sergei's VDC code
// (r_RainParticle can be found in effects.cpp on the server as well)
ConVar r_RainParticle("r_RainParticle", "Rain_01_impact", FCVAR_CHEAT | FCVAR_REPLICATED);
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "99", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
#else
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
#endif
float GUST_INTERVAL_MIN = 1;
@ -331,20 +324,6 @@ inline bool CClient_Precipitation::SimulateRain( CPrecipitationParticle* pPartic
}
}
#ifdef MAPBASE
// Based on Tony Sergi's code on the VDC. This version re-uses m_Splashes instead of dispatching the effect immediately.
trace_t trace;
UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace);
if (trace.fraction < 1 || trace.DidHit())
{
if (RandomInt(0, 100) <= r_RainSplashPercentage.GetInt())
m_Splashes.AddToTail( trace.endpos );
// Tell the framework it's time to remove the particle from the list
return false;
}
#else
// No longer in the air? punt.
if ( !IsInAir( pParticle->m_Pos ) )
{
@ -365,7 +344,6 @@ inline bool CClient_Precipitation::SimulateRain( CPrecipitationParticle* pPartic
// Tell the framework it's time to remove the particle from the list
return false;
}
#endif
// We still want this particle
return true;
@ -572,15 +550,7 @@ void CClient_Precipitation::CreateWaterSplashes()
if ( CurrentViewForward().Dot( vSplash - CurrentViewOrigin() ) > 1 )
{
#ifdef MAPBASE
// Use a particle or
if ( r_RainParticle.GetString()[0] != NULL )
DispatchParticleEffect(r_RainParticle.GetString(), vSplash, QAngle(RandomFloat(0, 360), RandomFloat(0, 360), RandomFloat(0, 360)), NULL);
else
FX_WaterRipple( vSplash, g_flSplashScale, &g_vSplashColor, g_flSplashLifetime, g_flSplashAlpha );
#else
FX_WaterRipple( vSplash, g_flSplashScale, &g_vSplashColor, g_flSplashLifetime, g_flSplashAlpha );
#endif
}
}
m_Splashes.Purge();
@ -698,13 +668,6 @@ void CClient_Precipitation::Precache( )
case PRECIPITATION_TYPE_RAIN:
Assert( m_nPrecipType == PRECIPITATION_TYPE_RAIN );
#ifdef MAPBASE
if (r_RainParticle.GetString()[0] != NULL)
{
PrecacheParticleSystem( r_RainParticle.GetString() );
DevMsg("Rain particle system \"%s\" precached!\n", r_RainParticle.GetString());
}
#endif
m_Speed = RAIN_SPEED;
m_MatHandle = materials->FindMaterial( "particle/rain", TEXTURE_GROUP_CLIENT_EFFECTS );
m_InitialRamp = 1.0f;

View File

@ -56,6 +56,10 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvPro
RecvPropFloat( RECVINFO( m_flFarZ ) ),
RecvPropInt( RECVINFO( m_nShadowQuality ) ),
#ifdef MAPBASE
RecvPropFloat( RECVINFO( m_flConstantAtten ) ),
RecvPropFloat( RECVINFO( m_flLinearAtten ) ),
RecvPropFloat( RECVINFO( m_flQuadraticAtten ) ),
RecvPropFloat( RECVINFO( m_flShadowAtten ) ),
RecvPropBool( RECVINFO( m_bAlwaysDraw ) ),
// Not needed on the client right now, change when it actually is needed
@ -89,6 +93,10 @@ C_EnvProjectedTexture *C_EnvProjectedTexture::Create( )
pEnt->m_bState = true;
#ifdef MAPBASE
pEnt->m_bAlwaysDraw = false;
pEnt->m_flConstantAtten = 0.0f;
pEnt->m_flLinearAtten = 100.0f;
pEnt->m_flQuadraticAtten = 0.0f;
pEnt->m_flShadowAtten = 0.0f;
//pEnt->m_bProjectedTextureVersion = 1;
#endif
@ -381,18 +389,23 @@ void C_EnvProjectedTexture::UpdateLight( void )
float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );
state.m_fQuadraticAtten = 0.0;
state.m_fLinearAtten = 100;
state.m_fConstantAtten = 0.0f;
state.m_FarZAtten = m_flFarZ;
#ifdef MAPBASE
state.m_fConstantAtten = m_flConstantAtten;
state.m_fLinearAtten = m_flLinearAtten;
state.m_fQuadraticAtten = m_flQuadraticAtten;
state.m_FarZAtten = m_flFarZ;
state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
state.m_flShadowAtten = m_flShadowAtten;
#else
state.m_fQuadraticAtten = 0.0;
state.m_fLinearAtten = 100;
state.m_fConstantAtten = 0.0f;
state.m_FarZAtten = m_flFarZ;
state.m_fBrightnessScale = m_flBrightnessScale;
state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;

View File

@ -59,6 +59,9 @@ BEGIN_RECV_TABLE( C_World, DT_World )
RecvPropFloat(RECVINFO(m_flMinPropScreenSpaceWidth)),
RecvPropString(RECVINFO(m_iszDetailSpriteMaterial)),
RecvPropInt(RECVINFO(m_bColdWorld)),
#ifdef MAPBASE
RecvPropString(RECVINFO(m_iszChapterTitle)),
#endif
END_RECV_TABLE()

View File

@ -56,6 +56,9 @@ public:
float m_flMinPropScreenSpaceWidth;
float m_flMaxPropScreenSpaceWidth;
bool m_bColdWorld;
#ifdef MAPBASE
char m_iszChapterTitle[64];
#endif
private:
void RegisterSharedActivities( void );

View File

@ -26,6 +26,7 @@ $Project
{
$File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"

View File

@ -1256,6 +1256,13 @@ void FX_BuildTeslaHitbox( const CEffectData &data )
{
Vector vColor( 1, 1, 1 );
#ifdef MAPBASE
if ( data.m_bCustomColors )
{
vColor = data.m_CustomColors.m_vecColor1;
}
#endif
C_BaseEntity *pEntity = ClientEntityList().GetEnt( data.entindex() );
C_BaseAnimating *pAnimating = pEntity ? pEntity->GetBaseAnimating() : NULL;
if (!pAnimating)

View File

@ -59,6 +59,7 @@ private:
#ifdef MAPBASE
bool m_bDrawSky;
bool m_bDrawSky2;
bool m_bUseEyePosition;
#endif
// Fades
@ -81,6 +82,7 @@ IMPLEMENT_CLIENTCLASS_DT( C_ScriptIntro, DT_ScriptIntro, CScriptIntro )
#ifdef MAPBASE
RecvPropBool( RECVINFO( m_bDrawSky ) ),
RecvPropBool( RECVINFO( m_bDrawSky2 ) ),
RecvPropBool( RECVINFO( m_bUseEyePosition ) ),
#endif
// Fov & fov blends
@ -181,10 +183,13 @@ void C_ScriptIntro::PostDataUpdate( DataUpdateType_t updateType )
// If it's a point_camera and it's ortho, send it to the intro data
// Change this code if the purpose of m_hCameraEntity in intro data ever goes beyond ortho
C_PointCamera *pCamera = dynamic_cast<C_PointCamera*>(m_hCameraEntity.Get());
if (pCamera && pCamera->IsOrtho())
if ( Q_strncmp(m_hCameraEntity->GetClassname(), "point_camera", 12) == 0 )
{
m_IntroData.m_hCameraEntity = m_hCameraEntity;
C_PointCamera *pCamera = dynamic_cast<C_PointCamera*>(m_hCameraEntity.Get());
if (pCamera && pCamera->IsOrtho())
{
m_IntroData.m_hCameraEntity = m_hCameraEntity;
}
}
#endif
}
@ -265,8 +270,21 @@ void C_ScriptIntro::ClientThink( void )
if ( m_hCameraEntity )
{
#ifdef MAPBASE
if ( m_bUseEyePosition )
{
m_IntroData.m_vecCameraView = m_hCameraEntity->EyePosition();
m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->EyeAngles();
}
else
{
m_IntroData.m_vecCameraView = m_hCameraEntity->GetAbsOrigin();
m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->GetAbsAngles();
}
#else
m_IntroData.m_vecCameraView = m_hCameraEntity->GetAbsOrigin();
m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->GetAbsAngles();
#endif
}
CalculateFOV();

View File

@ -736,7 +736,11 @@ void CViewRender::SetUpViews()
float flFOVOffset = fDefaultFov - view.fov;
//Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end
#ifdef MAPBASE
view.fovViewmodel = fabs(g_pClientMode->GetViewModelFOV()) - flFOVOffset;
#else
view.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;
#endif
if ( UseVR() )
{

View File

@ -17,6 +17,7 @@
#include "IEffects.h"
#ifdef MAPBASE
#include "saverestore_utlvector.h"
#include "interval.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
@ -40,6 +41,10 @@ BEGIN_DATADESC( CRagdollBoogie )
// Think this should be handled by StartTouch/etc.
// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
#ifdef MAPBASE
DEFINE_FIELD( m_vecColor, FIELD_VECTOR ),
#endif
DEFINE_FUNCTION( BoogieThink ),
DEFINE_FUNCTION( ZapThink ),
@ -53,7 +58,11 @@ LINK_ENTITY_TO_CLASS( env_ragdoll_boogie, CRagdollBoogie );
// Input : pTarget -
//-----------------------------------------------------------------------------
CRagdollBoogie *CRagdollBoogie::Create( CBaseEntity *pTarget, float flMagnitude,
#ifdef MAPBASE
float flStartTime, float flLengthTime, int nSpawnFlags, const Vector *vecColor )
#else
float flStartTime, float flLengthTime, int nSpawnFlags )
#endif
{
CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pTarget );
if ( !pRagdoll )
@ -67,6 +76,10 @@ CRagdollBoogie *CRagdollBoogie::Create( CBaseEntity *pTarget, float flMagnitude,
pBoogie->AttachToEntity( pTarget );
pBoogie->SetBoogieTime( flStartTime, flLengthTime );
pBoogie->SetMagnitude( flMagnitude );
#ifdef MAPBASE
if (vecColor != NULL)
pBoogie->SetColor( *vecColor );
#endif
pBoogie->Spawn();
return pBoogie;
}
@ -118,6 +131,13 @@ void CRagdollBoogie::ZapThink()
data.m_nEntIndex = GetMoveParent()->entindex();
data.m_flMagnitude = 4;
data.m_flScale = HasSpawnFlags(SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM) ? 1.0f : 2.0f;
#ifdef MAPBASE
if (!m_vecColor.IsZero())
{
data.m_bCustomColors = true;
data.m_CustomColors.m_vecColor1 = m_vecColor;
}
#endif
DispatchEffect( "TeslaHitboxes", data );
}
@ -285,14 +305,19 @@ public:
void InputActivate( inputdata_t &inputdata );
void InputDeactivate( inputdata_t &inputdata );
void InputBoogieTarget( inputdata_t &inputdata );
void InputSetZapColor( inputdata_t &inputdata );
bool KeyValue( const char *szKeyName, const char *szValue );
private:
float m_flStartTime;
float m_flBoogieLength;
interval_t m_BoogieLength;
float m_flMagnitude;
// This allows us to remove active boogies later.
CUtlVector<EHANDLE> m_Boogies;
Vector m_vecZapColor;
// This allows us to change or remove active boogies later.
CUtlVector<CHandle<CRagdollBoogie>> m_Boogies;
};
//-----------------------------------------------------------------------------
@ -301,9 +326,11 @@ private:
BEGIN_DATADESC( CPointRagdollBoogie )
DEFINE_KEYFIELD( m_flStartTime, FIELD_FLOAT, "StartTime" ),
DEFINE_KEYFIELD( m_flBoogieLength, FIELD_FLOAT, "BoogieLength" ),
DEFINE_KEYFIELD( m_BoogieLength, FIELD_INTERVAL, "BoogieLength" ),
DEFINE_KEYFIELD( m_flMagnitude, FIELD_FLOAT, "Magnitude" ),
DEFINE_KEYFIELD( m_vecZapColor, FIELD_VECTOR, "ZapColor" ),
// Think this should be handled by StartTouch/etc.
// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
@ -313,6 +340,7 @@ BEGIN_DATADESC( CPointRagdollBoogie )
DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),
DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ),
DEFINE_INPUTFUNC( FIELD_STRING, "BoogieTarget", InputBoogieTarget ),
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetZapColor", InputSetZapColor ),
END_DATADESC()
@ -326,7 +354,7 @@ bool CPointRagdollBoogie::ApplyBoogie( CBaseEntity *pTarget, CBaseEntity *pActiv
{
if (dynamic_cast<CRagdollProp*>(pTarget))
{
m_Boogies.AddToTail(CRagdollBoogie::Create(pTarget, m_flMagnitude, gpGlobals->curtime + m_flStartTime, m_flBoogieLength, GetSpawnFlags()));
m_Boogies.AddToTail(CRagdollBoogie::Create(pTarget, m_flMagnitude, gpGlobals->curtime + m_flStartTime, RandomInterval(m_BoogieLength), GetSpawnFlags(), &m_vecZapColor));
}
else if (pTarget->MyCombatCharacterPointer())
{
@ -337,7 +365,7 @@ bool CPointRagdollBoogie::ApplyBoogie( CBaseEntity *pTarget, CBaseEntity *pActiv
pRagdoll->SetCollisionBounds(CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs());
m_Boogies.AddToTail(CRagdollBoogie::Create(pRagdoll, m_flMagnitude, gpGlobals->curtime + m_flStartTime, m_flBoogieLength, GetSpawnFlags()));
m_Boogies.AddToTail(CRagdollBoogie::Create(pRagdoll, m_flMagnitude, gpGlobals->curtime + m_flStartTime, RandomInterval(m_BoogieLength), GetSpawnFlags(), &m_vecZapColor));
CTakeDamageInfo ragdollInfo(this, pActivator, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL);
ragdollInfo.SetDamagePosition(WorldSpaceCenter());
@ -382,6 +410,8 @@ void CPointRagdollBoogie::InputDeactivate( inputdata_t &inputdata )
UTIL_Remove(m_Boogies[i]);
}
m_Boogies.Purge();
//m_Boogies.RemoveAll();
}
@ -402,4 +432,47 @@ void CPointRagdollBoogie::InputBoogieTarget( inputdata_t &inputdata )
pEnt = gEntList.FindEntityByName(pEnt, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller);
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &inputdata -
//-----------------------------------------------------------------------------
void CPointRagdollBoogie::InputSetZapColor( inputdata_t &inputdata )
{
inputdata.value.Vector3D( m_vecZapColor );
if (!m_vecZapColor.IsZero())
{
// Turn into ratios of 255
m_vecZapColor /= 255.0f;
}
// Apply to existing boogies
for (int i = 0; i < m_Boogies.Count(); i++)
{
if (m_Boogies[i])
{
m_Boogies[i]->SetColor( m_vecZapColor );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Handles key values from the BSP before spawn is called.
//-----------------------------------------------------------------------------
bool CPointRagdollBoogie::KeyValue( const char *szKeyName, const char *szValue )
{
if ( FStrEq( szKeyName, "ZapColor" ) )
{
UTIL_StringToVector(m_vecZapColor.Base(), szValue);
if (!m_vecZapColor.IsZero())
{
// Turn into ratios of 255
m_vecZapColor /= 255.0f;
}
}
else
return BaseClass::KeyValue( szKeyName, szValue );
return true;
}
#endif

View File

@ -28,10 +28,18 @@ class CRagdollBoogie : public CBaseEntity
DECLARE_CLASS( CRagdollBoogie, CBaseEntity );
public:
#ifdef MAPBASE
static CRagdollBoogie *Create( CBaseEntity *pTarget, float flMagnitude, float flStartTime, float flLengthTime = 0.0f, int nSpawnFlags = 0, const Vector *vecColor = NULL );
#else
static CRagdollBoogie *Create( CBaseEntity *pTarget, float flMagnitude, float flStartTime, float flLengthTime = 0.0f, int nSpawnFlags = 0 );
#endif
static void IncrementSuppressionCount( CBaseEntity *pTarget );
static void DecrementSuppressionCount( CBaseEntity *pTarget );
#ifdef MAPBASE
void SetColor( const Vector &vecColor ) { m_vecColor = vecColor; }
#endif
void Spawn();
private:
@ -45,6 +53,10 @@ private:
float m_flBoogieLength;
float m_flMagnitude;
int m_nSuppressionCount;
#ifdef MAPBASE
Vector m_vecColor = Vector(1, 1, 1);
#endif
};
#endif // RAGDOLLBOOGIE_H

View File

@ -1934,7 +1934,7 @@ void CAI_BaseActor::OnStateChange( NPC_STATE OldState, NPC_STATE NewState )
{
PlayExpressionForState( NewState );
#ifdef HL2_EPISODIC
#if defined(HL2_EPISODIC) || defined(MAPBASE)
// If we've just switched states, ensure we stop any scenes that asked to be stopped
if ( OldState == NPC_STATE_IDLE )
{

View File

@ -13705,7 +13705,11 @@ void CAI_BaseNPC::TestPlayerPushing( CBaseEntity *pEntity )
// Heuristic for determining if the player is pushing me away
CBasePlayer *pPlayer = ToBasePlayer( pEntity );
#ifdef MAPBASE
if ( pPlayer && !( pPlayer->GetFlags() & FL_NOTARGET ) && IRelationType( pPlayer ) > D_FR )
#else
if ( pPlayer && !( pPlayer->GetFlags() & FL_NOTARGET ) )
#endif
{
if ( (pPlayer->m_nButtons & (IN_FORWARD|IN_BACK|IN_MOVELEFT|IN_MOVERIGHT)) ||
pPlayer->GetAbsVelocity().AsVector2D().LengthSqr() > 50*50 )

View File

@ -2900,6 +2900,9 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
//
if ( m_hCine->m_iszPreIdle != NULL_STRING )
{
#ifdef MAPBASE
m_hCine->OnPreIdleSequence( this );
#endif
m_hCine->StartSequence( ( CAI_BaseNPC * )this, m_hCine->m_iszPreIdle, false );
if ( FStrEq( STRING( m_hCine->m_iszPreIdle ), STRING( m_hCine->m_iszPlay ) ) )
{

View File

@ -390,6 +390,149 @@ void CC_NPC_Focus( const CCommand &args )
static ConCommand npc_focus("npc_focus", CC_NPC_Focus, "Displays red line to NPC's enemy (if has one) and blue line to NPC's target entity (if has one)\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at", FCVAR_CHEAT);
ConVar npc_create_equipment("npc_create_equipment", "");
#ifdef MAPBASE
extern int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 );
extern bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs );
//------------------------------------------------------------------------------
// Purpose: Create an NPC of the given type
//------------------------------------------------------------------------------
class CNPCCreateAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback
{
public:
virtual bool CreateAimed() { return false; }
virtual void CommandCallback( const CCommand &args )
{
MDLCACHE_CRITICAL_SECTION();
bool allowPrecache = CBaseEntity::IsPrecacheAllowed();
CBaseEntity::SetAllowPrecache( true );
// Try to create entity
CAI_BaseNPC *baseNPC = dynamic_cast< CAI_BaseNPC * >( CreateEntityByName(args[1]) );
if (baseNPC)
{
baseNPC->KeyValue( "additionalequipment", npc_create_equipment.GetString() );
if ( args.ArgC() == 3 )
{
baseNPC->SetName( AllocPooledString( args[2] ) );
}
else if ( args.ArgC() > 3 )
{
baseNPC->SetName( AllocPooledString( args[2] ) );
// Pass in any additional parameters.
for ( int i = 3; i + 1 < args.ArgC(); i += 2 )
{
const char *pKeyName = args[i];
const char *pValue = args[i+1];
baseNPC->KeyValue( pKeyName, pValue );
}
}
DispatchSpawn(baseNPC);
// Now attempt to drop into the world
CBasePlayer* pPlayer = UTIL_GetCommandClient();
trace_t tr;
Vector forward;
QAngle angles;
pPlayer->EyeVectors( &forward );
bool bCreateAimed = CreateAimed();
if (bCreateAimed)
{
VectorAngles( forward, angles );
angles.x = 0;
angles.z = 0;
}
AI_TraceLine(pPlayer->EyePosition(),
pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID,
pPlayer, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction != 1.0)
{
if (baseNPC->CapabilitiesGet() & bits_CAP_MOVE_FLY)
{
Vector pos = tr.endpos - forward * 36;
baseNPC->Teleport( &pos, bCreateAimed ? &angles : NULL, NULL );
}
else
{
// Raise the end position a little up off the floor, place the npc and drop him down
tr.endpos.z += 12;
baseNPC->Teleport( &tr.endpos, bCreateAimed ? &angles : NULL, NULL );
UTIL_DropToFloor( baseNPC, MASK_NPCSOLID );
}
// Now check that this is a valid location for the new npc to be
Vector vUpBit = baseNPC->GetAbsOrigin();
vUpBit.z += 1;
AI_TraceHull( baseNPC->GetAbsOrigin(), vUpBit, baseNPC->GetHullMins(), baseNPC->GetHullMaxs(),
MASK_NPCSOLID, baseNPC, COLLISION_GROUP_NONE, &tr );
if ( tr.startsolid || (tr.fraction < 1.0) )
{
baseNPC->SUB_Remove();
DevMsg("Can't create %s. Bad Position!\n",args[1]);
NDebugOverlay::Box(baseNPC->GetAbsOrigin(), baseNPC->GetHullMins(), baseNPC->GetHullMaxs(), 255, 0, 0, 0, 0);
}
}
else if (bCreateAimed)
{
baseNPC->Teleport( NULL, &angles, NULL );
}
baseNPC->Activate();
}
CBaseEntity::SetAllowPrecache( allowPrecache );
}
virtual int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands )
{
if ( !g_pGameRules )
{
return 0;
}
const char *cmdname = CreateAimed() ? "npc_create_aimed" : "npc_create";
char *substring = (char *)partial;
if ( Q_strstr( partial, cmdname ) )
{
substring = (char *)partial + strlen( cmdname ) + 1;
}
int checklen = Q_strlen( substring );
if (checklen <= 0)
{
// Only show classnames prefixed with "npc" unless the user starts typing other characters
substring = "npc";
checklen = 3;
}
CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc );
return EntityFactory_AutoComplete( cmdname, commands, symbols, substring, checklen );
}
};
static CNPCCreateAutoCompletionFunctor g_NPCCreateAutoComplete;
static ConCommand npc_create("npc_create", &g_NPCCreateAutoComplete, "Creates an NPC of the given type where the player is looking (if the given NPC can actually stand at that location).\n\tArguments: {npc_class_name}", FCVAR_CHEAT, &g_NPCCreateAutoComplete);
class CNPCCreateAimedAutoCompletionFunctor : public CNPCCreateAutoCompletionFunctor
{
public:
virtual bool CreateAimed() { return true; }
};
static CNPCCreateAimedAutoCompletionFunctor g_NPCCreateAimedAutoComplete;
static ConCommand npc_create_aimed("npc_create_aimed", &g_NPCCreateAimedAutoComplete, "Creates an NPC aimed away from the player of the given type where the player is looking (if the given NPC can actually stand at that location).\n\tArguments: {npc_class_name}", FCVAR_CHEAT, &g_NPCCreateAimedAutoComplete);
#else
//------------------------------------------------------------------------------
// Purpose: Create an NPC of the given type
//------------------------------------------------------------------------------
@ -540,6 +683,7 @@ void CC_NPC_Create_Aimed( const CCommand &args )
CBaseEntity::SetAllowPrecache( allowPrecache );
}
static ConCommand npc_create_aimed("npc_create_aimed", CC_NPC_Create_Aimed, "Creates an NPC aimed away from the player of the given type where the player is looking (if the given NPC can actually stand at that location). Note that this only works for npc classes that are already in the world. You can not create an entity that doesn't have an instance in the level.\n\tArguments: {npc_class_name}", FCVAR_CHEAT);
#endif
//------------------------------------------------------------------------------
// Purpose: Destroy unselected NPCs
@ -711,6 +855,134 @@ void CC_NPC_Reset( void )
}
static ConCommand npc_reset("npc_reset", CC_NPC_Reset, "Reloads schedules for all NPC's from their script files\n\tArguments: -none-", FCVAR_CHEAT);
#ifdef MAPBASE
extern bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs );
//------------------------------------------------------------------------------
// Purpose : Auto-completes with entities in the entity list, but only uses NPC-derived entities.
// Input : cmdname - The name of the command.
// &commands - Where the complete autocompletes should be sent to.
// substring - The current search query. (only pool entities that start with this)
// checklen - The number of characters to check.
// Output : A pointer to a cUtlRBTRee containing all of the entities.
//------------------------------------------------------------------------------
static int AutoCompleteNPCs(const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0)
{
CBaseEntity *pos = NULL;
while ((pos = gEntList.NextEnt(pos)) != NULL)
{
if (!pos->IsNPC())
continue;
const char *name = pos->GetClassname();
if (pos->GetEntityName() == NULL_STRING || Q_strnicmp(STRING(pos->GetEntityName()), substring, checklen))
{
if (Q_strnicmp(pos->GetClassname(), substring, checklen))
continue;
}
else
name = STRING(pos->GetEntityName());
CUtlString sym = name;
int idx = symbols.Find(sym);
if (idx == symbols.InvalidIndex())
{
symbols.Insert(sym);
}
// Too many
if (symbols.Count() >= COMMAND_COMPLETION_MAXITEMS)
break;
}
// Now fill in the results
for (int i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder(i))
{
const char *name = symbols[i].String();
char buf[512];
Q_strncpy(buf, name, sizeof(buf));
Q_strlower(buf);
CUtlString command;
command = CFmtStr("%s %s", cmdname, buf);
commands.AddToTail(command);
}
return symbols.Count();
}
//------------------------------------------------------------------------------
// There's a big set of NPC debug commands that do similar operations and
// can fall under this base class for auto-completion, etc.
//------------------------------------------------------------------------------
class CNPCDebugAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback
{
public:
virtual const char *CommandName() { return NULL; }
virtual void CommandCallback( const CCommand &args )
{
SetDebugBits( UTIL_GetCommandClient(), args[1], OVERLAY_NPC_NEAREST_BIT );
}
virtual int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands )
{
if ( !g_pGameRules )
{
return 0;
}
const char *cmdname = CommandName();
char *substring = (char *)partial;
if ( Q_strstr( partial, cmdname ) )
{
substring = (char *)partial + strlen( cmdname ) + 1;
}
int checklen = Q_strlen( substring );
if (checklen == 0 || atoi(substring) != 0)
{
// Must be the picker or an entity index
return 0;
}
CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc );
return AutoCompleteNPCs(cmdname, commands, symbols, substring, checklen);
}
};
#define NPCDebugCommand(name, functor, bit, help) class CNPC##functor##AutoCompletionFunctor : public CNPCDebugAutoCompletionFunctor \
{ \
public: \
virtual const char *CommandName() { return #name; } \
virtual void CommandCallback( const CCommand &args ) \
{ \
SetDebugBits( UTIL_GetCommandClient(), args[1], bit ); \
} \
}; \
static CNPC##functor##AutoCompletionFunctor g_NPC##functor##AutoCompletionFunctor; \
static ConCommand name(#name, &g_NPC##functor##AutoCompletionFunctor, help, FCVAR_CHEAT, &g_NPC##functor##AutoCompletionFunctor);
NPCDebugCommand( npc_nearest, Nearest, OVERLAY_NPC_NEAREST_BIT, "Draw's a while box around the NPC(s) nearest node\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at " );
NPCDebugCommand( npc_route, Route, OVERLAY_NPC_ROUTE_BIT, "Displays the current route of the given NPC as a line on the screen. Waypoints along the route are drawn as small cyan rectangles. Line is color coded in the following manner:\n\tBlue - path to a node\n\tCyan - detour around an object (triangulation)\n\tRed - jump\n\tMaroon - path to final target position\n\tArguments: {npc_name} / {npc_class_name} / no argument picks what player is looking at " );
NPCDebugCommand( npc_select, Select, OVERLAY_NPC_SELECTED_BIT, "Select or deselects the given NPC(s) for later manipulation. Selected NPC's are shown surrounded by a red translucent box\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at " );
NPCDebugCommand( npc_combat, Combat, OVERLAY_NPC_SQUAD_BIT, "Displays text debugging information about the squad and enemy of the selected NPC (See Overlay Text)\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at" );
NPCDebugCommand( npc_tasks, Tasks, OVERLAY_NPC_TASK_BIT, "Displays detailed text debugging information about the all the tasks of the selected NPC current schedule (See Overlay Text)\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at " );
NPCDebugCommand( npc_task_text, TaskText, OVERLAY_TASK_TEXT_BIT, "Outputs text debugging information to the console about the all the tasks + break conditions of the selected NPC current schedule\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at " );
NPCDebugCommand( npc_conditions, Conditions, OVERLAY_NPC_CONDITIONS_BIT, "Displays all the current AI conditions that an NPC has in the overlay text.\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at" );
NPCDebugCommand( npc_viewcone, Viewcone, OVERLAY_NPC_VIEWCONE_BIT, "Displays the viewcone of the NPC (where they are currently looking and what the extents of there vision is)\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at" );
NPCDebugCommand( npc_relationships, Relationships, OVERLAY_NPC_RELATION_BIT, "Displays the relationships between this NPC and all others.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at" );
NPCDebugCommand( npc_steering, Steering, OVERLAY_NPC_STEERING_REGULATIONS, "Displays the steering obstructions of the NPC( used to perform local avoidance )\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at" );
// For backwards compatibility
void CC_NPC_Squads( const CCommand &args )
{
SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_SQUAD_BIT);
}
static ConCommand npc_squads("npc_squads", CC_NPC_Squads, "Obsolete. Replaced by npc_combat", FCVAR_CHEAT);
#else
//------------------------------------------------------------------------------
// Purpose: Show the selected NPC's nearest node
//------------------------------------------------------------------------------
@ -805,6 +1077,7 @@ void CC_NPC_ViewSteeringRegulations( const CCommand &args )
SetDebugBits( UTIL_GetCommandClient(), args[1], OVERLAY_NPC_STEERING_REGULATIONS);
}
static ConCommand npc_steering("npc_steering", CC_NPC_ViewSteeringRegulations, "Displays the steering obstructions of the NPC (used to perform local avoidance)\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at", FCVAR_CHEAT);
#endif
void CC_NPC_ViewSteeringRegulationsAll( void )
{

View File

@ -608,7 +608,11 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
if ( !result->ShouldntUseScene() )
{
// This generates a fake CChoreoScene wrapping the sound.txt name
#ifdef MAPBASE
spoke = SpeakAutoGeneratedScene( response, delay, result, filter );
#else
spoke = SpeakAutoGeneratedScene( response, delay );
#endif
}
else
{
@ -863,9 +867,17 @@ bool CAI_Expresser::SpeakRawScene( const char *pszScene, float delay, AI_Respons
}
// This will create a fake .vcd/CChoreoScene to wrap the sound to be played
#ifdef MAPBASE
bool CAI_Expresser::SpeakAutoGeneratedScene( char const *soundname, float delay, AI_Response *response, IRecipientFilter *filter )
#else
bool CAI_Expresser::SpeakAutoGeneratedScene( char const *soundname, float delay )
#endif
{
#ifdef MAPBASE
float speakTime = GetOuter()->PlayAutoGeneratedSoundScene( soundname, delay, response, filter );
#else
float speakTime = GetOuter()->PlayAutoGeneratedSoundScene( soundname );
#endif
if ( speakTime > 0 )
{
SpeechMsg( GetOuter(), "SpeakAutoGeneratedScene( %s, %f) %f\n", soundname, delay, speakTime );

View File

@ -208,7 +208,11 @@ protected:
bool SpeakRawScene( const char *pszScene, float delay, AI_Response *response, IRecipientFilter *filter = NULL );
// This will create a fake .vcd/CChoreoScene to wrap the sound to be played
#ifdef MAPBASE
bool SpeakAutoGeneratedScene( char const *soundname, float delay, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
#else
bool SpeakAutoGeneratedScene( char const *soundname, float delay );
#endif
void DumpHistories();

View File

@ -1524,6 +1524,30 @@ bool CBaseCombatCharacter::BecomeRagdollBoogie( CBaseEntity *pKiller, const Vect
return true;
}
#ifdef MAPBASE
CBaseEntity *CBaseCombatCharacter::BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags, const Vector *vecColor )
{
Assert( CanBecomeRagdoll() );
CTakeDamageInfo info( pKiller, pKiller, 1.0f, DMG_GENERIC );
info.SetDamageForce( forceVector );
CBaseEntity *pRagdoll = CreateServerRagdoll( this, 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true );
pRagdoll->SetCollisionBounds( CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs() );
CBaseEntity *pBoogie = CRagdollBoogie::Create( pRagdoll, 200, gpGlobals->curtime, duration, flags, vecColor );
CTakeDamageInfo ragdollInfo( pKiller, pKiller, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL );
ragdollInfo.SetDamagePosition( WorldSpaceCenter() );
ragdollInfo.SetDamageForce( Vector( 0, 0, 1 ) );
TakeDamage( ragdollInfo );
return pBoogie;
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -4020,6 +4044,11 @@ void CBaseCombatCharacter::InputPickupWeaponInstant( inputdata_t &inputdata )
if (inputdata.value.Entity() && inputdata.value.Entity()->IsBaseCombatWeapon())
{
CBaseCombatWeapon *pWeapon = inputdata.value.Entity()->MyCombatWeaponPointer();
if (pWeapon->GetOwner())
{
Msg("Ignoring PickupWeaponInstant on %s because %s already has an owner\n", GetDebugName(), pWeapon->GetDebugName());
return;
}
if (CBaseCombatWeapon *pExistingWeapon = Weapon_OwnsThisType(pWeapon->GetClassname()))
{
@ -4036,6 +4065,8 @@ void CBaseCombatCharacter::InputPickupWeaponInstant( inputdata_t &inputdata )
{
Weapon_Equip(pWeapon);
}
pWeapon->OnPickedUp( this );
}
else
{

View File

@ -333,6 +333,12 @@ public:
virtual bool BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags );
#ifdef MAPBASE
// A version of BecomeRagdollBoogie() that allows the color to change and returns the entity itself instead.
// In order to avoid breaking anything, it doesn't change the original function.
virtual CBaseEntity *BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags, const Vector *vecColor );
#endif
CBaseEntity *FindHealthItem( const Vector &vecPosition, const Vector &range );

View File

@ -2037,6 +2037,8 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetLocalOrigin", InputSetLocalOrigin ),
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetLocalAngles", InputSetLocalAngles ),
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetAbsOrigin", InputSetAbsOrigin ),
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetAbsAngles", InputSetAbsAngles ),
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetLocalVelocity", InputSetLocalVelocity ),
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetLocalAngularVelocity", InputSetLocalAngularVelocity ),
@ -7092,7 +7094,7 @@ const char *CBaseEntity::GetContextValue( const char *contextName ) const
{
int idx = FindContextByName( contextName );
if ( idx == -1 )
return NULL;
return "";
return m_ResponseContexts[ idx ].m_iszValue.ToCStr();
}
@ -7554,10 +7556,30 @@ void CBaseEntity::InputSetLocalOrigin( inputdata_t& inputdata )
// Purpose: Sets our angles.
//-----------------------------------------------------------------------------
void CBaseEntity::InputSetLocalAngles( inputdata_t& inputdata )
{
QAngle ang;
inputdata.value.Angle3D(ang);
SetLocalAngles(ang);
}
//-----------------------------------------------------------------------------
// Purpose: Sets our origin.
//-----------------------------------------------------------------------------
void CBaseEntity::InputSetAbsOrigin( inputdata_t& inputdata )
{
Vector vec;
inputdata.value.Vector3D(vec);
SetLocalAngles(QAngle(vec.x, vec.y, vec.z));
SetAbsOrigin(vec);
}
//-----------------------------------------------------------------------------
// Purpose: Sets our angles.
//-----------------------------------------------------------------------------
void CBaseEntity::InputSetAbsAngles( inputdata_t& inputdata )
{
QAngle ang;
inputdata.value.Angle3D(ang);
SetAbsAngles(ang);
}
//-----------------------------------------------------------------------------
@ -8746,6 +8768,130 @@ void CBaseEntity::SetCollisionBoundsFromModel()
}
#ifdef MAPBASE
extern int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 );
//------------------------------------------------------------------------------
// Purpose: Create an entity of the given type
//------------------------------------------------------------------------------
class CEntCreateAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback
{
public:
virtual bool CreateAimed() { return false; }
virtual void CommandCallback( const CCommand &args )
{
MDLCACHE_CRITICAL_SECTION();
CBasePlayer *pPlayer = UTIL_GetCommandClient();
if (!pPlayer)
{
return;
}
// Don't allow regular users to create point_servercommand entities for the same reason as blocking ent_fire
if ( !Q_stricmp( args[1], "point_servercommand" ) )
{
if ( engine->IsDedicatedServer() )
{
// We allow people with disabled autokick to do it, because they already have rcon.
if ( pPlayer->IsAutoKickDisabled() == false )
return;
}
else if ( gpGlobals->maxClients > 1 )
{
// On listen servers with more than 1 player, only allow the host to create point_servercommand.
CBasePlayer *pHostPlayer = UTIL_GetListenServerHost();
if ( pPlayer != pHostPlayer )
return;
}
}
bool allowPrecache = CBaseEntity::IsPrecacheAllowed();
CBaseEntity::SetAllowPrecache( true );
// Try to create entity
CBaseEntity *entity = dynamic_cast< CBaseEntity * >( CreateEntityByName(args[1]) );
if (entity)
{
// Pass in any additional parameters.
for ( int i = 2; i + 1 < args.ArgC(); i += 2 )
{
const char *pKeyName = args[i];
const char *pValue = args[i+1];
entity->KeyValue( pKeyName, pValue );
}
DispatchSpawn(entity);
// Now attempt to drop into the world
trace_t tr;
Vector forward;
pPlayer->EyeVectors( &forward );
UTIL_TraceLine(pPlayer->EyePosition(),
pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_SOLID,
pPlayer, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction != 1.0 )
{
// Raise the end position a little up off the floor, place the npc and drop him down
tr.endpos.z += 12;
if (CreateAimed())
{
QAngle angles;
VectorAngles( forward, angles );
angles.x = 0;
angles.z = 0;
entity->Teleport( &tr.endpos, &angles, NULL );
}
else
{
entity->Teleport( &tr.endpos, NULL, NULL );
}
UTIL_DropToFloor( entity, MASK_SOLID );
}
entity->Activate();
}
CBaseEntity::SetAllowPrecache( allowPrecache );
}
virtual int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands )
{
if ( !g_pGameRules )
{
return 0;
}
const char *cmdname = CreateAimed() ? "ent_create_aimed" : "ent_create";
char *substring = (char *)partial;
if ( Q_strstr( partial, cmdname ) )
{
substring = (char *)partial + strlen( cmdname ) + 1;
}
int checklen = Q_strlen( substring );
CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc );
return EntityFactory_AutoComplete( cmdname, commands, symbols, substring, checklen );
}
};
static CEntCreateAutoCompletionFunctor g_EntCreateAutoComplete;
static ConCommand ent_create("ent_create", &g_EntCreateAutoComplete, "Creates an entity of the given type where the player is looking. Additional parameters can be passed in in the form: ent_create <entity name> <param 1 name> <param 1> <param 2 name> <param 2>...<param N name> <param N>", FCVAR_GAMEDLL | FCVAR_CHEAT, &g_EntCreateAutoComplete);
class CEntCreateAimedAutoCompletionFunctor : public CEntCreateAutoCompletionFunctor
{
public:
virtual bool CreateAimed() { return true; }
};
static CEntCreateAimedAutoCompletionFunctor g_EntCreateAimedAutoComplete;
static ConCommand ent_create_aimed("ent_create_aimed", &g_EntCreateAimedAutoComplete, "Creates an entity of the given type where the player is looking. Additional parameters can be passed in in the form: ent_create_aimed <entity name> <param 1 name> <param 1> <param 2 name> <param 2>...<param N name> <param N>", FCVAR_CHEAT, &g_EntCreateAimedAutoComplete);
#else
//------------------------------------------------------------------------------
// Purpose: Create an NPC of the given type
//------------------------------------------------------------------------------
@ -8816,6 +8962,7 @@ void CC_Ent_Create( const CCommand& args )
CBaseEntity::SetAllowPrecache( allowPrecache );
}
static ConCommand ent_create("ent_create", CC_Ent_Create, "Creates an entity of the given type where the player is looking. Additional parameters can be passed in in the form: ent_create <entity name> <param 1 name> <param 1> <param 2 name> <param 2>...<param N name> <param N>", FCVAR_GAMEDLL | FCVAR_CHEAT);
#endif
//------------------------------------------------------------------------------
// Purpose: Teleport a specified entity to where the player is looking

View File

@ -700,6 +700,8 @@ public:
void InputSetLocalOrigin( inputdata_t &inputdata );
void InputSetLocalAngles( inputdata_t &inputdata );
void InputSetAbsOrigin( inputdata_t &inputdata );
void InputSetAbsAngles( inputdata_t &inputdata );
void InputSetLocalVelocity( inputdata_t &inputdata );
void InputSetLocalAngularVelocity( inputdata_t &inputdata );
@ -1267,6 +1269,18 @@ public:
virtual float GetDamage() { return 0; }
virtual void SetDamage(float flDamage) {}
#ifdef MAPBASE
// Some entities want to use interactions regardless of whether they're a CBaseCombatCharacter.
// Valve ran into this issue with frag grenades when they started deriving from CBaseAnimating instead of CBaseCombatCharacter,
// preventing them from using the barnacle interactions for rigged grenade timing so it's guaranteed to blow up in the barnacle's face.
// We're used to unaltered behavior now, so we're not restoring that as default, but making this a "base entity" thing is supposed to help in situtions like those.
//
// Also, keep in mind pretty much all existing DispatchInteraction() calls are only performed on CBaseCombatCharacters.
// You'll need to change their code manually if you want other, non-character entities to use the interaction.
bool DispatchInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ) { return ( interactionType > 0 ) ? HandleInteraction( interactionType, data, sourceEnt ) : false; }
virtual bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ) { return false; }
#endif
virtual Vector EyePosition( void ); // position of eyes
virtual const QAngle &EyeAngles( void ); // Direction of eyes in world space
virtual const QAngle &LocalEyeAngles( void ); // Direction of eyes

View File

@ -2004,10 +2004,17 @@ float CBaseFlex::PlayScene( const char *pszScene, float flDelay, AI_Response *re
// Input : *soundname -
// Output : float
//-----------------------------------------------------------------------------
#ifdef MAPBASE
float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname, float flDelay, AI_Response *response, IRecipientFilter *filter )
{
return InstancedAutoGeneratedSoundScene( this, soundname, NULL, flDelay, false, response, false, filter );
}
#else
float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname )
{
return InstancedAutoGeneratedSoundScene( this, soundname );
}
#endif

View File

@ -116,7 +116,11 @@ public:
void SentenceStop( void ) { EmitSound( "AI_BaseNPC.SentenceStop" ); }
virtual float PlayScene( const char *pszScene, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
#ifdef MAPBASE
virtual float PlayAutoGeneratedSoundScene( const char *soundname, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
#else
virtual float PlayAutoGeneratedSoundScene( const char *soundname );
#endif
virtual int GetSpecialDSP( void ) { return 0; }

View File

@ -1504,12 +1504,6 @@ void CItemSoda::CanTouch ( CBaseEntity *pOther )
// technology demo
//=========================================================
#ifdef MAPBASE
// I would leave this on the client, but it sems as if I could only precache the particle system on the server for some reason.
// That desn't sound right...look into this further later.
ConVar r_RainParticle( "r_RainParticle", "Rain_01_impact", FCVAR_CHEAT | FCVAR_REPLICATED );
#endif
class CPrecipitation : public CBaseEntity
{
public:
@ -1546,9 +1540,6 @@ void CPrecipitation::Spawn( void )
PrecacheMaterial( "effects/fleck_ash2" );
PrecacheMaterial( "effects/fleck_ash3" );
PrecacheMaterial( "effects/ember_swirling001" );
#ifdef MAPBASE
PrecacheParticleSystem( r_RainParticle.GetString() );
#endif
Precache();
SetSolid( SOLID_NONE ); // Remove model & collisions

View File

@ -152,6 +152,29 @@ public:
{
m_Value.Vector3D(vec);
}
#ifdef MAPBASE
// Shortcut to using QAngles in Vector outputs, makes it look cleaner and allows easy modification
void Init( const QAngle &value )
{
// reinterpret_cast<const Vector&>(value)
m_Value.SetAngle3D( value );
}
// Shortcut to using QAngles in Vector outputs, makes it look cleaner and allows easy modification
void Set( const QAngle &value, CBaseEntity *pActivator, CBaseEntity *pCaller )
{
// reinterpret_cast<const Vector&>(value)
m_Value.SetAngle3D( value );
FireOutput( m_Value, pActivator, pCaller );
}
// Shortcut to using QAngles in Vector outputs, makes it look cleaner and allows easy modification
void Get( QAngle &ang )
{
m_Value.Angle3D(ang);
}
#endif
};

View File

@ -40,6 +40,13 @@ public:
#ifdef MAPBASE
void InputSetBrightness( inputdata_t &inputdata );
void InputSetColorTransitionTime( inputdata_t &inputdata );
void InputSetXOffset( inputdata_t &inputdata ) { m_flEastOffset = inputdata.value.Float(); }
void InputSetYOffset( inputdata_t &inputdata ) { m_flForwardOffset = inputdata.value.Float(); }
void InputSetOrthoSize( inputdata_t &inputdata ) { m_flOrthoSize = inputdata.value.Float(); }
void InputSetDistance( inputdata_t &inputdata ) { m_flSunDistance = inputdata.value.Float(); }
void InputSetFOV( inputdata_t &inputdata ) { m_flFOV = inputdata.value.Float(); }
void InputSetNearZDistance( inputdata_t &inputdata ) { m_flNearZ = inputdata.value.Float(); }
void InputSetNorthOffset( inputdata_t &inputdata ) { m_flNorthOffset = inputdata.value.Float(); }
#endif
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
@ -101,14 +108,19 @@ BEGIN_DATADESC( CGlobalLight )
DEFINE_KEYFIELD( m_flColorTransitionTime, FIELD_FLOAT, "colortransitiontime" ),
// Inputs
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetXOffset", InputSetXOffset ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetYOffset", InputSetYOffset ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetOrthoSize", InputSetOrthoSize ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetDistance", InputSetDistance ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFOV", InputSetFOV ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearZDistance", InputSetNearZDistance ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNorthOffset", InputSetNorthOffset ),
#else
DEFINE_INPUT( m_flSunDistance, FIELD_FLOAT, "SetDistance" ),
DEFINE_INPUT( m_flFOV, FIELD_FLOAT, "SetFOV" ),
DEFINE_INPUT( m_flNearZ, FIELD_FLOAT, "SetNearZDistance" ),
DEFINE_INPUT( m_flNorthOffset, FIELD_FLOAT, "SetNorthOffset" ),
#ifdef MAPBASE
DEFINE_INPUT( m_flEastOffset, FIELD_FLOAT, "SetXOffset" ),
DEFINE_INPUT( m_flForwardOffset, FIELD_FLOAT, "SetYOffset" ),
DEFINE_INPUT( m_flOrthoSize, FIELD_FLOAT, "SetOrthoSize" ),
#endif
DEFINE_INPUTFUNC( FIELD_COLOR32, "LightColor", InputSetLightColor ),
@ -183,7 +195,11 @@ int CGlobalLight::UpdateTransmitState()
bool CGlobalLight::KeyValue( const char *szKeyName, const char *szValue )
{
#ifdef MAPBASE
if ( FStrEq( szKeyName, "lightcolor" ) || FStrEq( szKeyName, "color" ) )
#else
if ( FStrEq( szKeyName, "color" ) )
#endif
{
float tmp[4];
UTIL_StringToFloatArray( tmp, 4, szValue );

View File

@ -44,6 +44,12 @@ BEGIN_DATADESC( CEnvProjectedTexture )
DEFINE_KEYFIELD( m_flBrightnessScale, FIELD_FLOAT, "brightnessscale" ),
DEFINE_FIELD( m_LightColor, FIELD_COLOR32 ),
DEFINE_KEYFIELD( m_flColorTransitionTime, FIELD_FLOAT, "colortransitiontime" ),
#ifdef MAPBASE
DEFINE_FIELD( m_flConstantAtten, FIELD_FLOAT ),
DEFINE_FIELD( m_flLinearAtten, FIELD_FLOAT ),
DEFINE_FIELD( m_flQuadraticAtten, FIELD_FLOAT ),
DEFINE_KEYFIELD( m_flShadowAtten, FIELD_FLOAT, "shadowatten" ),
#endif
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
@ -66,9 +72,14 @@ BEGIN_DATADESC( CEnvProjectedTexture )
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetSpotlightFrame", InputSetSpotlightFrame ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetBrightness", InputSetBrightness ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetColorTransitionTime", InputSetColorTransitionTime ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetQuadratic", InputSetQuadratic ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetLinear", InputSetLinear ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetConstant", InputSetConstant ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetShadowAtten", InputSetShadowAtten ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetNearZ", InputSetNearZ ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFarZ", InputSetFarZ ),
DEFINE_INPUTFUNC( FIELD_VOID, "AlwaysDrawOn", InputAlwaysDrawOn ),
DEFINE_INPUTFUNC( FIELD_VOID, "AlwaysDrawOff", InputAlwaysDrawOff ),
DEFINE_INPUTFUNC( FIELD_VOID, "StopFollowingTarget", InputStopFollowingTarget ),
DEFINE_INPUTFUNC( FIELD_VOID, "StartFollowingTarget", InputStartFollowingTarget ),
#endif
@ -100,6 +111,10 @@ IMPLEMENT_SERVERCLASS_ST( CEnvProjectedTexture, DT_EnvProjectedTexture )
SendPropFloat( SENDINFO( m_flFarZ ), 18, SPROP_ROUNDDOWN, 0.0f, 1500.0f ),
SendPropInt( SENDINFO( m_nShadowQuality ), 1, SPROP_UNSIGNED ), // Just one bit for now
#ifdef MAPBASE
SendPropFloat( SENDINFO( m_flConstantAtten ) ),
SendPropFloat( SENDINFO( m_flLinearAtten ) ),
SendPropFloat( SENDINFO( m_flQuadraticAtten ) ),
SendPropFloat( SENDINFO( m_flShadowAtten ) ),
SendPropBool( SENDINFO( m_bAlwaysDraw ) ),
// Not needed on the client right now, change when it actually is needed
@ -128,11 +143,21 @@ CEnvProjectedTexture::CEnvProjectedTexture( void )
m_nSpotlightTextureFrame = 0;
m_flBrightnessScale = 1.0f;
m_LightColor.Init( 255, 255, 255, 255 );
#ifdef MAPBASE
m_flColorTransitionTime = 0.0f;
#else
m_flColorTransitionTime = 0.5f;
#endif
m_flAmbient = 0.0f;
m_flNearZ = 4.0f;
m_flFarZ = 750.0f;
m_nShadowQuality = 0;
#ifdef MAPBASE
m_flQuadraticAtten = 0.0f;
m_flLinearAtten = 100.0f;
m_flConstantAtten = 0.0f;
m_flShadowAtten = 0.0f;
#endif
}
void UTIL_ColorStringToLinearFloatColor( Vector &color, const char *pString )
@ -195,6 +220,20 @@ bool CEnvProjectedTexture::KeyValue( const char *szKeyName, const char *szValue
Q_strcpy( m_SpotlightTextureName.GetForModify(), szValue );
#endif
}
#ifdef MAPBASE
else if ( FStrEq( szKeyName, "constant_attn" ) )
{
m_flConstantAtten = CorrectConstantAtten( atof( szValue ) );
}
else if ( FStrEq( szKeyName, "linear_attn" ) )
{
m_flLinearAtten = CorrectLinearAtten( atof( szValue ) );
}
else if ( FStrEq( szKeyName, "quadratic_attn" ) )
{
m_flQuadraticAtten = CorrectQuadraticAtten( atof( szValue ) );
}
#endif
else
{
return BaseClass::KeyValue( szKeyName, szValue );
@ -215,6 +254,26 @@ bool CEnvProjectedTexture::GetKeyValue( const char *szKeyName, char *szValue, in
Q_snprintf( szValue, iMaxLen, "%s", m_SpotlightTextureName.Get() );
return true;
}
#ifdef MAPBASE
else if ( FStrEq( szKeyName, "constant_attn" ) )
{
// Undo correction
Q_snprintf( szValue, iMaxLen, "%f", m_flConstantAtten *= 2.0f );
return true;
}
else if ( FStrEq( szKeyName, "linear_attn" ) )
{
// Undo correction
Q_snprintf( szValue, iMaxLen, "%f", m_flLinearAtten *= 0.01f );
return true;
}
else if ( FStrEq( szKeyName, "quadratic_attn" ) )
{
// Undo correction
Q_snprintf( szValue, iMaxLen, "%f", m_flQuadraticAtten *= 0.0001f );
return true;
}
#endif
return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
}

View File

@ -54,12 +54,21 @@ public:
void InputSetSpotlightFrame( inputdata_t &inputdata );
void InputSetBrightness( inputdata_t &inputdata );
void InputSetColorTransitionTime( inputdata_t &inputdata );
void InputSetConstant( inputdata_t &inputdata ) { m_flConstantAtten = CorrectConstantAtten(inputdata.value.Float()); }
void InputSetLinear( inputdata_t &inputdata ) { m_flLinearAtten = CorrectLinearAtten(inputdata.value.Float()); }
void InputSetQuadratic( inputdata_t &inputdata ) { m_flQuadraticAtten = CorrectQuadraticAtten(inputdata.value.Float()); }
void InputSetShadowAtten( inputdata_t &inputdata ) { m_flShadowAtten = inputdata.value.Float(); }
void InputSetNearZ( inputdata_t &inputdata );
void InputSetFarZ( inputdata_t &inputdata );
void InputAlwaysDrawOn( inputdata_t &inputdata ) { m_bAlwaysDraw = true; }
void InputAlwaysDrawOff( inputdata_t &inputdata ) { m_bAlwaysDraw = false; }
void InputStopFollowingTarget( inputdata_t &inputdata ) { m_bDontFollowTarget = true; }
void InputStartFollowingTarget( inputdata_t &inputdata ) { m_bDontFollowTarget = false; }
// Corrects keyvalue/input attenuation for internal FlashlightEffect_t attenuation.
float CorrectConstantAtten( float fl ) { return fl * 0.5f; }
float CorrectLinearAtten( float fl ) { return fl * 100.0f; }
float CorrectQuadraticAtten( float fl ) { return fl * 10000.0f; }
#endif
void InitialThink( void );
@ -91,11 +100,17 @@ private:
CNetworkVar( float, m_flFarZ );
CNetworkVar( int, m_nShadowQuality );
#ifdef MAPBASE
CNetworkVar( float, m_flConstantAtten );
CNetworkVar( float, m_flLinearAtten );
CNetworkVar( float, m_flQuadraticAtten );
CNetworkVar( float, m_flShadowAtten );
CNetworkVar( bool, m_bAlwaysDraw );
// 1 = New projected texture
// 0 = Non-Mapbase projected texture, e.g. one that uses the VDC parenting fix instead of the spawnflag
CNetworkVar( bool, m_bProjectedTextureVersion );
// Not needed on the client right now, change to CNetworkVar when it actually is needed
bool m_bProjectedTextureVersion;
#endif
};
#endif

View File

@ -3504,7 +3504,13 @@ void CNPC_Hunter::StartTask( const Task_t *pTask )
{
SetLastAttackTime( gpGlobals->curtime );
#ifdef MAPBASE
// The "VS_PLAYER" animation looks better than the regular animation when used against non-humans
if ( GetEnemy() && (GetEnemy()->IsPlayer() ||
(GetEnemy()->IsCombatCharacter() && GetEnemy()->MyCombatCharacterPointer()->GetHullType() != HULL_HUMAN)) )
#else
if ( GetEnemy() && GetEnemy()->IsPlayer() )
#endif
{
ResetIdealActivity( ( Activity )ACT_HUNTER_MELEE_ATTACK1_VS_PLAYER );
}

View File

@ -369,6 +369,11 @@ BEGIN_DATADESC( CPropJeepEpisodic )
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetCargoHopperVisibility", InputSetCargoVisibility ),
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_VOID, "EnableHazardLights", InputEnableHazardLights ),
DEFINE_INPUTFUNC( FIELD_VOID, "DisableHazardLights", InputDisableHazardLights ),
#endif
END_DATADESC();
IMPLEMENT_SERVERCLASS_ST(CPropJeepEpisodic, DT_CPropJeepEpisodic)
@ -1422,6 +1427,26 @@ void CPropJeepEpisodic::DestroyHazardLights( void )
SetContextThink( NULL, gpGlobals->curtime, "HazardBlink" );
}
#ifdef MAPBASE
void CPropJeepEpisodic::InputEnableHazardLights( inputdata_t &data )
{
if (m_bNoHazardLights)
{
m_bNoHazardLights = false;
CreateHazardLights();
}
}
void CPropJeepEpisodic::InputDisableHazardLights( inputdata_t &data )
{
if (!m_bNoHazardLights)
{
m_bNoHazardLights = true;
DestroyHazardLights();
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
// Input : nRole -

View File

@ -104,6 +104,10 @@ private:
void InputEnableRadarDetectEnemies( inputdata_t &data );
void InputAddBusterToCargo( inputdata_t &data );
void InputSetCargoVisibility( inputdata_t &data );
#ifdef MAPBASE
void InputEnableHazardLights( inputdata_t &data );
void InputDisableHazardLights( inputdata_t &data );
#endif
void InputOutsideTransition( inputdata_t &data );
#ifndef MAPBASE
void InputDisablePhysGun( inputdata_t &data );

View File

@ -17,6 +17,10 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef MAPBASE
ConVar explosion_sparks("explosion_sparks", "0", FCVAR_NONE);
#endif
//-----------------------------------------------------------------------------
// Purpose: Spark shower, created by the explosion entity.
//-----------------------------------------------------------------------------
@ -358,7 +362,11 @@ void CEnvExplosion::InputExplode( inputdata_t &inputdata )
SetNextThink( gpGlobals->curtime + 0.3 );
// Only do these effects if we're not submerged
#ifdef MAPBASE
if ( explosion_sparks.GetBool() && !(UTIL_PointContents( GetAbsOrigin() ) & CONTENTS_WATER) )
#else
if ( UTIL_PointContents( GetAbsOrigin() ) & CONTENTS_WATER )
#endif
{
// draw sparks
if ( !( m_spawnflags & SF_ENVEXPLOSION_NOSPARKS ) )

View File

@ -171,6 +171,12 @@ class CFilterMultiple : public CBaseFilter
bool PassesDamageFilterImpl(const CTakeDamageInfo &info);
#endif
void Activate(void);
#ifdef MAPBASE
bool BloodAllowed( CBaseEntity *pCaller, const CTakeDamageInfo &info );
bool PassesFinalDamageFilter( CBaseEntity *pCaller, const CTakeDamageInfo &info );
bool DamageMod( CBaseEntity *pCaller, CTakeDamageInfo &info );
#endif
};
LINK_ENTITY_TO_CLASS(filter_multi, CFilterMultiple);
@ -304,9 +310,9 @@ bool CFilterMultiple::PassesDamageFilterImpl(const CTakeDamageInfo &info)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
#ifdef MAPBASE
if (!pFilter->PassesDamageFilter(pCaller, info))
if (pFilter->PassesDamageFilter(pCaller, info))
#else
if (!pFilter->PassesDamageFilter(info))
if (pFilter->PassesDamageFilter(info))
#endif
{
return true;
@ -317,6 +323,125 @@ bool CFilterMultiple::PassesDamageFilterImpl(const CTakeDamageInfo &info)
}
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Returns true if blood should be allowed, false if not.
// Input : pEntity - Entity to test.
//-----------------------------------------------------------------------------
bool CFilterMultiple::BloodAllowed( CBaseEntity *pCaller, const CTakeDamageInfo &info )
{
// Test against each filter
if (m_nFilterType == FILTER_AND)
{
for (int i=0;i<MAX_FILTERS;i++)
{
if (m_hFilter[i] != NULL)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
if (!pFilter->BloodAllowed(pCaller, info))
{
return false;
}
}
}
return true;
}
else // m_nFilterType == FILTER_OR
{
for (int i=0;i<MAX_FILTERS;i++)
{
if (m_hFilter[i] != NULL)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
if (pFilter->BloodAllowed(pCaller, info))
{
return true;
}
}
}
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if the entity passes our filter, false if not.
// Input : pEntity - Entity to test.
//-----------------------------------------------------------------------------
bool CFilterMultiple::PassesFinalDamageFilter( CBaseEntity *pCaller, const CTakeDamageInfo &info )
{
// Test against each filter
if (m_nFilterType == FILTER_AND)
{
for (int i=0;i<MAX_FILTERS;i++)
{
if (m_hFilter[i] != NULL)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
if (!pFilter->PassesFinalDamageFilter(pCaller, info))
{
return false;
}
}
}
return true;
}
else // m_nFilterType == FILTER_OR
{
for (int i=0;i<MAX_FILTERS;i++)
{
if (m_hFilter[i] != NULL)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
if (pFilter->PassesFinalDamageFilter(pCaller, info))
{
return true;
}
}
}
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if damage should be modded, false if not.
// Input : pEntity - Entity to test.
//-----------------------------------------------------------------------------
bool CFilterMultiple::DamageMod( CBaseEntity *pCaller, CTakeDamageInfo &info )
{
// Test against each filter
if (m_nFilterType == FILTER_AND)
{
for (int i=0;i<MAX_FILTERS;i++)
{
if (m_hFilter[i] != NULL)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
if (!pFilter->DamageMod(pCaller, info))
{
return false;
}
}
}
return true;
}
else // m_nFilterType == FILTER_OR
{
for (int i=0;i<MAX_FILTERS;i++)
{
if (m_hFilter[i] != NULL)
{
CBaseFilter* pFilter = (CBaseFilter *)(m_hFilter[i].Get());
if (pFilter->DamageMod(pCaller, info))
{
return true;
}
}
}
return false;
}
}
#endif
// ###################################################################
// > FilterName

View File

@ -1059,11 +1059,6 @@ void CBreakable::Die( void )
iCount = func_break_max_pieces.GetInt();
}
#ifdef MAPBASE
// TEMP TEMP TEMP TEMP
DevMsg("vSize: %f %f %f\n", vSize.x, vSize.y, vSize.z);
#endif
ConVarRef breakable_disable_gib_limit( "breakable_disable_gib_limit" );
if ( !breakable_disable_gib_limit.GetBool() && iCount )
{

View File

@ -89,6 +89,9 @@
#include "tier3/tier3.h"
#include "serverbenchmark_base.h"
#include "querycache.h"
#ifdef MAPBASE
#include "world.h"
#endif
#ifdef TF_DLL
@ -701,6 +704,9 @@ bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory,
IGameSystem::Add( SoundEmitterSystem() );
// load Mod specific game events ( MUST be before InitAllSystems() so it can pickup the mod specific events)
#ifdef MAPBASE
gameeventmanager->LoadEventsFromFile("resource/MapbaseEvents.res");
#endif
gameeventmanager->LoadEventsFromFile("resource/ModEvents.res");
#ifdef CSTRIKE_DLL // BOTPORT: TODO: move these ifdefs out
@ -1733,6 +1739,17 @@ void CServerGameDLL::GetTitleName( const char *pMapName, char* pTitleBuff, int t
return;
}
}
#ifdef MAPBASE
// Check the world entity for a chapter title.
if ( CWorld *pWorld = GetWorldEntity() )
{
const char *pWorldChapter = pWorld->GetChapterTitle();
if ( pWorldChapter && pWorldChapter[0] != '\0' )
Q_strncpy( chapterTitle, pWorldChapter, sizeof( chapterTitle ) );
}
#endif
Q_strncpy( pTitleBuff, pMapName, titleBuffSize );
}
#endif
@ -1770,6 +1787,16 @@ void CServerGameDLL::GetSaveComment( char *text, int maxlength, float flMinutes,
break;
}
}
#ifdef MAPBASE
// Check the world entity for a chapter title.
if ( CWorld *pWorld = GetWorldEntity() )
{
const char *pWorldChapter = pWorld->GetChapterTitle();
if ( pWorldChapter && pWorldChapter[0] != '\0' )
pName = pWorldChapter;
}
#endif
// If we didn't get one, use the designer's map name, or the BSP name itself
if ( !pName )
@ -2065,6 +2092,16 @@ void UpdateChapterRestrictions( const char *mapname )
}
}
#ifdef MAPBASE
// Check the world entity for a chapter title.
if ( CWorld *pWorld = GetWorldEntity() )
{
const char *pWorldChapter = pWorld->GetChapterTitle();
if ( pWorldChapter && pWorldChapter[0] != '\0' )
Q_strncpy( chapterTitle, pWorldChapter, sizeof( chapterTitle ) );
}
#endif
if ( !chapterTitle[0] )
return;

View File

@ -17,6 +17,9 @@
#include "tier1/strtools.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
#ifdef MAPBASE
#include "ai_speech.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@ -148,10 +151,11 @@ void CGenericActor::Spawn()
m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result )
m_NPCState = NPC_STATE_NONE;
CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS );
#ifdef MAPBASE
CapabilitiesAdd( bits_CAP_SQUAD );
CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_DOORS_GROUP );
#else
CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS );
#endif
// remove head turn if no eyes or forward attachment
@ -187,6 +191,163 @@ void CGenericActor::Precache()
#ifdef MAPBASE
//=========================================================
#define TLK_ACTOR_PAIN "TLK_WOUND"
#define TLK_ACTOR_DEATH "TLK_DEATH"
#define TLK_ACTOR_ALERT "TLK_STARTCOMBAT"
#define TLK_ACTOR_IDLE "TLK_IDLE"
#define TLK_ACTOR_FEAR "TLK_FEAR"
#define TLK_ACTOR_LOSTENEMY "TLK_LOSTENEMY"
#define TLK_ACTOR_FOUNDENEMY "TLK_REFINDENEMY"
//=========================================================
// Enhanced generic actor with built-in response system usage, weapon capabilities, and more.
//=========================================================
class CGenericActorCustom : public CGenericActor
{
private:
DECLARE_CLASS( CGenericActorCustom, CGenericActor );
public:
//DECLARE_DATADESC();
CGenericActorCustom() { }
void Spawn( void );
void Precache( void );
bool KeyValue( const char *szKeyName, const char *szValue );
void SpeakIfAllowed( const char *concept, AI_CriteriaSet *modifiers = NULL );
void ModifyOrAppendCriteria( AI_CriteriaSet& set );
void PainSound( const CTakeDamageInfo &info );
void DeathSound( const CTakeDamageInfo &info );
void AlertSound( void );
void IdleSound( void );
void FearSound( void );
void LostEnemySound( void );
void FoundEnemySound( void );
};
LINK_ENTITY_TO_CLASS( generic_actor_custom, CGenericActorCustom );
//BEGIN_DATADESC( CGenericActorCustom )
//END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::Spawn()
{
BaseClass::Spawn();
CapabilitiesAdd( bits_CAP_USE_WEAPONS );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::Precache()
{
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose: Cache user entity field values until spawn is called.
// Input : szKeyName - Key to handle.
// szValue - Value for key.
// Output : Returns true if the key was handled, false if not.
//-----------------------------------------------------------------------------
bool CGenericActorCustom::KeyValue( const char *szKeyName, const char *szValue )
{
if (FStrEq(szKeyName, "UseShotRegulator"))
{
if (atoi(szValue) > 0)
CapabilitiesAdd( bits_CAP_USE_SHOT_REGULATOR );
else
CapabilitiesRemove( bits_CAP_USE_SHOT_REGULATOR );
return true;
}
return BaseClass::KeyValue( szKeyName, szValue );
}
//-----------------------------------------------------------------------------
// Purpose: Speak concept
//-----------------------------------------------------------------------------
void CGenericActorCustom::SpeakIfAllowed( const char *concept, AI_CriteriaSet *modifiers )
{
Speak( concept, modifiers ? *modifiers : AI_CriteriaSet() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::ModifyOrAppendCriteria( AI_CriteriaSet& set )
{
BaseClass::ModifyOrAppendCriteria( set );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::PainSound( const CTakeDamageInfo &info )
{
AI_CriteriaSet modifiers;
ModifyOrAppendDamageCriteria( modifiers, info );
SpeakIfAllowed( TLK_ACTOR_PAIN, &modifiers );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::DeathSound( const CTakeDamageInfo &info )
{
AI_CriteriaSet modifiers;
ModifyOrAppendDamageCriteria( modifiers, info );
SpeakIfAllowed( TLK_ACTOR_DEATH, &modifiers );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::AlertSound( void )
{
SpeakIfAllowed( TLK_ACTOR_ALERT );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::IdleSound( void )
{
SpeakIfAllowed( TLK_ACTOR_IDLE );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::FearSound( void )
{
SpeakIfAllowed( TLK_ACTOR_FEAR );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::LostEnemySound( void )
{
SpeakIfAllowed( TLK_ACTOR_LOSTENEMY );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGenericActorCustom::FoundEnemySound( void )
{
SpeakIfAllowed( TLK_ACTOR_FOUNDENEMY );
}
#endif

View File

@ -1283,6 +1283,38 @@ void CBounceBomb::CloseHooks()
#endif
}
#ifdef MAPBASE
extern int g_interactionBarnacleVictimBite;
extern int g_interactionBarnacleVictimFinalBite;
extern int ACT_BARNACLE_BITE_SMALL_THINGS;
//-----------------------------------------------------------------------------
// Purpose: Uses the new CBaseEntity interaction implementation and
// replaces the dynamic_casting from npc_barnacle
// Input : The type of interaction, extra info pointer, and who started it
// Output : true - if sub-class has a response for the interaction
// false - if sub-class has no response
//-----------------------------------------------------------------------------
bool CBounceBomb::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt )
{
// This was originally done in npc_barnacle itself, but
// we've transitioned to interactions so we could extend special behavior to others
// without just adding more casting.
if ( interactionType == g_interactionBarnacleVictimBite )
{
Assert( sourceEnt && sourceEnt->IsNPC() );
sourceEnt->MyNPCPointer()->SetActivity( (Activity)ACT_BARNACLE_BITE_SMALL_THINGS );
return true;
}
else if ( interactionType == g_interactionBarnacleVictimFinalBite )
{
ExplodeThink();
return true;
}
return BaseClass::HandleInteraction(interactionType, data, sourceEnt);
}
#endif
//---------------------------------------------------------
//---------------------------------------------------------
void CBounceBomb::InputDisarm( inputdata_t &inputdata )

View File

@ -83,6 +83,11 @@ public:
void OpenHooks( bool bSilent = false );
void CloseHooks();
#ifdef MAPBASE
// Uses the new CBaseEntity interaction implementation and replaces the dynamic_casting from npc_barnacle
bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt );
#endif
DECLARE_DATADESC();
static string_t gm_iszFloorTurretClassname;

View File

@ -297,7 +297,7 @@ public:
~CCommandRedirect()
{
g_pCommandRedirects.AddToTail(this);
g_pCommandRedirects.FindAndRemove(this);
/*
for (int i = 0; i < g_pCommandRedirects.Count(); i++)
{
@ -1790,7 +1790,16 @@ bool CHL2_Player::CommanderFindGoal( commandgoal_t *pGoal )
//---------------------------------
// MASK_SHOT on purpose! So that you don't hit the invisible hulls of the NPCs.
#ifdef MAPBASE
// Get either our +USE entity or the gravity gun entity
CBaseEntity *pHeldEntity = GetPlayerHeldEntity(this);
if ( !pHeldEntity )
PhysCannonGetHeldEntity( GetActiveWeapon() );
CTraceFilterSkipTwoEntities filter( this, pHeldEntity, COLLISION_GROUP_INTERACTIVE_DEBRIS );
#else
CTraceFilterSkipTwoEntities filter( this, PhysCannonGetHeldEntity( GetActiveWeapon() ), COLLISION_GROUP_INTERACTIVE_DEBRIS );
#endif
UTIL_TraceLine( EyePosition(), EyePosition() + forward * MAX_COORD_RANGE, MASK_SHOT, &filter, &tr );

View File

@ -589,6 +589,10 @@ class CTriggerWateryDeath : public CBaseTrigger
public:
DECLARE_DATADESC();
#ifdef MAPBASE
CTriggerWateryDeath();
#endif
void Spawn( void );
void Precache( void );
void Touch( CBaseEntity *pOther );
@ -614,6 +618,13 @@ private:
CUtlVector< float > m_flEntityKillTimes;
float m_flNextPullSound;
float m_flPainValue;
#ifdef MAPBASE
float m_flBiteInterval;
float m_flPainStep;
float m_flMaxPain;
COutputInt m_OnDamage;
#endif
};
BEGIN_DATADESC( CTriggerWateryDeath )
@ -621,6 +632,12 @@ BEGIN_DATADESC( CTriggerWateryDeath )
DEFINE_UTLVECTOR( m_hLeeches, FIELD_EHANDLE ),
DEFINE_FIELD( m_flNextPullSound, FIELD_TIME ),
DEFINE_FIELD( m_flPainValue, FIELD_FLOAT ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_flBiteInterval, FIELD_FLOAT, "BiteInterval" ),
DEFINE_KEYFIELD( m_flPainStep, FIELD_FLOAT, "PainStep" ),
DEFINE_KEYFIELD( m_flMaxPain, FIELD_FLOAT, "MaxPain" ),
DEFINE_OUTPUT( m_OnDamage, "OnDamage" ),
#endif
END_DATADESC()
@ -631,6 +648,15 @@ LINK_ENTITY_TO_CLASS( trigger_waterydeath, CTriggerWateryDeath );
#define WD_PAINVALUE_STEP 2.0
#define WD_MAX_DAMAGE 15.0f
#ifdef MAPBASE
CTriggerWateryDeath::CTriggerWateryDeath()
{
m_flBiteInterval = WD_KILLTIME_NEXT_BITE;
m_flPainStep = WD_PAINVALUE_STEP;
m_flMaxPain = WD_MAX_DAMAGE;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Called when spawning, after keyvalues have been handled.
//-----------------------------------------------------------------------------
@ -707,6 +733,23 @@ void CTriggerWateryDeath::Touch( CBaseEntity *pOther )
{
//EmitSound( filter, entindex(), "WateryDeath.Bite", &pOther->GetAbsOrigin() );
// Kill it
#ifdef MAPBASE
if ( pOther->IsPlayer() )
{
m_flPainValue = MIN( m_flPainValue + m_flPainStep, m_flMaxPain );
}
else
{
m_flPainValue = m_flMaxPain;
}
// Do nothing if there is no damage
if (m_flPainValue <= 0.0f)
{
m_flEntityKillTimes[iIndex] = gpGlobals->curtime + m_flBiteInterval;
return;
}
#else
if ( pOther->IsPlayer() )
{
m_flPainValue = MIN( m_flPainValue + WD_PAINVALUE_STEP, WD_MAX_DAMAGE );
@ -715,6 +758,7 @@ void CTriggerWateryDeath::Touch( CBaseEntity *pOther )
{
m_flPainValue = WD_MAX_DAMAGE;
}
#endif
// Use DMG_GENERIC & make the target inflict the damage on himself.
// This ensures that if the target is the player, the damage isn't modified by skill
@ -723,7 +767,13 @@ void CTriggerWateryDeath::Touch( CBaseEntity *pOther )
GuessDamageForce( &info, (pOther->GetAbsOrigin() - GetAbsOrigin()), pOther->GetAbsOrigin() );
pOther->TakeDamage( info );
#ifdef MAPBASE
m_OnDamage.Set(m_flPainValue, pOther, this);
m_flEntityKillTimes[iIndex] = gpGlobals->curtime + m_flBiteInterval;
#else
m_flEntityKillTimes[iIndex] = gpGlobals->curtime + WD_KILLTIME_NEXT_BITE;
#endif
}
}

View File

@ -226,6 +226,7 @@ BEGIN_DATADESC( CNPC_BaseZombie )
#ifdef MAPBASE
DEFINE_OUTPUT( m_OnSwattedProp, "OnSwattedProp" ),
DEFINE_OUTPUT( m_OnCrab, "OnCrab" ),
#endif
END_DATADESC()
@ -1089,6 +1090,10 @@ bool CNPC_BaseZombie::ShouldIgniteZombieGib( void )
#endif
}
#ifdef MAPBASE
extern CBaseAnimating *CreateServerRagdollSubmodel( CBaseAnimating *pOwner, const char *pModelName, const Vector &position, const QAngle &angles, int collisionGroup );
#endif
//-----------------------------------------------------------------------------
// Purpose: Handle the special case of a zombie killed by a physics chopper.
//-----------------------------------------------------------------------------
@ -1138,9 +1143,32 @@ void CNPC_BaseZombie::DieChopped( const CTakeDamageInfo &info )
vecLegsForce.z *= -10;
}
#ifdef MAPBASE
CBaseEntity *pLegGib = NULL;
if ( m_bForceServerRagdoll )
{
pLegGib = CreateServerRagdollSubmodel( this, GetLegsModel(), GetAbsOrigin(), GetAbsAngles(), COLLISION_GROUP_INTERACTIVE_DEBRIS );
pLegGib->VPhysicsGetObject()->AddVelocity(&vecLegsForce, NULL);
if (ShouldIgniteZombieGib())
static_cast<CBaseAnimating*>(pLegGib)->Ignite( random->RandomFloat( 8.0, 12.0 ), false );
if ( flFadeTime > 0.0 )
{
pLegGib->SUB_StartFadeOut( flFadeTime );
}
}
else
pLegGib = CreateRagGib( GetLegsModel(), GetAbsOrigin(), GetAbsAngles(), vecLegsForce, flFadeTime, ShouldIgniteZombieGib() );
#else
CBaseEntity *pLegGib = CreateRagGib( GetLegsModel(), GetAbsOrigin(), GetAbsAngles(), vecLegsForce, flFadeTime, ShouldIgniteZombieGib() );
#endif
if ( pLegGib )
{
#ifdef MAPBASE
// Inherit some misc. properties
pLegGib->m_iViewHideFlags = m_iViewHideFlags;
#endif
CopyRenderColorTo( pLegGib );
}
@ -1157,7 +1185,25 @@ void CNPC_BaseZombie::DieChopped( const CTakeDamageInfo &info )
QAngle TorsoAngles;
TorsoAngles = GetAbsAngles();
TorsoAngles.x -= 90.0f;
#ifdef MAPBASE
CBaseEntity *pTorsoGib = NULL;
if ( m_bForceServerRagdoll )
{
pTorsoGib = CreateServerRagdollSubmodel( this, GetTorsoModel(), GetAbsOrigin() + Vector( 0, 0, 64 ), TorsoAngles, COLLISION_GROUP_INTERACTIVE_DEBRIS );
pTorsoGib->VPhysicsGetObject()->AddVelocity(&forceVector, NULL);
if (ShouldIgniteZombieGib())
static_cast<CBaseAnimating*>(pLegGib)->Ignite( random->RandomFloat( 8.0, 12.0 ), false );
if ( flFadeTime > 0.0 )
{
pTorsoGib->SUB_StartFadeOut( flFadeTime );
}
}
else
pTorsoGib = CreateRagGib( GetTorsoModel(), GetAbsOrigin() + Vector( 0, 0, 64 ), TorsoAngles, forceVector, flFadeTime, ShouldIgniteZombieGib() );
#else
CBaseEntity *pTorsoGib = CreateRagGib( GetTorsoModel(), GetAbsOrigin() + Vector( 0, 0, 64 ), TorsoAngles, forceVector, flFadeTime, ShouldIgniteZombieGib() );
#endif
if ( pTorsoGib )
{
CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pTorsoGib);
@ -1166,6 +1212,11 @@ void CNPC_BaseZombie::DieChopped( const CTakeDamageInfo &info )
pAnimating->SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless );
}
#ifdef MAPBASE
// Inherit some misc. properties
pTorsoGib->m_iViewHideFlags = m_iViewHideFlags;
#endif
pTorsoGib->SetOwnerEntity( this );
CopyRenderColorTo( pTorsoGib );
@ -2294,7 +2345,23 @@ void CNPC_BaseZombie::BecomeTorso( const Vector &vecTorsoForce, const Vector &ve
if ( m_fIsTorso == true )
{
// -40 on Z to make up for the +40 on Z that we did above. This stops legs spawning above the head.
#ifdef MAPBASE
CBaseEntity *pGib = NULL;
if ( m_bForceServerRagdoll )
{
pGib = CreateServerRagdollSubmodel( this, GetLegsModel(), GetAbsOrigin() - Vector(0, 0, 40), GetAbsAngles(), COLLISION_GROUP_INTERACTIVE_DEBRIS );
pGib->VPhysicsGetObject()->AddVelocity( &vecLegsForce, NULL );
if (flFadeTime > 0.0)
{
pGib->SUB_StartFadeOut( flFadeTime );
}
}
else
pGib = CreateRagGib( GetLegsModel(), GetAbsOrigin() - Vector(0, 0, 40), GetAbsAngles(), vecLegsForce, flFadeTime );
#else
CBaseEntity *pGib = CreateRagGib( GetLegsModel(), GetAbsOrigin() - Vector(0, 0, 40), GetAbsAngles(), vecLegsForce, flFadeTime );
#endif
// don't collide with this thing ever
if ( pGib )
@ -2430,7 +2497,22 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
if( fRagdollCrab )
{
//Vector vecForce = Vector( 0, 0, random->RandomFloat( 700, 1100 ) );
#ifdef MAPBASE
CBaseEntity *pGib = NULL;
if ( m_bForceServerRagdoll )
{
pGib = CreateServerRagdollSubmodel( this, GetHeadcrabModel(), vecOrigin, GetLocalAngles(), COLLISION_GROUP_INTERACTIVE_DEBRIS );
pGib->VPhysicsGetObject()->AddVelocity(&vecVelocity, NULL);
if (ShouldIgniteZombieGib())
static_cast<CBaseAnimating*>(pGib)->Ignite( random->RandomFloat( 8.0, 12.0 ), false );
pGib->SUB_StartFadeOut( 15 );
}
else
pGib = CreateRagGib( GetHeadcrabModel(), vecOrigin, GetLocalAngles(), vecVelocity, 15, ShouldIgniteZombieGib() );
#else
CBaseEntity *pGib = CreateRagGib( GetHeadcrabModel(), vecOrigin, GetLocalAngles(), vecVelocity, 15, ShouldIgniteZombieGib() );
#endif
if ( pGib )
{
@ -2449,6 +2531,11 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
return;
}
#ifdef MAPBASE
// Inherit some misc. properties
pGib->m_iViewHideFlags = m_iViewHideFlags;
#endif
pGib->SetOwnerEntity( this );
CopyRenderColorTo( pGib );
@ -2488,6 +2575,12 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
// add on the parent flags
pCrab->AddSpawnFlags( m_spawnflags & ZOMBIE_CRAB_INHERITED_SPAWNFLAGS );
#ifdef MAPBASE
// Inherit some misc. properties
pCrab->m_bForceServerRagdoll = m_bForceServerRagdoll;
pCrab->m_iViewHideFlags = m_iViewHideFlags;
#endif
// make me the crab's owner to avoid collision issues
pCrab->SetOwnerEntity( this );
@ -2541,6 +2634,10 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
CopyRenderColorTo( pCrab );
pCrab->Activate();
#ifdef MAPBASE
m_OnCrab.Set( pCrab, pCrab, this );
#endif
}
if( fRemoveHead )

View File

@ -265,6 +265,7 @@ protected:
EHANDLE m_hPhysicsEnt;
#ifdef MAPBASE
COutputEHANDLE m_OnSwattedProp;
COutputEHANDLE m_OnCrab;
#endif
float m_flNextMoanSound;

View File

@ -40,6 +40,10 @@ ConVar sk_barnacle_health( "sk_barnacle_health","0");
static ConVar npc_barnacle_swallow( "npc_barnacle_swallow", "0", 0, "Use prototype swallow code." );
#ifdef MAPBASE
ConVar npc_barnacle_ignite( "npc_barnacle_ignite", "0", FCVAR_NONE, "Allows barnacles to be ignited by flares and beyond." );
#endif
const char *CNPC_Barnacle::m_szGibNames[NUM_BARNACLE_GIBS] =
{
"models/gibs/hgibs.mdl",
@ -69,6 +73,9 @@ int g_interactionBarnacleVictimDangle = 0;
int g_interactionBarnacleVictimReleased = 0;
int g_interactionBarnacleVictimGrab = 0;
int g_interactionBarnacleVictimBite = 0;
#ifdef MAPBASE
int g_interactionBarnacleVictimFinalBite = 0;
#endif
LINK_ENTITY_TO_CLASS( npc_barnacle, CNPC_Barnacle );
@ -187,7 +194,9 @@ BEGIN_DATADESC( CNPC_Barnacle )
DEFINE_THINKFUNC( BarnacleThink ),
DEFINE_THINKFUNC( WaitTillDead ),
#ifndef MAPBASE
DEFINE_FIELD( m_bSwallowingBomb, FIELD_BOOLEAN ),
#endif
END_DATADESC()
@ -275,7 +284,9 @@ void CNPC_Barnacle::Spawn()
m_cGibs = 0;
m_bLiftingPrey = false;
m_bSwallowingPrey = false;
#ifndef MAPBASE
m_bSwallowingBomb = false;
#endif
m_flDigestFinish = 0;
m_takedamage = DAMAGE_YES;
m_pConstraint = NULL;
@ -406,6 +417,16 @@ void CNPC_Barnacle::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot )
}
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CNPC_Barnacle::AllowedToIgnite( void )
{
return npc_barnacle_ignite.GetBool();
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Initialize tongue position when first spawned
// Input :
@ -509,7 +530,11 @@ void CNPC_Barnacle::BarnacleThink ( void )
}
else if ( GetEnemy() )
{
#ifdef MAPBASE
if ( m_bLiftingPrey )
#else
if ( m_bLiftingPrey || m_bSwallowingBomb == true )
#endif
{
LiftPrey();
}
@ -1145,6 +1170,24 @@ void CNPC_Barnacle::LiftPhysicsObject( float flBiteZOffset )
// If we got a physics prop, wait until the thing has settled down
m_bLiftingPrey = false;
#ifdef MAPBASE
Vector tipPos = m_vecTip.Get();
Activity curAct = GetActivity();
// Other, non-character entities use this now
if (pVictim->DispatchInteraction( g_interactionBarnacleVictimBite, &tipPos, this ))
{
// Make sure the interaction isn't making us use an irregular activity
// (e.g. biting)
if (GetActivity() == curAct)
SetActivity( (Activity)ACT_BARNACLE_TASTE_SPIT );
}
else
{
// Start the spit animation.
SetActivity( (Activity)ACT_BARNACLE_TASTE_SPIT );
}
#else
if ( hl2_episodic.GetBool() )
{
CBounceBomb *pBounce = dynamic_cast<CBounceBomb *>( pVictim );
@ -1181,6 +1224,7 @@ void CNPC_Barnacle::LiftPhysicsObject( float flBiteZOffset )
pBCC->DispatchInteraction( g_interactionBarnacleVictimBite, &tipPos, this );
}
#endif
#endif
}
else
@ -1577,6 +1621,18 @@ void CNPC_Barnacle::BitePrey( void )
CBaseCombatCharacter *pVictim = GetEnemyCombatCharacterPointer();
#ifdef MAPBASE
if ( pVictim == NULL )
{
if ( GetEnemy() )
{
Vector tipPos = m_vecTip.Get();
GetEnemy()->DispatchInteraction( g_interactionBarnacleVictimFinalBite, &tipPos, this );
}
return;
}
#else
#ifdef HL2_EPISODIC
if ( pVictim == NULL )
{
@ -1614,6 +1670,7 @@ void CNPC_Barnacle::BitePrey( void )
{
return;
}
#endif
EmitSound( "NPC_Barnacle.FinalBite" );
@ -1701,6 +1758,12 @@ void CNPC_Barnacle::BitePrey( void )
#endif
#ifdef MAPBASE
Vector tipPos = m_vecTip.Get();
if (pVictim->DispatchInteraction( g_interactionBarnacleVictimFinalBite, &tipPos, this ))
return;
#endif
// Players are never swallowed, nor is anything we don't have a ragdoll for
if ( !m_hRagdoll || pVictim->IsPlayer() )
{
@ -1885,13 +1948,20 @@ void CNPC_Barnacle::LostPrey( bool bRemoveRagdoll )
PhysEnableEntityCollisions( this, pEnemy );
#endif
#ifdef MAPBASE
// These can be CBaseEntity-based now
pEnemy->DispatchInteraction( g_interactionBarnacleVictimReleased, NULL, this );
#endif
//No one survives being snatched by a barnacle anymore, so leave
// this flag set so that their entity gets removed.
//GetEnemy()->RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE );
CBaseCombatCharacter *pVictim = GetEnemyCombatCharacterPointer();
if ( pVictim )
{
#ifndef MAPBASE
pVictim->DispatchInteraction( g_interactionBarnacleVictimReleased, NULL, this );
#endif
pVictim->RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE );
if ( m_hRagdoll )
@ -2721,6 +2791,9 @@ AI_BEGIN_CUSTOM_NPC( npc_barnacle, CNPC_Barnacle )
DECLARE_INTERACTION( g_interactionBarnacleVictimReleased )
DECLARE_INTERACTION( g_interactionBarnacleVictimGrab )
DECLARE_INTERACTION( g_interactionBarnacleVictimBite )
#ifdef MAPBASE
DECLARE_INTERACTION( g_interactionBarnacleVictimFinalBite )
#endif
// Conditions

View File

@ -84,6 +84,10 @@ public:
int OnTakeDamage_Alive( const CTakeDamageInfo &info );
void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
#ifdef MAPBASE
bool AllowedToIgnite( void );
#endif
// The tongue's vphysics updated
void OnTongueTipUpdated();
@ -209,7 +213,9 @@ private:
Vector m_vLastEnemyPos;
float m_flLastPull;
CSimpleSimTimer m_StuckTimer;
#ifndef MAPBASE // Handled by interactions now
bool m_bSwallowingBomb;
#endif
#ifdef HL2_EPISODIC
bool m_bSwallowingPoison;
#endif

View File

@ -32,6 +32,7 @@
#ifdef MAPBASE
#include "mapbase/GlobalStrings.h"
#include "globalstate.h"
#include "sceneentity.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
@ -448,6 +449,14 @@ void CNPC_Combine::Spawn( void )
m_flNextAltFireTime = gpGlobals->curtime;
NPCInit();
#ifdef MAPBASE
// This was moved from CalcWeaponProficiency() so soldiers don't change skin unnaturally and uncontrollably
if ( GetActiveWeapon() && EntIsClass(GetActiveWeapon(), gm_isz_class_Shotgun) && m_nSkin != COMBINE_SKIN_SHOTGUNNER )
{
m_nSkin = COMBINE_SKIN_SHOTGUNNER;
}
#endif
}
//-----------------------------------------------------------------------------
@ -2950,6 +2959,10 @@ bool CNPC_Combine::SpeakIfAllowed( const char *concept, AI_CriteriaSet& modifier
if ( !GetExpresser()->CanSpeakConcept( concept ) )
return false;
// Don't interrupt scripted VCD dialogue
if ( IsRunningScriptedSceneWithSpeechAndNotPaused( this, true ) )
return false;
if ( Speak( concept, modifiers ) )
{
JustMadeSound( sentencepriority, 2.0f /*GetTimeSpeechComplete()*/ );
@ -3655,10 +3668,12 @@ WeaponProficiency_t CNPC_Combine::CalcWeaponProficiency( CBaseCombatWeapon *pWea
else if( FClassnameIs( pWeapon, "weapon_shotgun" ) )
#endif
{
#ifndef MAPBASE // Moved so soldiers don't change skin unnaturally and uncontrollably
if( m_nSkin != COMBINE_SKIN_SHOTGUNNER )
{
m_nSkin = COMBINE_SKIN_SHOTGUNNER;
}
#endif
return WEAPON_PROFICIENCY_PERFECT;
}

View File

@ -276,7 +276,7 @@ void CNPC_PlayerCompanion::Spawn()
m_AnnounceAttackTimer.Set( 10, 30 );
#ifdef HL2_EPISODIC
#if HL2_EPISODIC && !MAPBASE // Mapbase permits this flag since the warning can be distracting and stripping the flag might break some HL2 maps in Episodic mods
// We strip this flag because it's been made obsolete by the StartScripting behavior
if ( HasSpawnFlags( SF_NPC_ALTCOLLISION ) )
{
@ -306,7 +306,7 @@ int CNPC_PlayerCompanion::Restore( IRestore &restore )
m_StandoffBehavior.SetActive( false );
}
#ifdef HL2_EPISODIC
#if HL2_EPISODIC && !MAPBASE // Mapbase permits this flag since the warning can be distracting and stripping the flag might break some HL2 maps in Episodic mods
// We strip this flag because it's been made obsolete by the StartScripting behavior
if ( HasSpawnFlags( SF_NPC_ALTCOLLISION ) )
{

View File

@ -19,6 +19,7 @@
#include "ammodef.h"
#ifdef MAPBASE
#include "AI_ResponseSystem.h"
#include "ai_speech.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
@ -1028,10 +1029,10 @@ AI_END_CUSTOM_NPC()
//=============================================================================
#ifdef MAPBASE
class CZombieCustom : public CZombie
class CZombieCustom : public CAI_ExpresserHost<CZombie>
{
DECLARE_DATADESC();
DECLARE_CLASS( CZombieCustom, CZombie );
DECLARE_CLASS( CZombieCustom, CAI_ExpresserHost<CZombie> );
public:
CZombieCustom();
@ -1039,10 +1040,11 @@ public:
void Spawn( void );
void Precache( void );
#ifdef EXPANDED_RESPONSE_SYSTEM_USAGE
DeclareResponseSystem()
void SpeakIfAllowed(const char *concept);
void SpeakIfAllowed( const char *concept, AI_CriteriaSet *modifiers = NULL );
void ModifyOrAppendCriteria( AI_CriteriaSet& set );
virtual CAI_Expresser *CreateExpresser( void );
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; }
virtual void PostConstructor( const char *szClassname );
void PainSound( const CTakeDamageInfo &info );
void DeathSound( const CTakeDamageInfo &info );
@ -1051,7 +1053,6 @@ public:
void AttackSound( void );
const char *GetMoanSound( int nSound );
#endif
void SetZombieModel( void );
@ -1064,6 +1065,8 @@ public:
string_t m_iszTorsoModel;
string_t m_iszHeadcrabClassname;
string_t m_iszHeadcrabModel;
CAI_Expresser *m_pExpresser;
};
BEGIN_DATADESC( CZombieCustom )
@ -1166,20 +1169,24 @@ void CZombieCustom::SetZombieModel( void )
}
}
#ifdef EXPANDED_RESPONSE_SYSTEM_USAGE
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CZombieCustom::PainSound( const CTakeDamageInfo &info )
{
SpeakIfAllowed( TLK_ZOMBIE_PAIN );
AI_CriteriaSet modifiers;
ModifyOrAppendDamageCriteria( modifiers, info );
SpeakIfAllowed( TLK_ZOMBIE_PAIN, &modifiers );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CZombieCustom::DeathSound( const CTakeDamageInfo &info )
{
SpeakIfAllowed( TLK_ZOMBIE_DEATH );
AI_CriteriaSet modifiers;
ModifyOrAppendDamageCriteria( modifiers, info );
SpeakIfAllowed( TLK_ZOMBIE_DEATH, &modifiers );
}
//-----------------------------------------------------------------------------
@ -1198,64 +1205,21 @@ void CZombieCustom::AlertSound( void )
//-----------------------------------------------------------------------------
const char *CZombieCustom::GetMoanSound( int nSound )
{
// This whole thing is really complicated and largely a copy-paste of CBaseEntity::DispatchResponse().
AI_CriteriaSet modifiers;
AddContext( "moansound", UTIL_VarArgs("%i", nSound & 4), 5.0f );
// We could probably do this through the response system alone now, but whatever.
modifiers.AppendCriteria( "moansound", UTIL_VarArgs("%i", nSound & 4) );
IResponseSystem *rs = GetResponseSystem();
if ( !rs )
AI_Response *response = SpeakFindResponse(TLK_ZOMBIE_MOAN, modifiers);
if ( !response )
return "NPC_BaseZombie.Moan1";
AI_CriteriaSet set;
set.AppendCriteria( "concept", TLK_ZOMBIE_MOAN, CONCEPT_WEIGHT );
ModifyOrAppendCriteria( set );
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if( pPlayer )
pPlayer->ModifyOrAppendPlayerCriteria( set );
ReAppendContextCriteria( set );
// Must be static so it could be returned
static char szSound[128];
response->GetName(szSound, sizeof(szSound));
AI_Response result;
rs->FindBestResponse(set, result);
// Get the response and turn it into something we can use
char response[256];
result.GetResponse(response, sizeof(response));
switch (result.GetType())
{
case RESPONSE_SENTENCE:
{
if (response[0] != '!')
{
SENTENCEG_PlayRndSz( edict(), response, 1, result.GetSoundLevel(), 0, PITCH_NORM );
break;
}
int sentenceIndex = SENTENCEG_Lookup( response );
if( sentenceIndex == -1 )
{
// sentence not found
break;
}
// Not sure how else to get around this
CPASAttenuationFilter filter( this );
CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, result.GetSoundLevel(), 0, PITCH_NORM );
return "AI_BaseNPC.SentenceStop";
}
break;
case RESPONSE_SCENE:
{
extern const char *GetFirstSoundInScene(const char *pszScene);
// Expand gender string
GenderExpandString( response, response, sizeof( response ) );
// Trust that it's been precached
Q_strncpy(response, GetFirstSoundInScene(response), sizeof(response));
}
break;
}
const char *szSound = response;
delete response;
return szSound;
}
@ -1285,9 +1249,9 @@ void CZombieCustom::AttackSound( void )
//-----------------------------------------------------------------------------
// Purpose: Speak concept
//-----------------------------------------------------------------------------
void CZombieCustom::SpeakIfAllowed(const char *concept)
void CZombieCustom::SpeakIfAllowed(const char *concept, AI_CriteriaSet *modifiers)
{
DispatchResponse(concept);
Speak( concept, modifiers ? *modifiers : AI_CriteriaSet() );
}
//-----------------------------------------------------------------------------
@ -1305,5 +1269,26 @@ void CZombieCustom::ModifyOrAppendCriteria( AI_CriteriaSet& set )
// This can be overridden with response contexts.
set.AppendCriteria( "classname", "npc_zombie" );
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CAI_Expresser *CZombieCustom::CreateExpresser( void )
{
m_pExpresser = new CAI_Expresser(this);
if (!m_pExpresser)
return NULL;
m_pExpresser->Connect(this);
return m_pExpresser;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CZombieCustom::PostConstructor(const char *szClassname)
{
BaseClass::PostConstructor(szClassname);
CreateExpresser();
}
#endif

View File

@ -284,7 +284,7 @@ public:
void ModifyOrAppendCriteria( AI_CriteriaSet& set );
virtual CAI_Expresser *CreateExpresser( void );
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; }
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; }
virtual void PostConstructor( const char *szClassname );
#endif

View File

@ -49,6 +49,8 @@ BEGIN_DATADESC(CScriptIntro)
#ifdef MAPBASE
DEFINE_KEYFIELD( m_bDrawSky, FIELD_BOOLEAN, "DrawSky" ),
DEFINE_KEYFIELD( m_bDrawSky2, FIELD_BOOLEAN, "DrawSky2" ),
DEFINE_KEYFIELD( m_bUseEyePosition, FIELD_BOOLEAN, "UseEyePosition" ),
#endif
// Inputs
@ -83,6 +85,7 @@ IMPLEMENT_SERVERCLASS_ST( CScriptIntro, DT_ScriptIntro )
#ifdef MAPBASE
SendPropBool( SENDINFO( m_bDrawSky ) ),
SendPropBool( SENDINFO( m_bDrawSky2 ) ),
SendPropBool( SENDINFO( m_bUseEyePosition ) ),
#endif
// Fov & fov blends

View File

@ -69,6 +69,7 @@ private:
#ifdef MAPBASE
CNetworkVar( bool, m_bDrawSky );
CNetworkVar( bool, m_bDrawSky2 );
CNetworkVar( bool, m_bUseEyePosition );
#endif
// Fov & fov blends

View File

@ -276,7 +276,7 @@ void CLogicMeasureMovement::MeasureThink( )
if (m_bOutputPosition)
{
m_OutPosition.Set(vecNewOrigin, m_hTarget.Get(), this);
m_OutAngles.Set(*(reinterpret_cast<Vector*>(vecNewAngles.Base())), m_hTarget.Get(), this);
m_OutAngles.Set(vecNewAngles, m_hTarget.Get(), this);
}
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_TELEPORT ))

View File

@ -18,6 +18,7 @@
#include "mapbase/variant_tools.h"
#include "mapbase/matchers.h"
#include "mapbase/datadesc_mod.h"
#include "activitylist.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
@ -1917,6 +1918,7 @@ private:
bool m_bPreserveValue;
bool m_bAlwaysOutputAsInt;
float m_flLerpPercent;
void UpdateOutValue(CBaseEntity *pActivator, float fNewValue);
@ -1937,6 +1939,8 @@ private:
void InputRandomInt( inputdata_t &inputdata );
void InputRandomFloat( inputdata_t &inputdata );
void InputLerpTo( inputdata_t &inputdata );
DECLARE_DATADESC();
};
@ -1948,6 +1952,7 @@ BEGIN_DATADESC( CMathCounterAdvanced )
// Keys
DEFINE_INPUT(m_bPreserveValue, FIELD_BOOLEAN, "PreserveValue"),
DEFINE_INPUT(m_bAlwaysOutputAsInt, FIELD_BOOLEAN, "AlwaysOutputAsInt"),
DEFINE_INPUT(m_flLerpPercent, FIELD_FLOAT, "SetLerpPercent"),
// Inputs
DEFINE_INPUTFUNC(FIELD_VOID, "SetValueToPi", InputSetValueToPi),
@ -1967,6 +1972,8 @@ BEGIN_DATADESC( CMathCounterAdvanced )
DEFINE_INPUTFUNC(FIELD_STRING, "RandomInt", InputRandomInt),
DEFINE_INPUTFUNC(FIELD_STRING, "RandomFloat", InputRandomFloat),
DEFINE_INPUTFUNC(FIELD_FLOAT, "LerpTo", InputLerpTo),
END_DATADESC()
//-----------------------------------------------------------------------------
@ -2280,6 +2287,21 @@ void CMathCounterAdvanced::InputRandomFloat( inputdata_t &inputdata )
UpdateOutValue( inputdata.pActivator, fNewValue );
}
//-----------------------------------------------------------------------------
// Purpose: Input handler for random float generation.
//-----------------------------------------------------------------------------
void CMathCounterAdvanced::InputLerpTo( inputdata_t &inputdata )
{
if( m_bDisabled )
{
DevMsg("Math Counter %s ignoring LERPTO because it is disabled\n", GetDebugName() );
return;
}
float fNewValue = m_OutValue.Get() + (inputdata.value.Float() - m_OutValue.Get()) * m_flLerpPercent;
UpdateOutValue( inputdata.pActivator, fNewValue );
}
//-----------------------------------------------------------------------------
// Purpose: Sets the value to the new value, clamping and firing the output value.
// Input : fNewValue - Value to set.
@ -3058,6 +3080,11 @@ int CLogicBranch::DrawDebugTextOverlays( void )
return text_offset;
}
#ifdef MAPBASE
extern void MapbaseGameLog_Record( const char *szContext );
extern ConVar mapbase_game_log_on_autosave;
#endif
//-----------------------------------------------------------------------------
// Purpose: Autosaves when triggered
//-----------------------------------------------------------------------------
@ -3094,6 +3121,13 @@ END_DATADESC()
//-----------------------------------------------------------------------------
void CLogicAutosave::InputSave( inputdata_t &inputdata )
{
#ifdef MAPBASE
if (mapbase_game_log_on_autosave.GetBool())
{
MapbaseGameLog_Record( "autosave" );
}
#endif
if ( m_bForceNewLevelUnit )
{
engine->ClearSaveDir();
@ -3107,6 +3141,13 @@ void CLogicAutosave::InputSave( inputdata_t &inputdata )
//-----------------------------------------------------------------------------
void CLogicAutosave::InputSaveDangerous( inputdata_t &inputdata )
{
#ifdef MAPBASE
if (mapbase_game_log_on_autosave.GetBool())
{
MapbaseGameLog_Record( "autosave_dangerous" );
}
#endif
CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
if ( g_ServerGameDLL.m_fAutoSaveDangerousTime != 0.0f && g_ServerGameDLL.m_fAutoSaveDangerousTime >= gpGlobals->curtime )
@ -3609,7 +3650,9 @@ public:
void InputNewLine( inputdata_t &inputdata ) { LCMsg("\n"); }
void InputDevNewLine( inputdata_t &inputdata ) { LCDevMsg(m_iDevLevel, "\n"); }
void InputClearConsole( inputdata_t &inputdata ) { engine->ServerCommand("clear"); }
// MAPBASE MP TODO: "ClearConsoleOnTarget"
// (and make this input broadcast to all players)
void InputClearConsole( inputdata_t &inputdata ) { UTIL_GetLocalPlayer() ? engine->ClientCommand(UTIL_GetLocalPlayer()->edict(), "clear") : NULL; }
DECLARE_DATADESC();
};
@ -3632,6 +3675,8 @@ BEGIN_DATADESC( CLogicConsole )
DEFINE_INPUTFUNC( FIELD_VOID, "NewLine", InputNewLine ),
DEFINE_INPUTFUNC( FIELD_VOID, "DevNewLine", InputDevNewLine ),
DEFINE_INPUTFUNC( FIELD_VOID, "ClearConsole", InputClearConsole ),
END_DATADESC()
ConVar sv_allow_logic_convar("sv_allow_logic_convar", "1");
@ -3696,23 +3741,31 @@ const char *CLogicConvar::GetConVarString( inputdata_t &inputdata )
ConVarRef pCVar = ConVarRef(STRING(m_iszConVar), true);
if (!pCVar.IsValid())
{
// It's not a convar, so check if it's a common cheat command a player might be using
const char *pszCVar = STRING( m_iszConVar );
CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator );
if (!pPlayer && AI_IsSinglePlayer())
pPlayer = UTIL_PlayerByIndex( 1 );
if (pPlayer)
{
const char *pszCVar = STRING( m_iszConVar );
// Check if it's a common cheat command a player might be using
if (FStrEq( pszCVar, "god" ))
return (pPlayer->GetFlags() & FL_GODMODE) ? "1" : "0";
if (FStrEq( pszCVar, "notarget" ))
return (pPlayer->GetFlags() & FL_NOTARGET) ? "1" : "0";
if (FStrEq( pszCVar, "noclip" ))
return (pPlayer->IsEFlagSet(EFL_NOCLIP_ACTIVE)) ? "1" : "0";
// It might be a client convar
// This function returns a blank string if the convar doesn't exist, so we have to put this at the end
const char *pszClientValue = engine->GetClientConVarValue( pPlayer->GetClientIndex(), pszCVar );
if (pszClientValue)
{
return pszClientValue;
}
}
Warning("Warning: %s has invalid convar \"%s\"\n", GetDebugName(), STRING(m_iszConVar));
//Warning("Warning: %s has invalid convar \"%s\"\n", GetDebugName(), STRING(m_iszConVar));
}
return pCVar.GetString();
@ -4587,6 +4640,7 @@ private:
void InputDisable( inputdata_t &inputdata );
void InputNormalize( inputdata_t &inputdata );
void InputNormalizeAngles( inputdata_t &inputdata );
void SetCoordinate(float value, char coord, CBaseEntity *pActivator);
void GetCoordinate(char coord, CBaseEntity *pActivator);
@ -4640,6 +4694,7 @@ BEGIN_DATADESC( CMathVector )
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
DEFINE_INPUTFUNC(FIELD_VOID, "Normalize", InputNormalize),
DEFINE_INPUTFUNC(FIELD_VOID, "NormalizeAngles", InputNormalizeAngles),
DEFINE_INPUTFUNC(FIELD_FLOAT, "SetX", InputSetX),
DEFINE_INPUTFUNC(FIELD_FLOAT, "SetY", InputSetY),
@ -4879,6 +4934,24 @@ void CMathVector::InputNormalize( inputdata_t &inputdata )
UpdateOutValue( inputdata.pActivator, cur );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CMathVector::InputNormalizeAngles( inputdata_t &inputdata )
{
if( m_bDisabled )
{
DevMsg("Math Vector %s ignoring NORMALIZEANGLES because it is disabled\n", GetDebugName() );
return;
}
Vector cur;
m_OutValue.Get(cur);
cur.x = AngleNormalize(cur.x);
cur.y = AngleNormalize(cur.y);
cur.z = AngleNormalize(cur.z);
UpdateOutValue( inputdata.pActivator, cur );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CMathVector::SetCoordinate(float value, char coord, CBaseEntity *pActivator)
@ -5354,6 +5427,7 @@ private:
//void InputSetTarget( inputdata_t &inputdata ) { BaseClass::InputSetTarget(inputdata); m_hTarget = NULL; }
void InputGetNumSkins( inputdata_t &inputdata );
void InputLookupSequence( inputdata_t &inputdata );
void InputLookupActivity( inputdata_t &inputdata );
// Outputs
COutputInt m_OutNumSkins;
@ -5371,6 +5445,7 @@ BEGIN_DATADESC( CLogicModelInfo )
// Inputs
DEFINE_INPUTFUNC( FIELD_VOID, "GetNumSkins", InputGetNumSkins ),
DEFINE_INPUTFUNC( FIELD_STRING, "LookupSequence", InputLookupSequence ),
DEFINE_INPUTFUNC( FIELD_STRING, "LookupActivity", InputLookupActivity ),
// Outputs
DEFINE_OUTPUT(m_OutNumSkins, "OutNumSkins"),
@ -5416,6 +5491,34 @@ void CLogicModelInfo::InputLookupSequence( inputdata_t &inputdata )
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CLogicModelInfo::InputLookupActivity( inputdata_t &inputdata )
{
CBaseAnimating *pAnimating = GetTarget(inputdata);
if (pAnimating && pAnimating->GetModelPtr())
{
int iActivity = ActivityList_IndexForName(inputdata.value.String());
if (iActivity == -1)
{
// Check if it's a raw activity ID
iActivity = atoi(inputdata.value.String());
if (!ActivityList_NameForIndex(iActivity))
{
Msg("%s received invalid LookupActivity %s\n", inputdata.value.String());
return;
}
}
int index = pAnimating->SelectWeightedSequence((Activity)iActivity);
if (index != ACT_INVALID)
m_OnHasSequence.Set(index, pAnimating, this);
else
m_OnLacksSequence.FireOutput(pAnimating, this);
}
}
//-----------------------------------------------------------------------------
// Purpose: Checks and calculates an entity's position.
//-----------------------------------------------------------------------------
@ -5441,7 +5544,8 @@ private:
CBaseEntity *GetTarget(CBaseEntity *pActivator, CBaseEntity *pCaller);
Vector GetPosition(CBaseEntity *pEntity);
const Vector &GetPosition(CBaseEntity *pEntity);
const QAngle &GetAngles(CBaseEntity *pEntity);
// Inputs
void InputGetPosition( inputdata_t &inputdata );
@ -5452,6 +5556,7 @@ private:
// Outputs
COutputVector m_OutPosition;
COutputVector m_OutAngles;
DECLARE_DATADESC();
};
@ -5472,6 +5577,7 @@ BEGIN_DATADESC( CLogicEntityPosition )
// Outputs
DEFINE_OUTPUT(m_OutPosition, "OutPosition"),
DEFINE_OUTPUT(m_OutAngles, "OutAngles"),
END_DATADESC()
@ -5487,16 +5593,15 @@ inline CBaseEntity *CLogicEntityPosition::GetTarget(CBaseEntity *pActivator, CBa
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Vector CLogicEntityPosition::GetPosition(CBaseEntity *pEntity)
const Vector &CLogicEntityPosition::GetPosition(CBaseEntity *pEntity)
{
Vector vecPosition = vec3_origin;
switch (m_iPositionType)
{
case POSITION_ORIGIN: vecPosition = pEntity->GetAbsOrigin(); break;
case POSITION_LOCAL: vecPosition = pEntity->GetLocalOrigin(); break;
case POSITION_BBOX: vecPosition = pEntity->WorldSpaceCenter(); break;
case POSITION_EYES: vecPosition = pEntity->EyePosition(); break;
case POSITION_EARS: vecPosition = pEntity->EarPosition(); break;
case POSITION_ORIGIN: return pEntity->GetAbsOrigin();
case POSITION_LOCAL: return pEntity->GetLocalOrigin();
case POSITION_BBOX: return pEntity->WorldSpaceCenter();
case POSITION_EYES: return pEntity->EyePosition();
case POSITION_EARS: return pEntity->EarPosition();
case POSITION_ATTACHMENT:
{
CBaseAnimating *pAnimating = pEntity->GetBaseAnimating();
@ -5506,10 +5611,47 @@ Vector CLogicEntityPosition::GetPosition(CBaseEntity *pEntity)
break;
}
// Attachment position doesn't originate anywhere, so use a static variable
static Vector vecPosition;
pAnimating->GetAttachment(STRING(m_iszPositionParameter), vecPosition);
return vecPosition;
}
}
return vec3_origin;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
const QAngle &CLogicEntityPosition::GetAngles(CBaseEntity *pEntity)
{
const QAngle *angAngles = &vec3_angle;
switch (m_iPositionType)
{
case POSITION_BBOX:
case POSITION_EARS:
case POSITION_ORIGIN: angAngles = &pEntity->GetAbsAngles(); break;
case POSITION_LOCAL: angAngles = &pEntity->GetLocalAngles(); break;
case POSITION_EYES: angAngles = &pEntity->EyeAngles(); break;
case POSITION_ATTACHMENT:
{
CBaseAnimating *pAnimating = pEntity->GetBaseAnimating();
if (!pAnimating)
{
Warning("%s wants to measure one of %s's attachments, but %s doesn't support them!\n", GetDebugName(), pEntity->GetDebugName(), pEntity->GetDebugName());
break;
}
// Attachment angles don't originate anywhere, so use a static variable
static QAngle AttachmentAngles;
matrix3x4_t attachmentToWorld;
pAnimating->GetAttachment( pAnimating->LookupAttachment( STRING( m_iszPositionParameter ) ), attachmentToWorld );
MatrixAngles( attachmentToWorld, AttachmentAngles );
angAngles = &AttachmentAngles;
} break;
}
return vecPosition;
return *angAngles;
}
//-----------------------------------------------------------------------------
@ -5518,9 +5660,14 @@ void CLogicEntityPosition::InputGetPosition( inputdata_t &inputdata )
{
CBaseEntity *pEntity = GetTarget(inputdata.pActivator, inputdata.pCaller);
if (!pEntity)
m_OutPosition.Set(vec3_origin, NULL, this);
{
m_OutPosition.Set( vec3_origin, NULL, this );
m_OutAngles.Set( vec3_angle, NULL, this );
return;
}
m_OutPosition.Set(GetPosition(pEntity), pEntity, this);
m_OutPosition.Set( GetPosition(pEntity), pEntity, this );
m_OutAngles.Set( GetAngles(pEntity), pEntity, this );
}
//-----------------------------------------------------------------------------
@ -5550,12 +5697,20 @@ void CLogicEntityPosition::InputPredictPosition( inputdata_t &inputdata )
{
CBaseEntity *pEntity = GetTarget(inputdata.pActivator, inputdata.pCaller);
if (!pEntity)
m_OutPosition.Set(vec3_origin, NULL, this);
{
m_OutPosition.Set( vec3_origin, NULL, this );
m_OutAngles.Set( vec3_angle, NULL, this );
return;
}
Vector vecPosition;
UTIL_PredictedPosition(pEntity, GetPosition(pEntity), inputdata.value.Float(), &vecPosition);
m_OutPosition.Set(vecPosition, pEntity, this);
QAngle angAngles;
UTIL_PredictedAngles(pEntity, GetAngles(pEntity), inputdata.value.Float(), &angAngles);
m_OutPosition.Set( vecPosition, pEntity, this );
m_OutAngles.Set( angAngles, pEntity, this );
}
//-----------------------------------------------------------------------------
@ -6190,12 +6345,16 @@ public:
// Inputs
void InputSetValue( inputdata_t &inputdata );
void InputSetValueNoFire( inputdata_t &inputdata );
void InputGetValue( inputdata_t &inputdata );
void InputSetGenerateType( inputdata_t &inputdata );
void InputEnable( inputdata_t &inputdata );
void InputDisable( inputdata_t &inputdata );
void InputToggle( inputdata_t &inputdata );
void UpdateOutValue( float fNewValue, CBaseEntity *pActivator = NULL );
void UpdateOutValueSine( float fNewValue, CBaseEntity *pActivator = NULL );
// Basic functions
void Spawn();
bool KeyValue( const char *szKeyName, const char *szValue );
@ -6213,8 +6372,16 @@ public:
// The gaussian stream normally only exists on the client, so we use our own.
static CGaussianRandomStream m_GaussianStream;
bool m_bHitMin; // Set when we reach or go below our minimum value, cleared if we go above it again.
bool m_bHitMax; // Set when we reach or exceed our maximum value, cleared if we fall below it again.
// Outputs
COutputFloat m_Value;
COutputFloat m_OutValue;
COutputFloat m_OnGetValue; // Used for polling the counter value.
COutputEvent m_OnHitMin;
COutputEvent m_OnHitMax;
COutputEvent m_OnChangedFromMin;
COutputEvent m_OnChangedFromMax;
DECLARE_DATADESC();
};
@ -6232,15 +6399,24 @@ BEGIN_DATADESC( CMathGenerate )
DEFINE_KEYFIELD( m_iGenerateType, FIELD_INTEGER, "GenerateType" ),
DEFINE_FIELD( m_bHitMax, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bHitMin, FIELD_BOOLEAN ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetValue", InputSetValue ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetValueNoFire", InputSetValueNoFire ),
DEFINE_INPUTFUNC( FIELD_VOID, "GetValue", InputGetValue ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetGenerateType", InputSetGenerateType ),
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
DEFINE_OUTPUT( m_Value, "OutValue" ),
DEFINE_OUTPUT( m_OutValue, "OutValue" ),
DEFINE_OUTPUT( m_OnHitMin, "OnHitMin" ),
DEFINE_OUTPUT( m_OnHitMax, "OnHitMax" ),
DEFINE_OUTPUT( m_OnGetValue, "OnGetValue" ),
DEFINE_OUTPUT( m_OnChangedFromMin, "OnChangedFromMin" ),
DEFINE_OUTPUT( m_OnChangedFromMax, "OnChangedFromMax" ),
DEFINE_THINKFUNC( GenerateSineWave ),
DEFINE_THINKFUNC( GenerateLinearRamp ),
@ -6278,7 +6454,7 @@ bool CMathGenerate::KeyValue( const char *szKeyName, const char *szValue )
{
if (FStrEq( szKeyName, "InitialValue" ))
{
m_Value.Init( atof(szValue) );
m_OutValue.Init( atof(szValue) );
}
else
return BaseClass::KeyValue( szKeyName, szValue );
@ -6290,14 +6466,22 @@ bool CMathGenerate::KeyValue( const char *szKeyName, const char *szValue )
//-----------------------------------------------------------------------------
void CMathGenerate::InputSetValue( inputdata_t &inputdata )
{
m_Value.Set(inputdata.value.Float(), inputdata.pActivator, this);
UpdateOutValue(inputdata.value.Float(), inputdata.pActivator);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CMathGenerate::InputSetValueNoFire( inputdata_t &inputdata )
{
m_Value.Init(inputdata.value.Float());
m_OutValue.Init(inputdata.value.Float());
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CMathGenerate::InputGetValue( inputdata_t &inputdata )
{
float flOutValue = m_OutValue.Get();
m_OnGetValue.Set( flOutValue, inputdata.pActivator, inputdata.pCaller );
}
//-----------------------------------------------------------------------------
@ -6337,6 +6521,123 @@ void CMathGenerate::InputToggle( inputdata_t &inputdata )
m_bDisabled ? InputEnable(inputdata) : InputDisable(inputdata);
}
//-----------------------------------------------------------------------------
// Purpose: Sets the value to the new value, clamping and firing the output value.
// Input : fNewValue - Value to set.
//-----------------------------------------------------------------------------
void CMathGenerate::UpdateOutValue( float fNewValue, CBaseEntity *pActivator )
{
if ((m_flMin != 0) || (m_flMax != 0))
{
//
// Fire an output any time we reach or exceed our maximum value.
//
if ( fNewValue >= m_flMax || (m_iGenerateType == GENERATE_SINE_WAVE && fNewValue >= (m_flMax * 0.995f)) )
{
if ( !m_bHitMax )
{
m_bHitMax = true;
m_OnHitMax.FireOutput( pActivator, this );
}
}
else
{
// Fire an output if we just changed from the maximum value
if ( m_OutValue.Get() == m_flMax )
{
m_OnChangedFromMax.FireOutput( pActivator, this );
}
m_bHitMax = false;
}
//
// Fire an output any time we reach or go below our minimum value.
//
if ( fNewValue <= m_flMin )
{
if ( !m_bHitMin )
{
m_bHitMin = true;
m_OnHitMin.FireOutput( pActivator, this );
}
}
else
{
// Fire an output if we just changed from the maximum value
if ( m_OutValue.Get() == m_flMin )
{
m_OnChangedFromMin.FireOutput( pActivator, this );
}
m_bHitMin = false;
}
fNewValue = clamp(fNewValue, m_flMin, m_flMax);
}
m_OutValue.Set(fNewValue, pActivator, this);
}
//-----------------------------------------------------------------------------
// Purpose: Sets the value to the new value, clamping and firing the output value.
// Sine generation needs to use a different function to account for skips and imprecision.
// Input : fNewValue - Value to set.
//-----------------------------------------------------------------------------
void CMathGenerate::UpdateOutValueSine( float fNewValue, CBaseEntity *pActivator )
{
if ((m_flMin != 0) || (m_flMax != 0))
{
//
// Fire an output any time we reach or exceed our maximum value.
//
if ( fNewValue >= (m_flMax * 0.995f) )
{
if ( !m_bHitMax )
{
m_bHitMax = true;
m_OnHitMax.FireOutput( pActivator, this );
}
}
else
{
// Fire an output if we just changed from the maximum value
if ( m_bHitMax )
{
m_OnChangedFromMax.FireOutput( pActivator, this );
}
m_bHitMax = false;
}
//
// Fire an output any time we reach or go below our minimum value.
//
if ( fNewValue <= (m_flMin * 1.005f) )
{
if ( !m_bHitMin )
{
m_bHitMin = true;
m_OnHitMin.FireOutput( pActivator, this );
}
}
else
{
// Fire an output if we just changed from the maximum value
if ( m_bHitMin )
{
m_OnChangedFromMin.FireOutput( pActivator, this );
}
m_bHitMin = false;
}
//fNewValue = clamp(fNewValue, m_flMin, m_flMax);
}
m_OutValue.Set(fNewValue, pActivator, this);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CMathGenerate::StartGenerating()
@ -6402,7 +6703,7 @@ void CMathGenerate::GenerateSineWave()
// get a value in [min,max]
flValue = ( m_flMax - m_flMin ) * flValue + m_flMin;
m_Value.Set( flValue, NULL, this );
UpdateOutValueSine( flValue );
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
}
@ -6414,7 +6715,7 @@ void CMathGenerate::GenerateLinearRamp()
// CLinearRampProxy in mathproxy.cpp
// Param1 = rate
float flVal = m_flParam1 * gpGlobals->curtime + m_Value.Get();
float flVal = m_flParam1 * gpGlobals->curtime + m_OutValue.Get();
// clamp
if (flVal < m_flMin)
@ -6422,7 +6723,7 @@ void CMathGenerate::GenerateLinearRamp()
else if (flVal > m_flMax)
flVal = m_flMax;
m_Value.Set( flVal, NULL, this );
UpdateOutValue( flVal );
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
}
@ -6433,7 +6734,7 @@ void CMathGenerate::GenerateUniformNoise()
{
// CUniformNoiseProxy in mathproxy.cpp
m_Value.Set( random->RandomFloat( m_flMin, m_flMax ), NULL, this );
UpdateOutValue( random->RandomFloat( m_flMin, m_flMax ) );
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
}
@ -6454,7 +6755,7 @@ void CMathGenerate::GenerateGaussianNoise()
else if (flVal > m_flMax)
flVal = m_flMax;
m_Value.Set( flVal, NULL, this );
UpdateOutValue( flVal );
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
}
@ -6467,7 +6768,7 @@ void CMathGenerate::GenerateExponential()
// Param1 = scale
// Param2 = offset
float flVal = m_flParam1 * exp( m_Value.Get() + m_flParam2 );
float flVal = m_flParam1 * exp( m_OutValue.Get() + m_flParam2 );
// clamp
if (flVal < m_flMin)
@ -6475,7 +6776,7 @@ void CMathGenerate::GenerateExponential()
else if (flVal > m_flMax)
flVal = m_flMax;
m_Value.Set( flVal, NULL, this );
UpdateOutValue( flVal );
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
}

View File

@ -92,19 +92,17 @@ void CVEnt_Precache(CMapbaseCVarModEntity *modent)
if (Q_strstr(STRING(modent->m_target), "sv_allow_logic_convar"))
return;
#ifdef MAPBASE_MP
if (gpGlobals->maxClients > 1 && !modent->m_bUseServer)
{
Warning("WARNING: %s is using the local player in a multiplayer game and will not function.\n", modent->GetDebugName());
}
#endif
CV_InitMod();
}
void CVEnt_Activate(CMapbaseCVarModEntity *modent, CBaseEntity *pActivator = UTIL_GetLocalPlayer())
void CVEnt_Activate(CMapbaseCVarModEntity *modent)
{
edict_t *edict = pActivator ? pActivator->edict() : NULL;
if (!edict)
return;
SetChangingCVars( modent );
if (m_ModEntities.Find(modent) == m_ModEntities.InvalidIndex())
m_ModEntities.AddToTail(modent);
const char *pszCommands = STRING( modent->m_target );
if ( Q_strnchr(pszCommands, '^', MAX_CONVARMOD_STRING_SIZE) )
{
@ -123,8 +121,29 @@ void CVEnt_Activate(CMapbaseCVarModEntity *modent, CBaseEntity *pActivator = UTI
pszCommands = szTmp;
}
engine->ClientCommand( edict, pszCommands );
engine->ClientCommand( edict, "mapbase_cvarsnotchanging\n" );
if (modent->m_bUseServer)
{
SetChangingCVars( modent );
engine->ServerCommand( pszCommands );
engine->ServerCommand( "mapbase_cvarsnotchanging" );
}
else
{
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
edict_t *edict = pPlayer ? pPlayer->edict() : NULL;
if (edict)
{
SetChangingCVars( modent );
engine->ClientCommand( edict, pszCommands );
engine->ClientCommand( edict, "mapbase_cvarsnotchanging" );
}
else
{
Warning("%s unable to find local player edict\n", modent->GetDebugName());
}
}
}
void CVEnt_Deactivate(CMapbaseCVarModEntity *modent)
{
@ -173,6 +192,7 @@ LINK_ENTITY_TO_CLASS( mapbase_convar_mod, CMapbaseCVarModEntity );
BEGIN_DATADESC( CMapbaseCVarModEntity )
DEFINE_UTLVECTOR( m_ModifiedConvars, FIELD_EMBEDDED ),
DEFINE_KEYFIELD( m_bUseServer, FIELD_BOOLEAN, "UseServer" ),
// Inputs
DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),

View File

@ -42,6 +42,7 @@ public:
bool NewCVar( ConVarRef *var, const char *pOldString, CBaseEntity *modent );
CUtlVector< modifiedconvars_t > m_ModifiedConvars;
bool m_bUseServer;
DECLARE_DATADESC();
};

View File

@ -565,6 +565,13 @@ int CPhysBox::ObjectCaps()
}
}
#ifdef MAPBASE
if ( HasSpawnFlags( SF_PHYSBOX_RADIUS_PICKUP ) )
{
caps |= FCAP_USE_IN_RADIUS;
}
#endif
return caps;
}

View File

@ -37,6 +37,9 @@
#define SF_PHYSBOX_NEVER_PICK_UP 0x200000 // Physcannon will never be able to pick this up.
#define SF_PHYSBOX_NEVER_PUNT 0x400000 // Physcannon will never be able to punt this object.
#define SF_PHYSBOX_PREVENT_PLAYER_TOUCH_ENABLE 0x800000 // If set, the player will not cause the object to enable its motion when bumped into
#ifdef MAPBASE
#define SF_PHYSBOX_RADIUS_PICKUP 0x1000000 // Allows this object to be picked up in a radius, useful for smaller objects. Based on the prop_physics input
#endif
// UNDONE: Hook collisions into the physics system to generate touch functions and take damage on falls
// UNDONE: Base class PhysBrush

View File

@ -82,6 +82,7 @@
#include "weapon_physcannon.h"
#ifdef MAPBASE
#include "mapbase/GlobalStrings.h"
#include "mapbase/matchers.h"
#endif
#endif
@ -7982,11 +7983,17 @@ public:
#ifdef MAPBASE
void InputEnable(inputdata_t &data);
void InputDisable(inputdata_t &data);
void InputSetAdditionalButtons(inputdata_t &data);
#endif
private:
int GetDisabledButtonMask( void );
#ifdef MAPBASE
int m_iAdditionalButtons;
#endif
DECLARE_DATADESC();
};
@ -7997,6 +8004,9 @@ BEGIN_DATADESC( CMovementSpeedMod )
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
DEFINE_KEYFIELD( m_iAdditionalButtons, FIELD_INTEGER, "AdditionalButtons" ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetAdditionalButtons", InputSetAdditionalButtons ),
#endif
END_DATADESC()
@ -8034,6 +8044,13 @@ int CMovementSpeedMod::GetDisabledButtonMask( void )
nMask |= IN_ZOOM;
}
#ifdef MAPBASE
if ( m_iAdditionalButtons != 0 )
{
nMask |= m_iAdditionalButtons;
}
#endif
return nMask;
}
@ -8102,8 +8119,15 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data)
}
}
#ifdef MAPBASE
if ( !HasSpawnFlags( SF_SPEED_MOD_DONT_SUPPRESS_FLASHLIGHT ) )
{
#endif
// Allow the flashlight again
pPlayer->SetFlashlightEnabled( true );
#ifdef MAPBASE
}
#endif
pPlayer->EnableButtons( GetDisabledButtonMask() );
// Restore the HUD
@ -8200,6 +8224,120 @@ void CMovementSpeedMod::InputDisable(inputdata_t &data)
}
}
}
void CMovementSpeedMod::InputSetAdditionalButtons(inputdata_t &data)
{
CBasePlayer *pPlayer = NULL;
if ( data.pActivator && data.pActivator->IsPlayer() )
{
pPlayer = (CBasePlayer *)data.pActivator;
}
else if ( !g_pGameRules->IsDeathmatch() )
{
pPlayer = UTIL_GetLocalPlayer();
}
bool bAlreadyDisabled = false;
if ( pPlayer )
{
bAlreadyDisabled = (pPlayer->m_afButtonDisabled & GetDisabledButtonMask()) != 0;
}
m_iAdditionalButtons = data.value.Int();
// If we were already disabling buttons, re-disable them
if ( bAlreadyDisabled )
{
// We should probably do something better than this.
pPlayer->m_afButtonForced = GetDisabledButtonMask();
}
}
#endif
#ifdef MAPBASE
class CLogicPlayerInfo : public CPointEntity
{
DECLARE_CLASS( CLogicPlayerInfo, CPointEntity );
public:
void InputGetPlayerInfo( inputdata_t &inputdata );
void InputGetPlayerByID( inputdata_t &inputdata );
void InputGetPlayerByName( inputdata_t &inputdata );
void GetPlayerInfo( CBasePlayer *pPlayer );
COutputInt m_OutUserID;
COutputString m_OutPlayerName;
COutputEHANDLE m_OutPlayerEntity;
DECLARE_DATADESC();
};
LINK_ENTITY_TO_CLASS( logic_playerinfo, CLogicPlayerInfo );
BEGIN_DATADESC( CLogicPlayerInfo )
DEFINE_INPUTFUNC( FIELD_EHANDLE, "GetPlayerInfo", InputGetPlayerInfo ),
DEFINE_INPUTFUNC( FIELD_STRING, "GetPlayerByID", InputGetPlayerByID ),
DEFINE_INPUTFUNC( FIELD_STRING, "GetPlayerByName", InputGetPlayerByName ),
DEFINE_OUTPUT( m_OutUserID, "OutUserID" ),
DEFINE_OUTPUT( m_OutPlayerName, "OutPlayerName" ),
DEFINE_OUTPUT( m_OutPlayerEntity, "OutPlayerEntity" ),
END_DATADESC()
void CLogicPlayerInfo::InputGetPlayerInfo( inputdata_t &inputdata )
{
CBasePlayer *pPlayer = ToBasePlayer(inputdata.value.Entity());
// If there was no entity to begin with, try the local player
if (!pPlayer && !inputdata.value.Entity())
pPlayer = UTIL_GetLocalPlayer();
if (pPlayer)
GetPlayerInfo( pPlayer );
}
void CLogicPlayerInfo::InputGetPlayerByID( inputdata_t &inputdata )
{
for (int i = 1; i < gpGlobals->maxClients; i++)
{
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
if (pPlayer)
{
if (Matcher_NamesMatch( inputdata.value.String(), UTIL_VarArgs("%i", pPlayer->GetUserID()) ))
{
GetPlayerInfo( pPlayer );
return;
}
}
}
}
void CLogicPlayerInfo::InputGetPlayerByName( inputdata_t &inputdata )
{
for (int i = 1; i < gpGlobals->maxClients; i++)
{
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
if (pPlayer)
{
if (Matcher_NamesMatch( inputdata.value.String(), pPlayer->GetPlayerName() ))
{
GetPlayerInfo( pPlayer );
return;
}
}
}
}
void CLogicPlayerInfo::GetPlayerInfo( CBasePlayer *pPlayer )
{
m_OutUserID.Set( pPlayer->GetUserID(), pPlayer, this );
m_OutPlayerName.Set( AllocPooledString(pPlayer->GetPlayerName()), pPlayer, this );
m_OutPlayerEntity.Set( pPlayer, pPlayer, this );
}
#endif

View File

@ -755,6 +755,41 @@ void CBreakableProp::HandleInteractionStick( int index, gamevcollisionevent_t *p
}
}
#ifdef MAPBASE
extern int g_interactionBarnacleVictimBite;
extern ConVar npc_barnacle_ignite;
//-----------------------------------------------------------------------------
// Purpose: Uses the new CBaseEntity interaction implementation
// Input : The type of interaction, extra info pointer, and who started it
// Output : true - if sub-class has a response for the interaction
// false - if sub-class has no response
//-----------------------------------------------------------------------------
bool CBreakableProp::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt )
{
#ifdef HL2_EPISODIC
// Allows flares to ignite barnacles.
if ( interactionType == g_interactionBarnacleVictimBite )
{
if ( npc_barnacle_ignite.GetBool() && sourceEnt->IsOnFire() == false )
{
sourceEnt->Ignite( 25.0f );
KillFlare( this, m_hFlareEnt, PROP_FLARE_IGNITE_SUBSTRACT );
IGameEvent *event = gameeventmanager->CreateEvent( "flare_ignite_npc" );
if ( event )
{
event->SetInt( "entindex", sourceEnt->entindex() );
gameeventmanager->FireEvent( event );
}
}
return true;
}
#endif
return BaseClass::HandleInteraction(interactionType, data, sourceEnt);
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Turn on prop debugging mode
//-----------------------------------------------------------------------------

View File

@ -119,6 +119,11 @@ public:
void HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent );
void HandleInteractionStick( int index, gamevcollisionevent_t *pEvent );
void StickAtPosition( const Vector &stickPosition, const Vector &savePosition, const QAngle &saveAngles );
#ifdef MAPBASE
// Uses the new CBaseEntity interaction implementation
bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt );
#endif
// Disable auto fading under dx7 or when level fades are specified
void DisableAutoFade();

View File

@ -4840,7 +4840,13 @@ float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *
// *phSceneEnt -
// Output : float
//-----------------------------------------------------------------------------
#ifdef MAPBASE
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, const char *soundname, EHANDLE *phSceneEnt,
float flPostDelay, bool bIsBackground, AI_Response *response,
bool bMultiplayer, IRecipientFilter *filter /* = NULL */ )
#else
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt /*= NULL*/ )
#endif
{
if ( !pActor )
{
@ -4858,10 +4864,38 @@ float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname
pScene->GenerateSoundScene( pActor, soundname );
#ifdef MAPBASE
pScene->m_bMultiplayer = bMultiplayer;
pScene->SetPostSpeakDelay( flPostDelay );
DispatchSpawn( pScene );
pScene->Activate();
pScene->m_bIsBackground = bIsBackground;
pScene->SetBackground( bIsBackground );
pScene->SetRecipientFilter( filter );
if ( response )
{
float flPreDelay = response->GetPreDelay();
if ( flPreDelay )
{
pScene->SetPreDelay( flPreDelay );
}
}
#else
pScene->Spawn();
pScene->Activate();
#endif
pScene->StartPlayback();
#ifdef MAPBASE
if ( response )
{
// If the response wants us to abort on NPC state switch, remember that
pScene->SetBreakOnNonIdle( response->ShouldBreakOnNonIdle() );
}
#endif
if ( phSceneEnt )
{
*phSceneEnt = pScene;

View File

@ -24,7 +24,11 @@ struct recentNPCSpeech_t
int GetRecentNPCSpeech( recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ] );
float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
#ifdef MAPBASE
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
#else
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL );
#endif
void StopScriptedScene( CBaseFlex *pActor, EHANDLE hSceneEnt );
void RemoveActorFromScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly, bool nonidlescenesonly = false, const char *pszThisSceneOnly = NULL );
void RemoveAllScenesInvolvingActor( CBaseFlex *pActor );

View File

@ -118,6 +118,9 @@ BEGIN_DATADESC( CAI_ScriptedSequence )
DEFINE_OUTPUT(m_OnScriptEvent[5], "OnScriptEvent06"),
DEFINE_OUTPUT(m_OnScriptEvent[6], "OnScriptEvent07"),
DEFINE_OUTPUT(m_OnScriptEvent[7], "OnScriptEvent08"),
#ifdef MAPBASE
DEFINE_OUTPUT(m_OnPreIdleSequence, "OnPreIdleSequence"),
#endif
END_DATADESC()
@ -838,6 +841,11 @@ void CAI_ScriptedSequence::OnBeginSequence( CBaseEntity *pActor )
{
m_OnBeginSequence.FireOutput( pActor, this );
}
void CAI_ScriptedSequence::OnPreIdleSequence( CBaseEntity *pActor )
{
m_OnPreIdleSequence.FireOutput( pActor, this );
}
#else
void CAI_ScriptedSequence::OnBeginSequence( void )
{
@ -1125,7 +1133,11 @@ void CAI_ScriptedSequence::PostIdleDone( CAI_BaseNPC *pNPC )
}
//Msg("%s finished post idle at %0.2f\n", pNPC->GetDebugName(), gpGlobals->curtime );
#ifdef MAPBASE
m_OnPostIdleEndSequence.FireOutput(pNPC, this);
#else
m_OnPostIdleEndSequence.FireOutput(NULL, this);
#endif
}

View File

@ -97,6 +97,7 @@ public:
void FireScriptEvent( int nEvent );
#ifdef MAPBASE
void OnBeginSequence( CBaseEntity *pActor );
void OnPreIdleSequence( CBaseEntity *pActor );
#else
void OnBeginSequence( void );
#endif
@ -218,6 +219,9 @@ private:
COutputEvent m_OnCancelSequence;
COutputEvent m_OnCancelFailedSequence; // Fired when a scene is cancelled before it's ever run
COutputEvent m_OnScriptEvent[MAX_SCRIPT_EVENTS];
#ifdef MAPBASE
COutputEvent m_OnPreIdleSequence;
#endif
static void ScriptEntityCancel( CBaseEntity *pentCine, bool bPretendSuccess = false );

View File

@ -26,6 +26,7 @@ $Project
{
$File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"

View File

@ -36,6 +36,9 @@
#include "datacache/imdlcache.h"
#include "util.h"
#include "cdll_int.h"
#ifdef MAPBASE
#include "fmtstr.h"
#endif
#ifdef PORTAL
#include "PortalSimulation.h"
@ -204,6 +207,46 @@ void CEntityFactoryDictionary::ReportEntitySizes()
}
}
#ifdef MAPBASE
int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 )
{
CEntityFactoryDictionary *pFactoryDict = (CEntityFactoryDictionary*)EntityFactoryDictionary();
for ( int i = pFactoryDict->m_Factories.First(); i != pFactoryDict->m_Factories.InvalidIndex(); i = pFactoryDict->m_Factories.Next( i ) )
{
const char *name = pFactoryDict->m_Factories.GetElementName( i );
if (Q_strnicmp(name, substring, checklen))
continue;
CUtlString sym = name;
int idx = symbols.Find(sym);
if (idx == symbols.InvalidIndex())
{
symbols.Insert(sym);
}
// Too many
if (symbols.Count() >= COMMAND_COMPLETION_MAXITEMS)
break;
}
// Now fill in the results
for (int i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder(i))
{
const char *name = symbols[i].String();
char buf[512];
Q_strncpy(buf, name, sizeof(buf));
Q_strlower(buf);
CUtlString command;
command = CFmtStr("%s %s", cmdname, buf);
commands.AddToTail(command);
}
return symbols.Count();
}
#endif
//-----------------------------------------------------------------------------
// class CFlaggedEntitiesEnum
@ -2507,6 +2550,10 @@ void UTIL_PredictedPosition( CBaseEntity *pTarget, float flTimeDelta, Vector *ve
if ( pAnimating != NULL )
{
vecPredictedVel = pAnimating->GetGroundSpeedVelocity();
#ifdef MAPBASE
if (vecPredictedVel.IsZero())
vecPredictedVel = pAnimating->GetSmoothedVelocity();
#endif
}
else
{
@ -2524,7 +2571,7 @@ void UTIL_PredictedPosition( CBaseEntity *pTarget, float flTimeDelta, Vector *ve
//-----------------------------------------------------------------------------
// Purpose: Same as above, except you don't have to use the absolute origin and can use your own position to predict from.
//-----------------------------------------------------------------------------
void UTIL_PredictedPosition( CBaseEntity *pTarget, Vector &vecActualPosition, float flTimeDelta, Vector *vecPredictedPosition )
void UTIL_PredictedPosition( CBaseEntity *pTarget, const Vector &vecActualPosition, float flTimeDelta, Vector *vecPredictedPosition )
{
if ( ( pTarget == NULL ) || ( vecPredictedPosition == NULL ) )
return;
@ -2547,7 +2594,11 @@ void UTIL_PredictedPosition( CBaseEntity *pTarget, Vector &vecActualPosition, fl
{
CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating *>(pTarget);
if ( pAnimating != NULL )
{
vecPredictedVel = pAnimating->GetGroundSpeedVelocity();
if (vecPredictedVel.IsZero())
vecPredictedVel = pAnimating->GetSmoothedVelocity();
}
else
vecPredictedVel = pTarget->GetSmoothedVelocity();
}
@ -2556,6 +2607,38 @@ void UTIL_PredictedPosition( CBaseEntity *pTarget, Vector &vecActualPosition, fl
// Get the result
(*vecPredictedPosition) = vecActualPosition + ( vecPredictedVel * flTimeDelta );
}
//-----------------------------------------------------------------------------
// Purpose: Predicts angles through angular velocity instead of predicting origin through regular velocity.
//-----------------------------------------------------------------------------
void UTIL_PredictedAngles( CBaseEntity *pTarget, const QAngle &angActualAngles, float flTimeDelta, QAngle *angPredictedAngles )
{
if ( ( pTarget == NULL ) || ( angPredictedAngles == NULL ) )
return;
QAngle angPredictedVel;
CBasePlayer *pPlayer = ToBasePlayer( pTarget );
if ( pPlayer != NULL )
{
if ( pPlayer->IsInAVehicle() )
angPredictedVel = pPlayer->GetVehicleEntity()->GetLocalAngularVelocity();
else
angPredictedVel = pPlayer->GetLocalAngularVelocity();
}
else
{
CBaseCombatCharacter *pCCTarget = pTarget->MyCombatCharacterPointer();
if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() )
angPredictedVel = pCCTarget->GetVehicleEntity()->GetLocalAngularVelocity();
else
{
angPredictedVel = pTarget->GetLocalAngularVelocity();
}
}
// Get the result
(*angPredictedAngles) = angActualAngles + ( angPredictedVel * flTimeDelta );
}
#endif
//-----------------------------------------------------------------------------

View File

@ -379,7 +379,8 @@ void UTIL_AxisStringToUnitDir( Vector &dir, const char *pString );
void UTIL_ClipPunchAngleOffset( QAngle &in, const QAngle &punch, const QAngle &clip );
void UTIL_PredictedPosition( CBaseEntity *pTarget, float flTimeDelta, Vector *vecPredictedPosition );
#ifdef MAPBASE
void UTIL_PredictedPosition( CBaseEntity *pTarget, Vector &vecActualPosition, float flTimeDelta, Vector *vecPredictedPosition );
void UTIL_PredictedPosition( CBaseEntity *pTarget, const Vector &vecActualPosition, float flTimeDelta, Vector *vecPredictedPosition );
void UTIL_PredictedAngles( CBaseEntity *pTarget, const QAngle &angActualAngles, float flTimeDelta, QAngle *angPredictedAngles );
#endif
void UTIL_Beam( Vector &Start, Vector &End, int nModelIndex, int nHaloIndex, unsigned char FrameStart, unsigned char FrameRate,
float Life, unsigned char Width, unsigned char EndWidth, unsigned char FadeLength, unsigned char Noise, unsigned char Red, unsigned char Green,

View File

@ -49,6 +49,10 @@ public:
inline const CHandle<CBaseEntity> &Entity(void) const;
inline color32 Color32(void) const { return rgbaVal; }
inline void Vector3D(Vector &vec) const;
#ifdef MAPBASE
// Gets angles from a vector
inline void Angle3D(QAngle &ang) const;
#endif
fieldtype_t FieldType( void ) { return fieldType; }
@ -59,6 +63,10 @@ public:
void SetEntity( CBaseEntity *val );
void SetVector3D( const Vector &val ) { vecVal[0] = val[0]; vecVal[1] = val[1]; vecVal[2] = val[2]; fieldType = FIELD_VECTOR; }
void SetPositionVector3D( const Vector &val ) { vecVal[0] = val[0]; vecVal[1] = val[1]; vecVal[2] = val[2]; fieldType = FIELD_POSITION_VECTOR; }
#ifdef MAPBASE
// Passes in angles as a vector
void SetAngle3D( const QAngle &val ) { vecVal[0] = val[0]; vecVal[1] = val[1]; vecVal[2] = val[2]; fieldType = FIELD_VECTOR; }
#endif
void SetColor32( color32 val ) { rgbaVal = val; fieldType = FIELD_COLOR32; }
void SetColor32( int r, int g, int b, int a ) { rgbaVal.r = r; rgbaVal.g = g; rgbaVal.b = b; rgbaVal.a = a; fieldType = FIELD_COLOR32; }
void Set( fieldtype_t ftype, void *data );
@ -112,6 +120,25 @@ inline void variant_t::Vector3D(Vector &vec) const
}
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Returns this variant as angles.
//-----------------------------------------------------------------------------
inline void variant_t::Angle3D(QAngle &ang) const
{
if (( fieldType == FIELD_VECTOR ) || ( fieldType == FIELD_POSITION_VECTOR ))
{
ang[0] = vecVal[0];
ang[1] = vecVal[1];
ang[2] = vecVal[2];
}
else
{
ang = vec3_angle;
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Returns this variant as an EHANDLE.
//-----------------------------------------------------------------------------

View File

@ -376,6 +376,9 @@ BEGIN_DATADESC( CWorld )
// keyvalues are parsed from map, but not saved/loaded
DEFINE_KEYFIELD( m_iszChapterTitle, FIELD_STRING, "chaptertitle" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_bChapterTitleNoMessage, FIELD_BOOLEAN, "chaptertitlenomessage" ),
#endif
DEFINE_KEYFIELD( m_bStartDark, FIELD_BOOLEAN, "startdark" ),
DEFINE_KEYFIELD( m_bDisplayTitle, FIELD_BOOLEAN, "gametitle" ),
DEFINE_FIELD( m_WorldMins, FIELD_VECTOR ),
@ -407,6 +410,9 @@ IMPLEMENT_SERVERCLASS_ST(CWorld, DT_WORLD)
SendPropFloat (SENDINFO(m_flMinPropScreenSpaceWidth), 0, SPROP_NOSCALE ),
SendPropStringT (SENDINFO(m_iszDetailSpriteMaterial) ),
SendPropInt (SENDINFO(m_bColdWorld), 1, SPROP_UNSIGNED ),
#ifdef MAPBASE
SendPropStringT (SENDINFO(m_iszChapterTitle) ),
#endif
END_SEND_TABLE()
//
@ -678,6 +684,23 @@ void CWorld::Precache( void )
// Call all registered precachers.
CPrecacheRegister::Precache();
#ifdef MAPBASE
if ( m_iszChapterTitle.Get() != NULL_STRING && !m_bChapterTitleNoMessage )
{
DevMsg( 2, "Chapter title: %s\n", STRING(m_iszChapterTitle.Get()) );
CMessage *pMessage = (CMessage *)CBaseEntity::Create( "env_message", vec3_origin, vec3_angle, NULL );
if ( pMessage )
{
pMessage->SetMessage( m_iszChapterTitle.Get() );
m_iszChapterTitle.Set( NULL_STRING );
// send the message entity a play message command, delayed by 1 second
pMessage->AddSpawnFlags( SF_MESSAGE_ONCE );
pMessage->SetThink( &CMessage::SUB_CallUseToggle );
pMessage->SetNextThink( gpGlobals->curtime + 1.0f );
}
}
#else
if ( m_iszChapterTitle != NULL_STRING )
{
DevMsg( 2, "Chapter title: %s\n", STRING(m_iszChapterTitle) );
@ -693,6 +716,7 @@ void CWorld::Precache( void )
pMessage->SetNextThink( gpGlobals->curtime + 1.0f );
}
}
#endif
g_iszFuncBrushClassname = AllocPooledString("func_brush");
}

View File

@ -52,10 +52,26 @@ public:
bool IsColdWorld( void );
#ifdef MAPBASE
inline const char *GetChapterTitle()
{
return STRING(m_iszChapterTitle.Get());
}
#endif
private:
DECLARE_DATADESC();
#ifdef MAPBASE
// Now needs to show up on the client for RPC
CNetworkVar( string_t, m_iszChapterTitle );
// Suppresses m_iszChapterTitle's env_message creation,
// allowing it to only be used for saves and RPC
bool m_bChapterTitleNoMessage;
#else
string_t m_iszChapterTitle;
#endif
CNetworkVar( float, m_flWaveHeight );
CNetworkVector( m_WorldMins );

View File

@ -1651,6 +1651,13 @@ void CAchievementMgr::OnMapEvent( const char *pchEventName )
CBaseAchievement *pAchievement = m_vecMapEventListeners[iAchievement];
pAchievement->OnMapEvent( pchEventName );
}
#ifdef MAPBASE
if (cc_achievement_debug.GetBool())
{
Msg( "CAchievementMgr::OnMapEvent: Achievement \"%s\" not found\n", pchEventName );
}
#endif
}
//-----------------------------------------------------------------------------

View File

@ -814,6 +814,10 @@ void CBaseCombatWeapon::OnPickedUp( CBaseCombatCharacter *pNewOwner )
// Robin: We don't want to delete weapons the player has picked up, so
// clear the name of the weapon. This prevents wildcards that are meant
// to find NPCs finding weapons dropped by the NPCs as well.
#ifdef MAPBASE
// Level designers might want some weapons to preserve their original names, however.
if ( !HasSpawnFlags(SF_WEAPON_PRESERVE_NAME) )
#endif
SetName( NULL_STRING );
}
else

View File

@ -52,20 +52,17 @@ class CUserCmd;
// I really, REALLY hope no weapon uses their own spawnflags.
// If you want yours to use spawnflags, start at 16 just to be safe.
// Prevents NPCs from picking up the weapon.
#define SF_WEAPON_NO_NPC_PICKUP (1<<3)
// Prevents the weapon from filling up to max automatically
// when picked up by the player or dropped.
#define SF_WEAPON_PRESERVE_AMMO (1<<4)
#define SF_WEAPON_NO_NPC_PICKUP (1<<3) // Prevents NPCs from picking up the weapon.
#define SF_WEAPON_PRESERVE_AMMO (1<<4) // Prevents the weapon from filling up to max automatically when dropped or picked up by players.
#define SF_WEAPON_PRESERVE_NAME (1<<5) // Prevents the weapon's name from being cleared upon being picked up by a player.
// ----------------------------------------------
// Internal Spawnflags
//
// For all of the weapons that show up in-game, I personally feel like
// this beats adding new variables by at least a long shot.
// These spawnflags are not supposed to be used by level designers.
// They're just my way of trying to avoid adding new variables
// that have to stay in memory and save/load.
// ----------------------------------------------
#define SF_WEAPON_NO_AUTO_SWITCH_WHEN_EMPTY (1<<5) // So weapons with ammo preserved at 0 don't switch.
#define SF_WEAPON_USED (1<<6) // Weapon is being +USE'd, not bumped
#define SF_WEAPON_NO_AUTO_SWITCH_WHEN_EMPTY (1<<6) // So weapons with ammo preserved at 0 don't switch.
#define SF_WEAPON_USED (1<<7) // Weapon is being +USE'd, not bumped
#endif
//Percent

View File

@ -620,6 +620,14 @@ void CGameRules::OnSkillLevelChanged( int iNewLevel )
pEntity->AcceptInput("SkillLevelChanged", UTIL_GetLocalPlayer(), NULL, varNewLevel, 0);
pEntity = gEntList.FindEntityByClassname(pEntity, "logic_skill");
}
// Fire game event for difficulty level changed
IGameEvent *event = gameeventmanager->CreateEvent("skill_changed");
if (event)
{
event->SetInt("skill_level", iNewLevel);
gameeventmanager->FireEvent(event);
}
}
#endif

View File

@ -0,0 +1,243 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A special system designed to record game information for map testing.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "tier0/icommandline.h"
#include "igamesystem.h"
#include "filesystem.h"
#include "utlbuffer.h"
#ifdef CLIENT_DLL
#else
#include "ammodef.h"
#include "ai_basenpc.h"
#include "ai_squad.h"
#include "fmtstr.h"
#include "GameEventListener.h"
#include "saverestore_utlvector.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef GAME_DLL
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
class CMapbaseGameLogger : public CLogicalEntity, public CGameEventListener
{
public:
DECLARE_DATADESC();
DECLARE_CLASS( CMapbaseGameLogger, CLogicalEntity );
CMapbaseGameLogger()
{
pGameLoggerEnt = this;
}
void Activate()
{
BaseClass::Activate();
ListenForGameEvent("skill_changed");
}
void FireGameEvent( IGameEvent *event )
{
if (FStrEq(event->GetName(), "skill_changed"))
{
m_ListSkillChanged.AddToTail(event->GetInt("skill_level"));
m_ListSkillChangedTime.AddToTail(gpGlobals->curtime);
}
}
float m_flLastLogTime;
int m_iSaveID;
CUtlVector<int> m_ListSkillChanged;
CUtlVector<float> m_ListSkillChangedTime;
static CMapbaseGameLogger *GetGameLoggerEnt()
{
if (!pGameLoggerEnt)
pGameLoggerEnt = static_cast<CMapbaseGameLogger*>(CBaseEntity::Create("mapbase_game_logger", vec3_origin, vec3_angle));
return pGameLoggerEnt;
}
private:
static CHandle<CMapbaseGameLogger> pGameLoggerEnt;
};
LINK_ENTITY_TO_CLASS( mapbase_game_logger, CMapbaseGameLogger );
BEGIN_DATADESC( CMapbaseGameLogger )
DEFINE_FIELD( m_flLastLogTime, FIELD_TIME ),
DEFINE_FIELD( m_iSaveID, FIELD_INTEGER ),
DEFINE_UTLVECTOR( m_ListSkillChanged, FIELD_INTEGER ),
DEFINE_UTLVECTOR( m_ListSkillChangedTime, FIELD_TIME ),
END_DATADESC()
CHandle<CMapbaseGameLogger> CMapbaseGameLogger::pGameLoggerEnt;
void MapbaseGameLog_CVarToggle( IConVar *var, const char *pOldString, float flOldValue );
ConVar mapbase_game_log_on_autosave( "mapbase_game_log_on_autosave", "0", FCVAR_NONE, "Logs information to %mapname%_log_%number%.txt on each autosave", MapbaseGameLog_CVarToggle );
void MapbaseGameLog_Init()
{
if (mapbase_game_log_on_autosave.GetBool())
{
// Create the game logger ent
CMapbaseGameLogger::GetGameLoggerEnt();
}
}
void MapbaseGameLog_Record( const char *szContext )
{
CMapbaseGameLogger *pGameLoggerEnt = CMapbaseGameLogger::GetGameLoggerEnt();
if (!pGameLoggerEnt)
{
Warning("Failed to get game logger ent\n");
return;
}
KeyValues *pKV = new KeyValues( "Log" );
KeyValues *pKVLogInfo = pKV->FindKey( "logging_info", true );
if ( pKVLogInfo )
{
pKVLogInfo->SetString("context", szContext);
pKVLogInfo->SetFloat("last_log", pGameLoggerEnt->m_flLastLogTime > 0.0f ? gpGlobals->curtime - pGameLoggerEnt->m_flLastLogTime : -1.0f);
}
KeyValues *pKVGameInfo = pKV->FindKey( "game_info", true );
if ( pKVGameInfo )
{
pKVGameInfo->SetInt("skill", g_pGameRules->GetSkillLevel());
if (pGameLoggerEnt->m_ListSkillChanged.Count() > 0)
{
KeyValues *pKVSkill = pKVGameInfo->FindKey("skill_changes", true);
for (int i = 0; i < pGameLoggerEnt->m_ListSkillChanged.Count(); i++)
{
float flTime = pGameLoggerEnt->m_ListSkillChangedTime[i];
switch (pGameLoggerEnt->m_ListSkillChanged[i])
{
case SKILL_EASY: pKVSkill->SetString(CNumStr(flTime), "easy"); break;
case SKILL_MEDIUM: pKVSkill->SetString(CNumStr(flTime), "normal"); break;
case SKILL_HARD: pKVSkill->SetString(CNumStr(flTime), "hard"); break;
}
}
}
}
KeyValues *pKVPlayer = pKV->FindKey( "player", true );
if ( pKVPlayer )
{
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if ( pPlayer )
{
pKVPlayer->SetInt("health", pPlayer->GetHealth());
pKVPlayer->SetInt("armor", pPlayer->ArmorValue());
pKVPlayer->SetString("position", CFmtStrN<128>("[%f %f %f]", pPlayer->GetAbsOrigin().x, pPlayer->GetAbsOrigin().y, pPlayer->GetAbsOrigin().z));
pKVPlayer->SetString("angles", CFmtStrN<128>("[%f %f %f]", pPlayer->EyeAngles().x, pPlayer->EyeAngles().y, pPlayer->EyeAngles().z));
KeyValues *pKVWeapons = pKVPlayer->FindKey( "weapons", true );
if ( pKVWeapons )
{
// Cycle through all of the player's weapons
for ( int i = 0; i < pPlayer->WeaponCount(); i++ )
{
CBaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
if ( !pWeapon )
continue;
if ( pPlayer->GetActiveWeapon() == pWeapon )
pKVWeapons->SetString(pWeapon->GetClassname(), CFmtStrN<32>("%i; %i (active)", pWeapon->m_iClip1, pWeapon->m_iClip2));
else
pKVWeapons->SetString(pWeapon->GetClassname(), CFmtStrN<32>("%i; %i", pWeapon->m_iClip1, pWeapon->m_iClip2));
}
}
KeyValues *pKVAmmo = pKVPlayer->FindKey( "ammo", true );
if ( pKVAmmo )
{
// Cycle through all of the player's ammo
for ( int i = 0; i < GetAmmoDef()->m_nAmmoIndex; i++ )
{
int iAmmo = pPlayer->GetAmmoCount( i );
if ( iAmmo > 0 )
pKVAmmo->SetInt( GetAmmoDef()->m_AmmoType[i].pName, iAmmo );
}
}
}
}
CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
int nAIs = g_AI_Manager.NumAIs();
for (int i = 0; i < nAIs; i++)
{
CAI_BaseNPC *pNPC = ppAIs[i];
if (!pNPC->IsAlive() || pNPC->GetSleepState() != AISS_AWAKE)
continue;
KeyValues *pKVNPC = pKV->FindKey( CNumStr( pNPC->entindex() ), true );
if (pKVNPC)
{
pKVNPC->SetString("classname", pNPC->GetClassname());
pKVNPC->SetString("name", STRING(pNPC->GetEntityName()));
pKVNPC->SetString("position", CFmtStrN<128>("[%f %f %f]", pNPC->GetAbsOrigin().x, pNPC->GetAbsOrigin().y, pNPC->GetAbsOrigin().z));
pKVNPC->SetInt("health", pNPC->GetHealth());
if (pNPC->GetActiveWeapon())
pKVNPC->SetString("weapon", pNPC->GetActiveWeapon()->GetClassname());
if (pNPC->GetSquad())
pKVNPC->SetString("squad", pNPC->GetSquad()->GetName());
}
}
CFmtStrN<MAX_PATH> pathfmt("map_logs/%s_log_%i.txt", gpGlobals->mapname, pGameLoggerEnt->m_iSaveID);
pGameLoggerEnt->m_flLastLogTime = gpGlobals->curtime;
pGameLoggerEnt->m_iSaveID++;
// Create the folder first, since "map_logs" is not standard and is unlikely to exist
g_pFullFileSystem->CreateDirHierarchy( "map_logs", "MOD" );
if (pKV->SaveToFile( g_pFullFileSystem, pathfmt, "MOD" ))
{
Msg("Saved game log file to \"%s\"\n", pathfmt);
}
pKV->deleteThis();
}
static void CC_Mapbase_GameLogRecord( const CCommand& args )
{
MapbaseGameLog_Record( "command" );
}
static ConCommand mapbase_game_log_record("mapbase_game_log_record", CC_Mapbase_GameLogRecord, "Records game data to %mapname%_log_%number%." );
void MapbaseGameLog_CVarToggle( IConVar *var, const char *pOldString, float flOldValue )
{
if (mapbase_game_log_on_autosave.GetBool())
{
// Create the game logger ent
CMapbaseGameLogger::GetGameLoggerEnt();
}
}
#endif

View File

@ -17,10 +17,13 @@
#ifdef DISCORD_RPC
#include "discord_rpc.h"
#include <time.h>
#include "c_world.h"
#endif
#include "filesystem.h"
#include "c_playerresource.h"
#include <vgui_controls/Controls.h>
#include <vgui/ILocalize.h>
#endif
@ -448,6 +451,35 @@ void MapbaseRPC_UpdateSteam( int iType, const char *pMapName )
#endif
#ifdef DISCORD_RPC
void MapbaseRPC_GetDiscordMapInfo( char *pDetails, size_t iSize, const char *pMapName )
{
if (!pMapName)
pMapName = "N/A";
// Say we're in the main menu if it's a background map
if (engine->IsLevelMainMenuBackground())
{
Q_snprintf( pDetails, iSize, "Main Menu (%s)", pMapName );
}
else
{
C_World *pWorld = GetClientWorldEntity();
if ( pWorld && pWorld->m_iszChapterTitle[0] != '\0' )
{
// Show the chapter title first
const char *pChapterTitle = g_pVGuiLocalize->FindAsUTF8( pWorld->m_iszChapterTitle );
if (!pChapterTitle || pChapterTitle[0] == '\0')
pChapterTitle = pWorld->m_iszChapterTitle;
Q_snprintf( pDetails, iSize, "%s (%s)", pChapterTitle, pMapName );
}
else
{
Q_snprintf( pDetails, iSize, "%s", pMapName );
}
}
}
void MapbaseRPC_GetDiscordParameters( DiscordRichPresence &discordPresence, int iType, const char *pMapName )
{
static char details[128];
@ -469,10 +501,7 @@ void MapbaseRPC_GetDiscordParameters( DiscordRichPresence &discordPresence, int
Q_strncpy( details, pMetadata->m_iszRPCDetails, sizeof(details) );
else
{
if (engine->IsLevelMainMenuBackground())
Q_snprintf( details, sizeof(details), "Main Menu (%s)", pMapName ? pMapName : "N/A" );
else
Q_snprintf( details, sizeof(details), "%s", pMapName ? pMapName : "N/A" );
MapbaseRPC_GetDiscordMapInfo( details, sizeof(details), pMapName );
}
}
else
@ -489,15 +518,7 @@ void MapbaseRPC_GetDiscordParameters( DiscordRichPresence &discordPresence, int
case RPCSTATE_LEVEL_INIT:
default:
{
// Say we're in the main menu if it's a background map
if (engine->IsLevelMainMenuBackground())
{
Q_snprintf( details, sizeof(details), "Main Menu (%s)", pMapName ? pMapName : "N/A" );
}
else
{
Q_snprintf( details, sizeof(details), "%s", pMapName ? pMapName : "N/A" );
}
MapbaseRPC_GetDiscordMapInfo( details, sizeof(details), pMapName );
} break;
}
}

View File

@ -74,6 +74,8 @@ ConVar mapbase_load_actbusy("mapbase_load_actbusy", "1", FCVAR_ARCHIVE, "Should
#endif
#ifdef GAME_DLL
extern void MapbaseGameLog_Init();
extern void ParseCustomActbusyFile(const char *file);
extern bool LoadResponseSystemFile(const char *scriptfile);
@ -203,6 +205,13 @@ public:
}
}
#ifdef GAME_DLL
virtual void LevelInitPostEntity()
{
MapbaseGameLog_Init();
}
#endif
virtual void LevelShutdownPreEntity()
{
// How would we make sure they don't last between maps?

View File

@ -170,7 +170,7 @@ float4 main( PS_INPUT i ) : COLOR
float4 stretchColor = tex2D( StretchSampler, i.baseTexCoordDetailTexCoord.xy );
// Apply wrinkle blend to only RGB. Alpha comes from the base texture
baseColor.rgb = flTextureAmount * baseColor + flWrinkleAmount * wrinkleColor + flStretchAmount * stretchColor;
baseColor.rgb = flTextureAmount * baseColor.rgb + flWrinkleAmount * wrinkleColor.rgb + flStretchAmount * stretchColor.rgb;
#endif
#if DETAILTEXTURE
@ -235,7 +235,7 @@ float4 main( PS_INPUT i ) : COLOR
envMapColor = (ENV_MAP_SCALE *
lerp(1, fFresnelRanges, g_EnvMapFresnel.x) *
lerp(fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask)) *
texCUBE( EnvmapSampler, vReflect ) *
texCUBE( EnvmapSampler, vReflect ).xyz *
g_EnvmapTint_ShadowTweaks.xyz;
}
}
@ -332,7 +332,7 @@ float4 main( PS_INPUT i ) : COLOR
float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, vEyeDir.xyz ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y;
diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo * g_SelfIllumScaleBiasExpBrightness.w, baseColor.a * saturate( flSelfIllumFresnel ) );
#else
float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoordDetailTexCoord.xy );
float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoordDetailTexCoord.xy ).xyz;
vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl );
diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo, vSelfIllumMask );
#endif

View File

@ -192,7 +192,7 @@ float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMod
HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input )
{
// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;
return texCUBE( normalizeSampler, input );
return texCUBE( normalizeSampler, input ).xyz;
}
/*
@ -209,6 +209,13 @@ HALF4 EnvReflect( sampler envmapSampler,
}
*/
// Vectorized smoothstep for doing three smoothsteps at once. Used by uberlight
float3 smoothstep3( float3 edge0, float3 edge1, float3 OneOverWidth, float3 x )
{
x = saturate((x - edge0) * OneOverWidth); // Scale, bias and saturate x to the range of zero to one
return x*x*(3-2*x); // Evaluate polynomial
}
float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )
{
#if 0

View File

@ -116,7 +116,7 @@ float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const floa
float3 fOut = float3( fResult, fResult, fResult );
if ( bDoLightingWarp )
{
fOut = 2.0f * tex1D( lightWarpSampler, fResult );
fOut = 2.0f * tex1D( lightWarpSampler, fResult ).xyz;
}
return fOut;
@ -146,7 +146,7 @@ float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cL
}
else
{
return normalize( cLightInfo[nLightIndex].pos - worldPos );
return normalize( cLightInfo[nLightIndex].pos.xyz - worldPos );
}
}
@ -181,7 +181,7 @@ void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, con
// Optionally warp as function of scalar specular and fresnel
if ( bDoSpecularWarp )
specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }
specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ).xyz; // Sample at { (L.R)^k, fresnel }
specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L
specularLighting *= color; // Modulate with light color
@ -286,19 +286,19 @@ float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNor
if ( nNumLights > 0 )
{
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler,
cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert,
cLightInfo[0].pos.xyz, cLightInfo[0].color.xyz, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
if ( nNumLights > 1 )
{
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler,
cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert,
cLightInfo[1].pos.xyz, cLightInfo[1].color.xyz, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
if ( nNumLights > 2 )
{
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler,
cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert,
cLightInfo[2].pos.xyz, cLightInfo[2].color.xyz, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
if ( nNumLights > 3 )

View File

@ -1715,13 +1715,15 @@ void DrawLightmappedGeneric_DX9(CBaseVSShader *pShader, IMaterialVar** params,
{
bool hasFlashlight = pShader->UsingFlashlight( params );
ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
if ( !IsX360() && !r_flashlight_version2.GetInt() )
{
DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr );
return;
}
DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr );
//ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
//
//if ( !IsX360() && !r_flashlight_version2.GetInt() )
//{
// DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr );
// return;
//}
//
//DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr );
}

View File

@ -992,18 +992,18 @@ void DrawSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamic
CBasePerMaterialContextData **pContextDataPtr )
{
ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
//ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
bool bHasFlashlight = pShader->UsingFlashlight( params );
if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetBool() ) )
{
DrawSkin_DX9_Internal( pShader, params, pShaderAPI,
pShaderShadow, false, info, vertexCompression, pContextDataPtr++ );
if ( pShaderShadow )
{
pShader->SetInitialShadowState( );
}
}
//if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetBool() ) )
//{
// DrawSkin_DX9_Internal( pShader, params, pShaderAPI,
// pShaderShadow, false, info, vertexCompression, pContextDataPtr++ );
// if ( pShaderShadow )
// {
// pShader->SetInitialShadowState( );
// }
//}
DrawSkin_DX9_Internal( pShader, params, pShaderAPI,
pShaderShadow, bHasFlashlight, info, vertexCompression, pContextDataPtr );
}

View File

@ -187,10 +187,10 @@ BEGIN_VS_SHADER( SDK_UnlitGeneric, "Help for SDK_UnlitGeneric" )
VertexLitGeneric_DX9_Vars_t vars;
SetupVars( vars );
ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
//ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
bool bNewFlashlightPath = IsX360() || ( r_flashlight_version2.GetInt() != 0 );
if ( ( pShaderShadow == NULL ) && ( pShaderAPI != NULL ) && !bNewFlashlightPath && pShaderAPI->InFlashlightMode() ) // Not snapshotting && flashlight pass
//bool bNewFlashlightPath = IsX360() || ( r_flashlight_version2.GetInt() != 0 );
if ( ( pShaderShadow == NULL ) && ( pShaderAPI != NULL ) && /*!bNewFlashlightPath &&*/ pShaderAPI->InFlashlightMode() ) // Not snapshotting && flashlight pass
{
Draw( false );
}

View File

@ -487,10 +487,10 @@ END_SHADER_PARAMS
SHADER_DRAW
{
ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
//ConVarRef r_flashlight_version2 = ConVarRef( "r_flashlight_version2" );
bool bHasFlashlight = UsingFlashlight( params );
if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) )
if ( bHasFlashlight /*&& ( IsX360() || r_flashlight_version2.GetInt() )*/ )
{
DrawPass( params, pShaderAPI, pShaderShadow, false, vertexCompression );
SHADOW_STATE

View File

@ -139,10 +139,6 @@ enum
STATIC_PROP_NO_SELF_SHADOWING = 0x80, // disable self shadowing in vrad
#ifdef MAPBASE
STATIC_PROP_OVERRIDE_PROPDATA = 0x100,
#endif
STATIC_PROP_WC_MASK = 0xd8, // all flags settable in hammer (?)
};

View File

@ -59,6 +59,7 @@ void InitMaterialSystem( const char *materialBaseDirPath, CreateInterfaceFn file
LoadMaterialSystemInterface( fileSystemFactory );
MaterialSystem_Config_t config;
g_pMaterialSystem->OverrideConfig( config, false );
g_pMaterialSystem->ModInit();
}
void ShutdownMaterialSystem( )

View File

@ -84,9 +84,15 @@ inline bool SideHasCubemapAndWasntManuallyReferenced( int iSide )
return s_aCubemapSideData[iSide].bHasEnvMapInMaterial && !s_aCubemapSideData[iSide].bManuallyPickedByAnEnvCubemap;
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
char* g_pParallaxObbStrs[MAX_MAP_CUBEMAPSAMPLES];
void Cubemap_InsertSample( const Vector& origin, int size, char* pParallaxObbStr = "" )
{
g_pParallaxObbStrs[g_nCubemapSamples] = pParallaxObbStr;
#else
void Cubemap_InsertSample( const Vector& origin, int size )
{
#endif
dcubemapsample_t *pSample = &g_CubemapSamples[g_nCubemapSamples];
pSample->origin[0] = ( int )origin[0];
pSample->origin[1] = ( int )origin[1];
@ -529,7 +535,11 @@ static void GeneratePatchedName( const char *pMaterialName, const PatchInfo_t &i
//-----------------------------------------------------------------------------
// Patches the $envmap for a material and all its dependents, returns true if any patching happened
//-----------------------------------------------------------------------------
#ifdef PARALLAX_CORRECTED_CUBEMAPS
static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, const PatchInfo_t &info, const char *pCubemapTexture, const char *pParallaxObbMatrix = "" )
#else
static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, const PatchInfo_t &info, const char *pCubemapTexture )
#endif
{
// Do *NOT* patch the material if there is an $envmap specified and it's not 'env_cubemap'
@ -547,7 +557,11 @@ static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, cons
const char *pDependentMaterial = FindDependentMaterial( pMaterialName, &pDependentMaterialVar );
if ( pDependentMaterial )
{
#ifdef PARALLAX_CORRECTED_CUBEMAPS
bDependentMaterialPatched = PatchEnvmapForMaterialAndDependents( pDependentMaterial, info, pCubemapTexture, pParallaxObbMatrix );
#else
bDependentMaterialPatched = PatchEnvmapForMaterialAndDependents( pDependentMaterial, info, pCubemapTexture );
#endif
}
// If we have neither to patch, we're done
@ -558,7 +572,11 @@ static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, cons
char pPatchedMaterialName[1024];
GeneratePatchedName( pMaterialName, info, true, pPatchedMaterialName, 1024 );
#ifdef PARALLAX_CORRECTED_CUBEMAPS
MaterialPatchInfo_t pPatchInfo[6];
#else
MaterialPatchInfo_t pPatchInfo[2];
#endif
int nPatchCount = 0;
if ( bShouldPatchEnvCubemap )
{
@ -568,6 +586,31 @@ static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, cons
++nPatchCount;
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
// Parallax cubemap matrix
CUtlVector<char *> matRowList;
if (pParallaxObbMatrix[0] != '\0')
{
V_SplitString( pParallaxObbMatrix, ";", matRowList );
pPatchInfo[nPatchCount].m_pKey = "$envMapParallax";
pPatchInfo[nPatchCount].m_pValue = "1";
++nPatchCount;
pPatchInfo[nPatchCount].m_pKey = "$envMapParallaxOBB1";
pPatchInfo[nPatchCount].m_pValue = matRowList[0];
++nPatchCount;
pPatchInfo[nPatchCount].m_pKey = "$envMapParallaxOBB2";
pPatchInfo[nPatchCount].m_pValue = matRowList[1];
++nPatchCount;
pPatchInfo[nPatchCount].m_pKey = "$envMapParallaxOBB3";
pPatchInfo[nPatchCount].m_pValue = matRowList[2];
++nPatchCount;
pPatchInfo[nPatchCount].m_pKey = "$envMapOrigin";
pPatchInfo[nPatchCount].m_pValue = matRowList[3];
++nPatchCount;
}
#endif
char pDependentPatchedMaterialName[1024];
if ( bDependentMaterialPatched )
{
@ -579,7 +622,14 @@ static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, cons
++nPatchCount;
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
CreateMaterialPatch( pMaterialName, pPatchedMaterialName, nPatchCount, pPatchInfo, PATCH_INSERT );
// Clean up parallax stuff
matRowList.PurgeAndDeleteElements();
#else
CreateMaterialPatch( pMaterialName, pPatchedMaterialName, nPatchCount, pPatchInfo, PATCH_REPLACE );
#endif
return true;
}
@ -598,7 +648,11 @@ static bool PatchEnvmapForMaterialAndDependents( const char *pMaterialName, cons
// default (skybox) cubemap into this file so the cubemap doesn't have the pink checkerboard at
// runtime before they run buildcubemaps.
//-----------------------------------------------------------------------------
#ifdef PARALLAX_CORRECTED_CUBEMAPS
static int Cubemap_CreateTexInfo( int originalTexInfo, int origin[3], int cubemapIndex )
#else
static int Cubemap_CreateTexInfo( int originalTexInfo, int origin[3] )
#endif
{
// Don't make cubemap tex infos for nodes
if ( originalTexInfo == TEXINFO_NODE )
@ -630,6 +684,15 @@ static int Cubemap_CreateTexInfo( int originalTexInfo, int origin[3] )
char pGeneratedTexDataName[1024];
GeneratePatchedName( pMaterialName, info, true, pGeneratedTexDataName, 1024 );
#ifdef PARALLAX_CORRECTED_CUBEMAPS
// Append origin info if this cubemap has a parallax OBB
char originAppendedString[1024] = "";
if (g_pParallaxObbStrs[cubemapIndex][0] != '\0')
{
Q_snprintf(originAppendedString, 1024, "%s;[%d %d %d]", g_pParallaxObbStrs[cubemapIndex], origin[0], origin[1], origin[2]);
}
#endif
// Make sure the texdata doesn't already exist.
int nTexDataID = FindTexData( pGeneratedTexDataName );
bool bHasTexData = (nTexDataID != -1);
@ -641,7 +704,11 @@ static int Cubemap_CreateTexInfo( int originalTexInfo, int origin[3] )
// Hook the texture into the material and all dependent materials
// but if no hooking was necessary, exit out
#ifdef PARALLAX_CORRECTED_CUBEMAPS
if ( !PatchEnvmapForMaterialAndDependents( pMaterialName, info, pTextureName, originAppendedString ) )
#else
if ( !PatchEnvmapForMaterialAndDependents( pMaterialName, info, pTextureName ) )
#endif
return originalTexInfo;
// Store off the name of the cubemap that we need to create since we successfully patched
@ -731,7 +798,11 @@ void Cubemap_FixupBrushSidesMaterials( void )
}
#endif
#ifdef PARALLAX_CORRECTED_CUBEMAPS
pSide->texinfo = Cubemap_CreateTexInfo( pSide->texinfo, g_CubemapSamples[cubemapID].origin, cubemapID );
#else
pSide->texinfo = Cubemap_CreateTexInfo( pSide->texinfo, g_CubemapSamples[cubemapID].origin );
#endif
if ( pSide->pMapDisp )
{
pSide->pMapDisp->face.texinfo = pSide->texinfo;
@ -947,7 +1018,11 @@ void Cubemap_AttachDefaultCubemapToSpecularSides( void )
Assert( pSide->texinfo == pSide->pMapDisp->face.texinfo );
}
#endif
#ifdef PARALLAX_CORRECTED_CUBEMAPS
pSide->texinfo = Cubemap_CreateTexInfo( pSide->texinfo, g_CubemapSamples[iCubemap].origin, iCubemap );
#else
pSide->texinfo = Cubemap_CreateTexInfo( pSide->texinfo, g_CubemapSamples[iCubemap].origin );
#endif
if ( pSide->pMapDisp )
{
pSide->pMapDisp->face.texinfo = pSide->texinfo;

View File

@ -15,6 +15,9 @@
#include "materialsub.h"
#include "fgdlib/fgdlib.h"
#include "manifest.h"
#ifdef PARALLAX_CORRECTED_CUBEMAPS
#include "matrixinvert.h"
#endif
#ifdef VSVMFIO
#include "VmfImport.h"
@ -1618,9 +1621,16 @@ ChunkFileResult_t CMapFile::LoadEntityCallback(CChunkFile *pFile, int nParam)
if( ( g_nDXLevel == 0 ) || ( g_nDXLevel >= 70 ) )
{
const char *pSideListStr = ValueForKey( mapent, "sides" );
#ifdef PARALLAX_CORRECTED_CUBEMAPS
char *pParallaxObbStr = ValueForKey( mapent, "parallaxobb" );
#endif
int size;
size = IntForKey( mapent, "cubemapsize" );
#ifdef PARALLAX_CORRECTED_CUBEMAPS
Cubemap_InsertSample( mapent->origin, size, pParallaxObbStr );
#else
Cubemap_InsertSample( mapent->origin, size );
#endif
Cubemap_SaveBrushSides( pSideListStr );
}
// clear out this entity
@ -1628,6 +1638,88 @@ ChunkFileResult_t CMapFile::LoadEntityCallback(CChunkFile *pFile, int nParam)
return(ChunkFile_Ok);
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
//
// parallax_obb brushes are removed after the transformation matrix is found and saved into
// the entity's data (ent will be removed after data transferred to patched materials)
//
if (!strcmp("parallax_obb", pClassName))
{
matrix3x4_t obbMatrix, invObbMatrix;
SetIdentityMatrix(obbMatrix);
SetIdentityMatrix(invObbMatrix);
// Get corner and its 3 edges (scaled, local x, y, and z axes)
mapbrush_t *brush = &mapbrushes[mapent->firstbrush];
Vector corner, x, y, z;
// Find first valid winding (with these whiles, if not enough valid windings then identity matrix is passed through to vmts)
int i = 0;
while (i < brush->numsides)
{
winding_t* wind = brush->original_sides[i].winding;
if (!wind)
{
i++;
continue;
}
corner = wind->p[0];
y = wind->p[1] - corner;
z = wind->p[3] - corner;
x = CrossProduct(y, z).Normalized();
i++;
break;
}
// Skip second valid winding (opposite face from first, unusable for finding Z's length)
while (i < brush->numsides)
{
winding_t* wind = brush->original_sides[i].winding;
if (!wind)
{
i++;
continue;
}
i++;
break;
}
// Find third valid winding
while (i < brush->numsides)
{
winding_t* wind = brush->original_sides[i].winding;
if (!wind)
{
i++;
continue;
}
// Find length of x
// Start with diagonal, then scale x by the projection of diag onto x
Vector diag = wind->p[0] - wind->p[2];
x *= abs(DotProduct(diag, x));
// Build transformation matrix (what is needed to turn a [0,0,0] - [1,1,1] cube into this brush)
MatrixSetColumn(x, 0, obbMatrix);
MatrixSetColumn(y, 1, obbMatrix);
MatrixSetColumn(z, 2, obbMatrix);
MatrixSetColumn(corner, 3, obbMatrix);
//find inverse (we need the world to local matrix, "transformationmatrix" is kind of a misnomer)
MatrixInversion(obbMatrix, invObbMatrix);
break;
}
char szMatrix[1024];
Q_snprintf(szMatrix, 1024, "[%f %f %f %f];[%f %f %f %f];[%f %f %f %f]", invObbMatrix[0][0], invObbMatrix[0][1], invObbMatrix[0][2], invObbMatrix[0][3], invObbMatrix[1][0], invObbMatrix[1][1], invObbMatrix[1][2], invObbMatrix[1][3], invObbMatrix[2][0], invObbMatrix[2][1], invObbMatrix[2][2], invObbMatrix[2][3]);
SetKeyValue(mapent, "transformationmatrix", szMatrix);
return (ChunkFile_Ok);
}
#endif
if ( !strcmp( "test_sidelist", pClassName ) )
{
ConvertSideList(mapent, "sides");
@ -2615,6 +2707,30 @@ bool LoadMapFile( const char *pszFileName )
}
}
#ifdef PARALLAX_CORRECTED_CUBEMAPS
// Fill out parallax obb matrix array
for (int i = 0; i < g_nCubemapSamples; i++)
{
if (g_pParallaxObbStrs[i][0] != '\0')
{
entity_t* obbEnt = EntityByName(g_pParallaxObbStrs[i]);
g_pParallaxObbStrs[i] = ValueForKey(obbEnt, "transformationmatrix");
}
}
// Remove parallax_obb entities (in a nice slow linear search)
for (int i = 0; i < g_MainMap->num_entities; i++)
{
entity_t* mapent = &g_MainMap->entities[i];
const char *pClassName = ValueForKey( mapent, "classname" );
if ( !strcmp( "parallax_obb", pClassName ) )
{
mapent->numbrushes = 0;
mapent->epairs = NULL;
}
}
#endif
if ((eResult == ChunkFile_Ok) || (eResult == ChunkFile_EOF))
{
// Update the overlay/side list(s).

View File

@ -102,6 +102,7 @@ isstaticprop_ret IsStaticProp( studiohdr_t* pHdr )
if (!(pHdr->flags & STUDIOHDR_FLAGS_STATIC_PROP))
return RET_FAIL_NOT_MARKED_STATIC_PROP;
#ifndef MAPBASE
// If it's got a propdata section in the model's keyvalues, it's not allowed to be a prop_static
KeyValues *modelKeyValues = new KeyValues(pHdr->pszName());
if ( StudioKeyValues( pHdr, modelKeyValues ) )
@ -117,6 +118,7 @@ isstaticprop_ret IsStaticProp( studiohdr_t* pHdr )
}
}
modelKeyValues->deleteThis();
#endif
return RET_VALID;
}
@ -166,11 +168,7 @@ bool LoadStudioModel( char const* pModelName, char const* pEntityType, CUtlBuffe
}
isstaticprop_ret isStaticProp = IsStaticProp(pHdr);
#ifdef MAPBASE
if ( isStaticProp != RET_VALID && strcmp(pEntityType, "prop_static_override") != 0 )
#else
if ( isStaticProp != RET_VALID )
#endif
{
if ( isStaticProp == RET_FAIL_NOT_MARKED_STATIC_PROP )
{
@ -244,11 +242,7 @@ CPhysCollide* ComputeConvexHull( studiohdr_t* pStudioHdr )
//-----------------------------------------------------------------------------
// Add, find collision model in cache
//-----------------------------------------------------------------------------
#ifdef MAPBASE
static CPhysCollide* GetCollisionModel( char const* pModelName, bool bOverridePropdata = false )
#else
static CPhysCollide* GetCollisionModel( char const* pModelName )
#endif
{
// Convert to a common string
char* pTemp = (char*)_alloca(strlen(pModelName) + 1);
@ -271,11 +265,7 @@ static CPhysCollide* GetCollisionModel( char const* pModelName )
// Load the studio model file
CUtlBuffer buf;
#ifdef MAPBASE
if (!LoadStudioModel(pModelName, bOverridePropdata ? "prop_static_override" : "prop_static", buf))
#else
if (!LoadStudioModel(pModelName, "prop_static", buf))
#endif
{
Warning("Error loading studio model \"%s\"!\n", pModelName );
@ -486,11 +476,7 @@ static bool ComputeLightingOrigin( StaticPropBuild_t const& build, Vector& light
static void AddStaticPropToLump( StaticPropBuild_t const& build )
{
// Get the collision model
#ifdef MAPBASE
CPhysCollide* pConvexHull = GetCollisionModel( build.m_pModelName, (build.m_Flags & STATIC_PROP_OVERRIDE_PROPDATA) > 0 );
#else
CPhysCollide* pConvexHull = GetCollisionModel( build.m_pModelName );
#endif
if (!pConvexHull)
return;
@ -602,11 +588,7 @@ void EmitStaticProps()
for ( i = 0; i < num_entities; ++i)
{
char* pEntity = ValueForKey(&entities[i], "classname");
#ifdef MAPBASE
if (!strncmp(pEntity, "prop_static", 11) || !strcmp(pEntity, "static_prop"))
#else
if (!strcmp(pEntity, "static_prop") || !strcmp(pEntity, "prop_static"))
#endif
{
StaticPropBuild_t build;
@ -639,14 +621,6 @@ void EmitStaticProps()
build.m_Flags |= STATIC_PROP_SCREEN_SPACE_FADE;
}
#ifdef MAPBASE
//if (IntForKey(&entities[i], "override_propdata") == 1)
if (!strcmp(pEntity + 11, "_override"))
{
build.m_Flags |= STATIC_PROP_OVERRIDE_PROPDATA;
}
#endif
const char *pKey = ValueForKey( &entities[i], "fadescale" );
if ( pKey && pKey[0] )
{

View File

@ -153,6 +153,13 @@ int FindMiptex (const char *name)
{
textureref[i].flags |= SURF_NOLIGHT;
}
#ifdef MAPBASE
// handle Slammin-inspired %compileNoShadows%
else if ( ( propVal = GetMaterialVar( matID, "%compileNoShadows" ) ) && StringIsTrue( propVal ) )
{
textureref[i].flags |= SURF_NOSHADOWS;
}
#endif
else
{
// HANDLE ALL OF THE STUFF THAT IS RENDERED WITH THE MATERIAL THAT IS ON IT.

View File

@ -43,7 +43,11 @@ qboolean noshare;
qboolean nosubdiv;
qboolean notjunc;
qboolean noopt;
#ifdef MAPBASE
qboolean noleaktest;
#else
qboolean leaktest;
#endif
qboolean verboseentities;
qboolean dumpcollide = false;
qboolean g_bLowPriority = false;
@ -85,182 +89,6 @@ int entity_num;
node_t *block_nodes[BLOCKS_SPACE+2][BLOCKS_SPACE+2];
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Manifest stuff
//-----------------------------------------------------------------------------
CUtlVector<const char *> g_szManifestFiles;
bool g_bManifestVerbose = true; // Change to false when testing is over
#define ManifestMsg(msg, ...) g_bManifestVerbose ? Msg(msg, __VA_ARGS__) : NULL
#define ManifestWarning(msg, ...) g_bManifestVerbose ? Warning(msg, __VA_ARGS__) : NULL
void SetManifestFile(char const *file)
{
if (g_pFileSystem->FileExists( file ))
{
Msg("Manifest file: %s\n", file);
g_szManifestFiles.AddToTail(file);
}
}
void ZipDirectory(const char *dir, const char *relative, IZip *package, int *filecount)
{
ManifestMsg(" MANIFEST: Mounting directory \"%s\"\n", dir);
FileFindHandle_t handle = NULL;
const char *file = g_pFullFileSystem->FindFirst(dir, &handle);
// Prevents us from packaging the folder itself
//if (file)
// file = g_pFullFileSystem->FindNext(handle);
while (file)
{
// Don't use hidden files/folders
if (file[0] != '.')
{
char subdir[MAX_PATH];
Q_strncpy(subdir, dir, strlen(dir) - 1); // Remove wildcard
Q_ComposeFileName(subdir, file, subdir, sizeof(subdir));
char subrelative[MAX_PATH];
Q_strncpy(subrelative, relative, sizeof(subrelative));
Q_ComposeFileName(subrelative, file, subrelative, sizeof(subrelative));
if (g_pFullFileSystem->FindIsDirectory(handle))
{
// Append wildcard
Q_ComposeFileName(subdir, "*", subdir, sizeof(subdir));
// Mount subdirectory
ZipDirectory(subdir, subrelative, package, filecount);
}
else
{
// Mount file
ManifestMsg(" MANIFEST: File \"%s\" packed into BSP at \"%s\"\n", subdir, subrelative);
*filecount++;
AddFileToPak(package, subrelative, subdir);
}
}
file = g_pFullFileSystem->FindNext(handle);
}
g_pFullFileSystem->FindClose(handle);
}
void ParseManifestFile()
{
if (g_szManifestFiles.Count() == 0)
return;
Msg("Starting pack manifest with %i files\n", g_szManifestFiles.Count());
int totalfilecount = 0;
for (int i = 0; i < g_szManifestFiles.Count(); i++)
{
FileHandle_t manifestfile = g_pFileSystem->Open( g_szManifestFiles[i], "rb" );
if (!manifestfile)
{
Warning("Manifest file \"%s\" cannot be read!\n", g_szManifestFiles[i]);
continue;
}
//FileHandle_t curfile;
bool curfile;
char buf[1024];
char *scan;
int filecount = 0;
bool fullpath = false;
while ( CmdLib_FGets( buf, sizeof( buf ), manifestfile ) )
{
scan = buf;
// Check if it's an actual path or just relative
fullpath = (scan[0] == '#');
if (fullpath)
scan += 1;
else
{
char file[128];
Q_strncpy(file, scan, sizeof(file));
char path[_MAX_PATH];
Q_ExtractFilePath(source, path, sizeof(path));
sprintf(scan, "%s%s", path, file);
}
bool inquotes = (scan[0] == '"');
int namelength;
if (inquotes)
{
scan += 1;
namelength = strcspn( scan, "\"" );
}
else
{
namelength = strcspn( scan, " \t" );
}
char filename[FILENAME_MAX];
Q_strncpy(filename, scan, namelength + 1);
scan += (namelength + inquotes);
scan += strspn(scan, " \t");
// Remove any quotes in the internal path.
// The fact they're actually optional in the second path is irrelevant.
if (scan[0] == '"')
{
scan[0] = '\0';
if (scan[strlen(scan) - 1] == '"')
scan[strlen(scan) - 1] = '\0';
}
curfile = g_pFileSystem->FileExists(filename);
if (curfile)
{
// Assume internal file is a directory if no extension
if (Q_GetFileExtension(scan) == NULL)
Q_ComposeFileName(scan, filename, scan, sizeof(filename));
ManifestMsg(" MANIFEST: File \"%s\" packed into BSP at \"%s\"\n", filename, scan);
filecount++;
AddFileToPak(GetPakFile(), scan, filename);
}
else if (g_pFullFileSystem->IsDirectory(filename))
{
// Append wildcard
if (!Q_strstr(filename, "*"))
Q_ComposeFileName(filename, "*", filename, sizeof(filename));
// Internal path must be a directory
if (scan[0] == NULL || Q_GetFileExtension(scan) == NULL)
ZipDirectory(filename, scan, GetPakFile(), &filecount);
else
Warning("\n MANIFEST WARNING: Directory \"%s\" tried to pack to a file!\nIf you are not trying to package a directory to the BSP, add an extension to \"%s\".\nIf you are trying to package a directory, remove the extension from \"%s\".\n\n", filename, filename, scan);
}
else
{
Warning(" MANIFEST WARNING: File \"%s\" does not exist!\n", filename);
}
}
if (filecount > 0)
ManifestMsg("%i file(s) packed from manifest %s\n", filecount, g_szManifestFiles[i]);
else
ManifestWarning("*** No files zipped from manifest %s!\n ***", g_szManifestFiles[i]);
totalfilecount += filecount;
g_pFileSystem->Close( manifestfile );
}
Msg("%i total file(s) packed from manifests\n", totalfilecount);
}
#endif
//-----------------------------------------------------------------------------
// Assign occluder areas (must happen *after* the world model is processed)
//-----------------------------------------------------------------------------
@ -473,7 +301,11 @@ void ProcessWorldModel (void)
Warning( ("**** leaked ****\n") );
leaked = true;
LeakFile (tree);
#ifdef MAPBASE
if (!noleaktest)
#else
if (leaktest)
#endif
{
Warning( ("--- MAP LEAKED ---\n") );
exit (0);
@ -1178,11 +1010,19 @@ int RunVBSP( int argc, char **argv )
Msg ("microvolume = %f\n", microvolume);
i++;
}
#ifdef MAPBASE
else if (!Q_stricmp(argv[i], "-noleaktest"))
{
Msg ("noleaktest = true\n");
noleaktest = true;
}
#else
else if (!Q_stricmp(argv[i], "-leaktest"))
{
Msg ("leaktest = true\n");
leaktest = true;
}
#endif
else if (!Q_stricmp(argv[i], "-verboseentities"))
{
Msg ("verboseentities = true\n");
@ -1316,19 +1156,10 @@ int RunVBSP( int argc, char **argv )
EnableFullMinidumps( true );
}
#ifdef MAPBASE
else if ( !Q_stricmp( argv[i], "-deletecubemaps" ) )
else if ( !Q_stricmp( argv[i], "-nodefaultcubemap" ) )
{
g_bNoDefaultCubemaps = true;
}
else if ( !Q_stricmp( argv[i], "-manifest" ) )
{
SetManifestFile(argv[i+1]);
i++;
}
else if ( !Q_stricmp( argv[i], "-manifest_verbose" ) )
{
g_bManifestVerbose = true;
}
#endif
else if (argv[i][0] == '-')
{
@ -1445,13 +1276,6 @@ int RunVBSP( int argc, char **argv )
ThreadSetDefault ();
numthreads = 1; // multiple threads aren't helping...
#ifdef MAPBASE
// Any additional files to pack?
char ManifestFile[512];
_snprintf( ManifestFile, sizeof(ManifestFile), "%s_zipmanifest.txt", source );
SetManifestFile(ManifestFile);
#endif
// Setup the logfile.
char logFile[512];
_snprintf( logFile, sizeof(logFile), "%s.log", source );
@ -1568,11 +1392,6 @@ int RunVBSP( int argc, char **argv )
AddBufferToPak( GetPakFile(), "stale.txt", "stale", strlen( "stale" ) + 1, false );
}
#ifdef MAPBASE
// Is this a good place for this?
ParseManifestFile();
#endif
LoadMapFile (name);
WorldVertexTransitionFixup();
if( ( g_nDXLevel == 0 ) || ( g_nDXLevel >= 70 ) )

View File

@ -34,6 +34,12 @@ class CUtlBuffer;
// this will output glview files for the given brushmodel. Brushmodel 1 is the world, 2 is the first brush entity, etc.
#define DEBUG_BRUSHMODEL 0
#ifdef MAPBASE
// Activates compiler code for parallax corrected cubemaps
// https://developer.valvesoftware.com/wiki/Parallax_Corrected_Cubemaps
#define PARALLAX_CORRECTED_CUBEMAPS 1
#endif
struct portal_t;
struct node_t;
@ -607,7 +613,12 @@ void SaveVertexNormals( void );
//=============================================================================
// cubemap.cpp
#ifdef PARALLAX_CORRECTED_CUBEMAPS
extern char* g_pParallaxObbStrs[MAX_MAP_CUBEMAPSAMPLES];
void Cubemap_InsertSample( const Vector& origin, int size, char* pParallaxObbStr );
#else
void Cubemap_InsertSample( const Vector& origin, int size );
#endif
void Cubemap_CreateDefaultCubemaps( void );
void Cubemap_SaveBrushSides( const char *pSideListStr );
void Cubemap_FixupBrushSidesMaterials( void );

View File

@ -6,7 +6,7 @@
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Macro OUTBINNAME "mapbase_vbsp"
$Macro OUTBINNAME "vbsp"
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"

View File

@ -6,7 +6,7 @@
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Macro OUTBINNAME "mapbase_vrad_dll"
$Macro OUTBINNAME "vrad_dll"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"

View File

@ -6,7 +6,7 @@
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Macro OUTBINNAME "mapbase_vrad"
$Macro OUTBINNAME "vrad"
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"

View File

@ -6,7 +6,7 @@
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Macro OUTBINNAME "mapbase_vvis_dll"
$Macro OUTBINNAME "vvis_dll"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"

View File

@ -6,7 +6,7 @@
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Macro OUTBINNAME "mapbase_vvis"
$Macro OUTBINNAME "vvis"
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"