1212#include " c_basehlplayer.h"
1313#endif
1414
15+ #ifdef MAPBASE_MP
16+ #include " takedamageinfo.h"
17+ #ifdef HL2MP
18+ #include " c_hl2mp_playerresource.h"
19+ #endif
20+ #endif
21+
1522#include " death_pose.h"
1623
1724// memdbgon must be the last include file in a .cpp file!!!
1825#include " tier0/memdbgon.h"
1926
2027#define PING_MAX_TIME 2.0
2128
29+ #ifdef MAPBASE_MP
30+ BEGIN_RECV_TABLE_NOBASE ( C_AI_BaseNPC, DT_BaseNPCGameData )
31+ RecvPropInt( RECVINFO( m_iHealth ) ),
32+ RecvPropInt( RECVINFO( m_takedamage ) ),
33+ RecvPropInt( RECVINFO( m_bloodColor ) ),
34+ // RecvPropString( RECVINFO( m_szNetname ) ), // Transmitted by player resource now
35+ RecvPropInt( RECVINFO( m_nDefaultPlayerRelationship ) ),
36+ END_RECV_TABLE();
37+ #endif
38+
39+ #ifdef CAI_BaseNPC
40+ #undef CAI_BaseNPC
41+ #endif
42+
2243IMPLEMENT_CLIENTCLASS_DT ( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC )
2344 RecvPropInt( RECVINFO( m_lifeState ) ),
2445 RecvPropBool( RECVINFO( m_bPerformAvoidance ) ),
@@ -31,6 +52,9 @@ IMPLEMENT_CLIENTCLASS_DT( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC )
3152 RecvPropInt( RECVINFO( m_bSpeedModActive ) ),
3253 RecvPropBool( RECVINFO( m_bImportanRagdoll ) ),
3354 RecvPropFloat( RECVINFO( m_flTimePingEffect ) ),
55+ #ifdef MAPBASE_MP
56+ RecvPropDataTable ( " npc_gamedata" , 0 , 0 , &REFERENCE_RECV_TABLE ( DT_BaseNPCGameData ) ),
57+ #endif
3458END_RECV_TABLE ()
3559
3660extern ConVar cl_npc_speedmod_intime;
@@ -47,6 +71,9 @@ bool NPC_IsImportantNPC( C_BaseAnimating *pAnimating )
4771
4872C_AI_BaseNPC::C_AI_BaseNPC ()
4973{
74+ #ifdef MAPBASE_MP
75+ SetBloodColor ( DONT_BLEED );
76+ #endif
5077}
5178
5279// -----------------------------------------------------------------------------
@@ -183,3 +210,105 @@ bool C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x
183210 return bRet;
184211}
185212
213+ #ifdef MAPBASE_MP
214+ // -----------------------------------------------------------------------------
215+ // Purpose:
216+ // Output : char const
217+ // -----------------------------------------------------------------------------
218+ const char *C_AI_BaseNPC::GetPlayerName ( void ) const
219+ {
220+ #ifdef HL2MP
221+ if (g_HL2MP_PR)
222+ {
223+ return g_HL2MP_PR->GetNPCName ( entindex () );
224+ }
225+ #endif
226+
227+ return BaseClass::GetPlayerName ();
228+ }
229+
230+ // -----------------------------------------------------------------------------
231+ // Purpose:
232+ // -----------------------------------------------------------------------------
233+ void C_AI_BaseNPC::DispatchTraceAttack ( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
234+ {
235+ m_fNoDamageDecal = false ;
236+
237+ if ( info.GetAttacker () && info.GetAttacker ()->IsPlayer () )
238+ {
239+ if ( IsPlayerAlly ( ToBasePlayer ( info.GetAttacker () ) ) )
240+ {
241+ m_fNoDamageDecal = true ;
242+ return ;
243+ }
244+ }
245+
246+ BaseClass::DispatchTraceAttack ( info, vecDir, ptr, pAccumulator );
247+ }
248+
249+ // -----------------------------------------------------------------------------
250+ // Purpose:
251+ // -----------------------------------------------------------------------------
252+ void C_AI_BaseNPC::DecalTrace ( trace_t *pTrace, char const *decalName )
253+ {
254+ if ( m_fNoDamageDecal )
255+ {
256+ // Don't do impact decals when we shouldn't
257+ // (adapts an existing hack from singleplayer HL2, see serverside counterpart)
258+ m_fNoDamageDecal = false ;
259+ return ;
260+ }
261+ BaseClass::DecalTrace ( pTrace, decalName );
262+ }
263+
264+ // -----------------------------------------------------------------------------
265+ // Purpose:
266+ // -----------------------------------------------------------------------------
267+ void C_AI_BaseNPC::ImpactTrace ( trace_t *pTrace, int iDamageType, const char *pCustomImpactName )
268+ {
269+ if ( m_fNoDamageDecal )
270+ {
271+ // Don't do impact decals when we shouldn't
272+ // (adapts an existing hack from singleplayer HL2, see serverside counterpart)
273+ m_fNoDamageDecal = false ;
274+ return ;
275+ }
276+ BaseClass::ImpactTrace ( pTrace, iDamageType, pCustomImpactName );
277+ }
278+
279+ // -----------------------------------------------------------------------------
280+ // Purpose:
281+ // -----------------------------------------------------------------------------
282+ bool C_AI_BaseNPC::IsPlayerAlly ( C_BasePlayer *pPlayer )
283+ {
284+ if ( pPlayer == NULL )
285+ {
286+ pPlayer = C_BasePlayer::GetLocalPlayer ();
287+ }
288+
289+ if ( pPlayer->GetTeamNumber () == TEAM_UNASSIGNED )
290+ {
291+ // AI relationship code isn't available here, so we currently transmit a var from the server to determine if we're, at least generically, an ally
292+ return (m_nDefaultPlayerRelationship == GR_TEAMMATE);
293+ }
294+ else if (GetTeamNumber () == pPlayer->GetTeamNumber ())
295+ {
296+ // Same team probably means allies
297+ return true ;
298+ }
299+
300+ return false ;
301+ }
302+
303+ // -----------------------------------------------------------------------------
304+ // Purpose:
305+ // -----------------------------------------------------------------------------
306+ bool C_AI_BaseNPC::IsNeutralTo ( C_BasePlayer *pPlayer )
307+ {
308+ if ( IsPlayerAlly ( pPlayer ) )
309+ return false ;
310+
311+ return (m_nDefaultPlayerRelationship == GR_NOTTEAMMATE);
312+ }
313+ #endif
314+
0 commit comments