From 057228f1b0c777a2873202cce7607d6b69173472 Mon Sep 17 00:00:00 2001 From: wootguy Date: Sun, 22 Dec 2024 19:17:00 -0800 Subject: [PATCH] fixes + tweaks fixes: - inverted camera "No instant turn" flag. No actually means yes. - rotating doors still instakilling when blocked - snipers not shooting far enough again (infested) - grunts and shock troopers dropping weapons inside walls - antiblock swapping with turrets - bullsquid attacking nothing after killing its enemy - wrong kill icon for garg stomp attack - alien slave getting stuck trying to talk until attacked/used tweaks: - sniper sound is heard further away - monsters will keep moving if they want to talk while following - allies only attack the player(s) who provoked them, then forgive the player when killed - notarget cheat makes monsters forget the player as an enemy --- cl_dll/hl/hl_baseentity.cpp | 4 ++ dlls/func/CBaseDoor.cpp | 1 + dlls/func/CRotDoor.cpp | 10 ++-- dlls/game/multiplay_gamerules.cpp | 2 +- dlls/monster/CBarney.cpp | 3 +- dlls/monster/CBaseGrunt.cpp | 18 ++++--- dlls/monster/CBaseMonster.cpp | 82 +++++++++++++++++++++++++++--- dlls/monster/CBaseMonster.h | 7 +++ dlls/monster/CBaseTurret.h | 2 +- dlls/monster/CBullsquid.cpp | 3 +- dlls/monster/CController.cpp | 6 +-- dlls/monster/CGargantua.h | 1 + dlls/monster/CHornet.cpp | 2 +- dlls/monster/CISlave.cpp | 8 +-- dlls/monster/CKingpin.cpp | 2 +- dlls/monster/CMonsterMaker.cpp | 2 +- dlls/monster/COsprey.cpp | 4 +- dlls/monster/COtis.cpp | 8 ++- dlls/monster/CScientist.cpp | 3 +- dlls/monster/CShockTrooper.cpp | 11 +++- dlls/monster/CTalkSquadMonster.cpp | 37 +++----------- dlls/monster/CTalkSquadMonster.h | 6 +-- dlls/monster/CTor.cpp | 2 +- dlls/monster/CTurret.cpp | 2 +- dlls/monster/CVoltigore.cpp | 4 +- dlls/triggers/CTriggerCamera.cpp | 4 +- 26 files changed, 149 insertions(+), 85 deletions(-) diff --git a/cl_dll/hl/hl_baseentity.cpp b/cl_dll/hl/hl_baseentity.cpp index 9ddda924..3820a379 100644 --- a/cl_dll/hl/hl_baseentity.cpp +++ b/cl_dll/hl/hl_baseentity.cpp @@ -180,6 +180,10 @@ int CBaseMonster::TaskIsRunning( void ) { return 0; } void CBaseMonster::ScheduleChange( void ) { } void CBaseMonster::SetClassify( int ) { } void CBaseMonster::Revive( void ) { } +void CBaseMonster::Provoke(CBaseEntity* attacker) {} +void CBaseMonster::OnKillProvoker(CBaseEntity* provoker) {} +void CBaseMonster::Unprovoke(bool friendsToo) {} +int CBaseMonster::IRelationship(CBaseEntity* pTarget) { return 0; } float CBaseMonster::GetDamage(float defaultDamage) { return defaultDamage; } int CBaseEntity::IRelationship ( CBaseEntity *pTarget ) { return 0; } BOOL CBaseMonster :: FindCover ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist ) { return FALSE; } diff --git a/dlls/func/CBaseDoor.cpp b/dlls/func/CBaseDoor.cpp index 901f4a30..97d0d512 100644 --- a/dlls/func/CBaseDoor.cpp +++ b/dlls/func/CBaseDoor.cpp @@ -793,6 +793,7 @@ void CBaseDoor::Blocked(CBaseEntity* pOther) if (pOther->IsMonster() && !pOther->IsAlive()) { // don't let corpses block doors pOther->Killed(pev, GIB_ALWAYS); + lastDamage = 0; // allow gibbing multiple players return; // don't bounce back because the path is clear now } diff --git a/dlls/func/CRotDoor.cpp b/dlls/func/CRotDoor.cpp index 37d171cb..eaeea8de 100644 --- a/dlls/func/CRotDoor.cpp +++ b/dlls/func/CRotDoor.cpp @@ -129,10 +129,12 @@ void CRotDoor::Blocked(CBaseEntity* pOther) { pev->dmg = initialDamage; - // increase damage exponentially as time goes on to account for monsters with insane health values - // and only hurt the entity preventing the door from opening - if (++blockedCounter > 8 && m_toggle_state == TS_GOING_UP) { - pev->dmg += V_min(1000, powf(10, (blockedCounter / 8))); + if (gpGlobals->time - lastDamage > DOOR_SMASH_MIN_DELAY) { + // increase damage exponentially as time goes on to account for monsters with insane health values + // and only hurt the entity preventing the door from opening + if (++blockedCounter > 8 && m_toggle_state == TS_GOING_UP) { + pev->dmg += V_min(1000, powf(10, (blockedCounter / 8))); + } } CBaseDoor::Blocked(pOther); diff --git a/dlls/game/multiplay_gamerules.cpp b/dlls/game/multiplay_gamerules.cpp index fc39aba7..c6ee0ce4 100644 --- a/dlls/game/multiplay_gamerules.cpp +++ b/dlls/game/multiplay_gamerules.cpp @@ -917,7 +917,7 @@ void CHalfLifeMultiplay::DeathNotice( CBaseMonster *pVictim, entvars_t *pKiller, break; } - switch (pVictim->IRelationship(pVictim->Classify(), CLASS_PLAYER)) { + switch (CBaseEntity::IRelationship(pVictim->Classify(), CLASS_PLAYER)) { case R_AL: victimColor = FRIEND_TEAM_COLOR; break; diff --git a/dlls/monster/CBarney.cpp b/dlls/monster/CBarney.cpp index 0a055320..73fbd81e 100644 --- a/dlls/monster/CBarney.cpp +++ b/dlls/monster/CBarney.cpp @@ -562,8 +562,7 @@ int CBarney :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, floa // Alright, now I'm pissed! PlaySentence( "BA_MAD", 4, VOL_NORM, ATTN_NORM ); - Remember( bits_MEMORY_PROVOKED ); - StopFollowing( TRUE ); + Provoke(attacker); } else { diff --git a/dlls/monster/CBaseGrunt.cpp b/dlls/monster/CBaseGrunt.cpp index f8a0067e..0503b575 100644 --- a/dlls/monster/CBaseGrunt.cpp +++ b/dlls/monster/CBaseGrunt.cpp @@ -105,9 +105,7 @@ void CBaseGrunt::Killed(entvars_t* pevAttacker, int iGib) { if (HasMemory(bits_MEMORY_SUSPICIOUS) || IsFacing(pevAttacker, pev->origin)) { - Remember(bits_MEMORY_PROVOKED); - - StopFollowing(true); + Provoke((CBaseEntity*)GET_PRIVATE(ENT(pevAttacker))); } } @@ -479,8 +477,7 @@ int CBaseGrunt :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, f // Alright, now I'm pissed! PlaySentenceSound(HGRUNT_SENT_MAD); - Remember(bits_MEMORY_PROVOKED); - StopFollowing(TRUE); + Provoke(attacker); ALERT(at_console, "Monster is now MAD!\n"); } else @@ -720,7 +717,7 @@ void CBaseGrunt::ShootMinigun(Vector& vecShootOrigin, Vector& vecShootDir) { void CBaseGrunt::ShootSniper(Vector& vecShootOrigin, Vector& vecShootDir) { //TODO: why is this 556? is 762 too damaging? FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_1DEGREES, 8192, BULLET_MONSTER_762); - EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/sniper_fire.wav", 1, 0.3); + EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/sniper_fire.wav", 1, 0.2); } void CBaseGrunt ::ShootShotgun(Vector& vecShootOrigin, Vector& vecShootDir) @@ -889,6 +886,11 @@ bool CBaseGrunt::DropEquipment(int attachmentIdx, int equipMask, Vector velocity Vector vecGunAngles; GetAttachment(attachmentIdx, vecGunPos, vecGunAngles); + if (POINT_CONTENTS(vecGunPos) == CONTENTS_SOLID) { + vecGunPos = pev->origin; + vecGunPos.z += pev->maxs.z * 0.5f; + } + int equipmentToDrop = m_iEquipment & equipMask; bool droppedAnything = false; @@ -1117,7 +1119,9 @@ void CBaseGrunt::InitAiFlags() { canCallMedic = false; suppressOccludedTarget = false; maxSuppressTime = 3.0f; - maxShootDist = 2048; + + if (!maxShootDist) + maxShootDist = 2048; } void CBaseGrunt::BasePrecache() { diff --git a/dlls/monster/CBaseMonster.cpp b/dlls/monster/CBaseMonster.cpp index 5cb3762b..859557d9 100644 --- a/dlls/monster/CBaseMonster.cpp +++ b/dlls/monster/CBaseMonster.cpp @@ -1035,6 +1035,7 @@ int CBaseMonster::CheckEnemy(CBaseEntity* pEnemy) if (!pEnemy->IsAlive()) { + OnKillProvoker(m_hEnemy); SetConditions(bits_COND_ENEMY_DEAD); ClearConditions(bits_COND_SEE_ENEMY | bits_COND_ENEMY_OCCLUDED); return FALSE; @@ -2187,8 +2188,10 @@ void CBaseMonster::MonsterInit(void) m_hEnemy = NULL; - m_flDistTooFar = 1024.0; - m_flDistLook = 2048.0; + if (m_flDistLook == 0) { + m_flDistTooFar = 1024.0; + m_flDistLook = 2048.0; + } m_lastInterpOrigin = pev->origin; @@ -2372,7 +2375,7 @@ int CBaseMonster::Classify(int defaultClassify) { // if player ally is set, then ally status towards players is inverted if (m_IsPlayerAlly) { - bool isDefaultPlayerAlly = IRelationship(defaultClassify, CLASS_PLAYER) == R_AL; + bool isDefaultPlayerAlly = CBaseEntity::IRelationship(defaultClassify, CLASS_PLAYER) == R_AL; if (isDefaultPlayerAlly) { // if the monster is allied by default, then isPlayerAlly makes it hostile. @@ -3798,6 +3801,10 @@ BOOL CBaseMonster::GetEnemy(void) } } + if (m_hEnemy && (m_hEnemy->pev->flags & FL_NOTARGET)) { + m_hEnemy = NULL; + } + // remember old enemies if (m_hEnemy == NULL && PopEnemy()) { @@ -7316,7 +7323,7 @@ BOOL CBaseMonster::CanFollow(void) if (!IsAlive()) return FALSE; - return !IsFollowing(); + return TRUE; } @@ -7333,7 +7340,7 @@ void CBaseMonster::FollowerUse(CBaseEntity* pActivator, CBaseEntity* pCaller, US { DeclineFollowing(); } - else if (CanFollow()) + else if (CanFollow() && (!IsFollowing() || m_hTargetEnt.GetEntity() != pActivator)) { if (canBeMadAtPlayer && (m_afMemory & bits_MEMORY_PROVOKED)) { const char* name = DisplayName(); @@ -7484,7 +7491,7 @@ void CBaseMonster::SetHealth() { void CBaseMonster::InitModel() { SET_MODEL(edict(), GetModel()); - bool isAlly = IRelationship(Classify(), CLASS_PLAYER) == R_AL; + bool isAlly = CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL; if (isAlly != m_friendlySkinFirst) { // use friendly skin @@ -7511,7 +7518,7 @@ void CBaseMonster::Nerf() { } } - if (IRelationship(CLASS_PLAYER, Classify()) <= R_NO && !IsMachine()) { + if (CBaseEntity::IRelationship(CLASS_PLAYER, Classify()) <= R_NO && !IsMachine()) { return; // don't care about friendlies } @@ -7601,7 +7608,7 @@ void CBaseMonster::Nerf() { // allow the custom extra health } - if (IRelationship(CLASS_PLAYER, Classify()) > R_NO || (IsTurret() && !m_IsPlayerAlly)) { + if (CBaseEntity::IRelationship(CLASS_PLAYER, Classify()) > R_NO || (IsTurret() && !m_IsPlayerAlly)) { g_nerfStats.totalMonsterHealth += pev->health; g_nerfStats.totalMonsters++; } @@ -7841,4 +7848,63 @@ float CBaseMonster::GetDamage(float defaultDamage) { // owner damage overrides self damage (snarks, grenades, etc.) return (mon ? mon->GetDamage(defaultDamage) : defaultDamage) * GetDamageModifier(); +} + +void CBaseMonster::Provoke(CBaseEntity* attacker) { + Remember(bits_MEMORY_PROVOKED); + StopFollowing(TRUE); + + if (attacker) + m_bMadPlayer[attacker->entindex() - 1] = true; +} + +void CBaseMonster::OnKillProvoker(CBaseEntity* provoker) { + if (!provoker || !provoker->IsPlayer()) { + return; + } + + m_bMadPlayer[provoker->entindex() - 1] = false; + + bool anyTargetsLeft = false; + for (int i = 0; i < 32; i++) { + if (m_bMadPlayer[i]) { + CBasePlayer* plr = UTIL_PlayerByIndex(i + 1); + + if (!plr) { + m_bMadPlayer[i] = false; + continue; + } + + anyTargetsLeft = true; + } + } + + if (!anyTargetsLeft) { + Forget(bits_MEMORY_PROVOKED); + } +} + +void CBaseMonster::Unprovoke(bool friendsToo) { + Forget(bits_MEMORY_PROVOKED); + + if (m_hEnemy) { + int irel = IRelationship(m_hEnemy); + + if (m_hEnemy && m_hEnemy->IsPlayer() && (irel == R_NO || irel == R_AL)) { + m_hEnemy = NULL; + } + } + + if (friendsToo) { + UnprovokeFriends(); + } +} + +int CBaseMonster::IRelationship(CBaseEntity* pTarget) +{ + if (m_afMemory & bits_MEMORY_PROVOKED) + if (pTarget->IsPlayer() && m_bMadPlayer[pTarget->entindex() - 1]) + return R_HT; + + return CBaseToggle::IRelationship(pTarget); } \ No newline at end of file diff --git a/dlls/monster/CBaseMonster.h b/dlls/monster/CBaseMonster.h index c5d77bb3..e48404a3 100644 --- a/dlls/monster/CBaseMonster.h +++ b/dlls/monster/CBaseMonster.h @@ -152,6 +152,7 @@ class EXPORT CBaseMonster : public CBaseToggle bool m_friendlySkinFirst; // true if the friendly skin comes before the enemy skin bool canBeMadAtPlayer; // grunt will retaliate on too much friendly fire + bool m_bMadPlayer[32]; // players this friendly is mad at int m_freeroam; int m_lastNode; int m_targetNode; @@ -476,6 +477,12 @@ class EXPORT CBaseMonster : public CBaseToggle virtual float GetDamageModifier(); virtual float GetDamage(float defaultDamage); + + virtual void Provoke(CBaseEntity* attacker); + virtual void OnKillProvoker(CBaseEntity* provoker); + virtual void Unprovoke(bool friendsToo); + virtual void UnprovokeFriends(void) {} // calms an npc and friends down that was provoked by a player's friendly fire + virtual int IRelationship(CBaseEntity* pTarget) override; }; diff --git a/dlls/monster/CBaseTurret.h b/dlls/monster/CBaseTurret.h index 80e60859..9f8c7d63 100644 --- a/dlls/monster/CBaseTurret.h +++ b/dlls/monster/CBaseTurret.h @@ -32,7 +32,7 @@ class EXPORT CBaseTurret : public CBaseMonster virtual int Classify(void); const char* GetDeathNoticeWeapon() { return "weapon_9mmAR"; } BOOL IsMachine() { return 1; } // ignore classification overrides - BOOL IsTurret() { return 1; } + BOOL IsNormalMonster(void) { return FALSE; } void DeathSound(); int BloodColor(void) { return DONT_BLEED; } diff --git a/dlls/monster/CBullsquid.cpp b/dlls/monster/CBullsquid.cpp index 6f9bf73d..56ebf7c0 100644 --- a/dlls/monster/CBullsquid.cpp +++ b/dlls/monster/CBullsquid.cpp @@ -1117,7 +1117,8 @@ Schedule_t *CBullsquid :: GetSchedule( void ) return GetScheduleOfType ( SCHED_MELEE_ATTACK2 ); } - return GetScheduleOfType ( SCHED_CHASE_ENEMY ); + if (m_hEnemy && m_hEnemy->IsAlive()) + return GetScheduleOfType ( SCHED_CHASE_ENEMY ); break; } diff --git a/dlls/monster/CController.cpp b/dlls/monster/CController.cpp index a8c86c9e..20010453 100644 --- a/dlls/monster/CController.cpp +++ b/dlls/monster/CController.cpp @@ -323,7 +323,7 @@ void CController :: HandleAnimEvent( MonsterEvent_t *pEvent ) pBall->pev->velocity = Vector( 0, 0, 32 ); pBall->m_hEnemy = m_hEnemy; - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { pBall->pev->rendercolor = Vector(0, 255, 255); } @@ -673,7 +673,7 @@ void CController :: RunTask ( Task_t *pTask ) CBaseMonster *pBall = (CBaseMonster*)Create( "controller_energy_ball", vecSrc, pev->angles, edict() ); pBall->pev->velocity = vecDir; - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { pBall->pev->rendercolor = Vector(0, 255, 255); } } @@ -881,7 +881,7 @@ void CController :: RunAI( void ) ball->SetAttachment( edict(), (i + 3) ); ball->SetScale( 1.0 ); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { ball->SetColor(0, 255, 255); } diff --git a/dlls/monster/CGargantua.h b/dlls/monster/CGargantua.h index da8fa9db..2d8f2494 100644 --- a/dlls/monster/CGargantua.h +++ b/dlls/monster/CGargantua.h @@ -51,6 +51,7 @@ class CStomp : public CBaseEntity void Spawn(void); void Think(void); static CStomp* StompCreate(const Vector& origin, const Vector& end, edict_t* owner, float speed, float damage); + const char* GetDeathNoticeWeapon() { return "weapon_crowbar"; } private: // UNDONE: re-use this sprite list instead of creating new ones all the time diff --git a/dlls/monster/CHornet.cpp b/dlls/monster/CHornet.cpp index 9e37792d..46bf44d6 100644 --- a/dlls/monster/CHornet.cpp +++ b/dlls/monster/CHornet.cpp @@ -249,7 +249,7 @@ old colors */ CBaseEntity* owner = CBaseEntity::Instance(pev->owner); CBaseMonster* mon = owner ? owner->MyMonsterPointer() : NULL; - bool firedByAllyMonster = mon && !mon->IsPlayer() && mon->IRelationship(mon->Classify(), CLASS_PLAYER) == R_AL; + bool firedByAllyMonster = mon && !mon->IsPlayer() && CBaseEntity::IRelationship(mon->Classify(), CLASS_PLAYER) == R_AL; // trail RGBA color = RGBA(255,255,255); diff --git a/dlls/monster/CISlave.cpp b/dlls/monster/CISlave.cpp index b36166ff..8c69cce8 100644 --- a/dlls/monster/CISlave.cpp +++ b/dlls/monster/CISlave.cpp @@ -539,7 +539,7 @@ void CISlave :: StartTask ( Task_t *pTask ) { ClearBeams( ); - CTalkSquadMonster :: StartTask ( pTask ); + CTalkSquadMonster:: StartTask ( pTask ); } void CISlave::RunTask(Task_t* pTask) @@ -548,7 +548,7 @@ void CISlave::RunTask(Task_t* pTask) { case TASK_MOVE_TO_TARGET_RANGE: { - CBaseMonster::RunTask(pTask); + CTalkSquadMonster::RunTask(pTask); // always run when following someone because the walk speed is painfully slow m_movementActivity = ACT_RUN; @@ -556,7 +556,7 @@ void CISlave::RunTask(Task_t* pTask) } default: { - CBaseMonster::RunTask(pTask); + CTalkSquadMonster::RunTask(pTask); } } } @@ -584,7 +584,7 @@ void CISlave :: Spawn() MonsterInit(); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { m_beamColor = Vector(96, 180, 255); } else { diff --git a/dlls/monster/CKingpin.cpp b/dlls/monster/CKingpin.cpp index b176dd13..98119df3 100644 --- a/dlls/monster/CKingpin.cpp +++ b/dlls/monster/CKingpin.cpp @@ -430,7 +430,7 @@ void CKingpin::Spawn() MonsterInit(); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { m_beamColor = Vector(16, 255, 255); } else { diff --git a/dlls/monster/CMonsterMaker.cpp b/dlls/monster/CMonsterMaker.cpp index 4bbe3637..09c41f2e 100644 --- a/dlls/monster/CMonsterMaker.cpp +++ b/dlls/monster/CMonsterMaker.cpp @@ -750,7 +750,7 @@ void CMonsterMaker::Nerf() { int clazz = Classify(); - if (IRelationship(CLASS_PLAYER, clazz) <= R_NO || !strcmp(spawnCname, "monster_snark")) { + if (CBaseEntity::IRelationship(CLASS_PLAYER, clazz) <= R_NO || !strcmp(spawnCname, "monster_snark")) { return; // don't care about nerfing friendlies/insects/snarks } diff --git a/dlls/monster/COsprey.cpp b/dlls/monster/COsprey.cpp index 4ef00ad1..99e3b13b 100644 --- a/dlls/monster/COsprey.cpp +++ b/dlls/monster/COsprey.cpp @@ -229,12 +229,12 @@ void COsprey :: FindAllThink( void ) { CBaseEntity *pEntity = NULL; - bool isOspreyPlayerAlly = IRelationship(Classify(), CLASS_PLAYER) == R_AL; + bool isOspreyPlayerAlly = CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL; m_iUnits = 0; while (m_iUnits < OSPREY_MAX_CARRY && (pEntity = UTIL_FindEntityByClassname( pEntity, replenishMonster)) != NULL) { - bool isUnitPlayerAlly = IRelationship(pEntity->Classify(), CLASS_PLAYER) == R_AL; + bool isUnitPlayerAlly = CBaseEntity::IRelationship(pEntity->Classify(), CLASS_PLAYER) == R_AL; if (pEntity->IsAlive() && isUnitPlayerAlly == isOspreyPlayerAlly) { m_hGrunt[m_iUnits] = pEntity; diff --git a/dlls/monster/COtis.cpp b/dlls/monster/COtis.cpp index a5277cce..8fcac03b 100644 --- a/dlls/monster/COtis.cpp +++ b/dlls/monster/COtis.cpp @@ -874,6 +874,7 @@ int COtis :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float { m_flPlayerDamage += flDamage; + ALERT(at_console, "MY enemy is %s\n", m_hEnemy ? m_hEnemy->DisplayName() : "NULL"); // This is a heurstic to determine if the player intended to harm me // If I have an enemy, we can't establish intent (may just be crossfire) if ( m_hEnemy == NULL ) @@ -884,8 +885,7 @@ int COtis :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float // Alright, now I'm pissed! PlaySentence( "OT_MAD", 4, VOL_NORM, ATTN_NORM ); - Remember( bits_MEMORY_PROVOKED ); - StopFollowing( TRUE ); + Provoke(attacker); } else { @@ -1030,10 +1030,8 @@ Schedule_t *COtis :: GetSchedule ( void ) if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) ) return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND ); } - if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() ) - { + if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak()) PlaySentence( "OT_KILL", 4, VOL_NORM, ATTN_NORM ); - } switch( m_MonsterState ) { diff --git a/dlls/monster/CScientist.cpp b/dlls/monster/CScientist.cpp index 91036046..c8c1b903 100644 --- a/dlls/monster/CScientist.cpp +++ b/dlls/monster/CScientist.cpp @@ -763,8 +763,7 @@ int CScientist :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, f if ( pevInflictor && pevInflictor->flags & FL_CLIENT ) { - Remember( bits_MEMORY_PROVOKED ); - StopFollowing( TRUE ); + Provoke((CBaseEntity*)GET_PRIVATE(ENT(pevAttacker))); } // make sure friends talk about it if player hurts scientist... diff --git a/dlls/monster/CShockTrooper.cpp b/dlls/monster/CShockTrooper.cpp index 9a370149..92c99ad5 100644 --- a/dlls/monster/CShockTrooper.cpp +++ b/dlls/monster/CShockTrooper.cpp @@ -325,10 +325,17 @@ void CShockTrooper::GibMonster() if (mon) { + // prevent dropping roach inside walls + TraceResult tr; + TRACE_MONSTER_HULL(mon->edict(), mon->pev->origin, mon->pev->origin, ignore_monsters, NULL, &tr); + if (tr.fStartSolid) { + UTIL_SetOrigin(mon->pev, pev->origin + Vector(0, 0, pev->maxs.z * 0.5f)); + } + mon->pev->velocity = Vector(RANDOM_FLOAT(-100, 100), RANDOM_FLOAT(-100, 100), RANDOM_FLOAT(200, 300)); mon->pev->avelocity = Vector(0, RANDOM_FLOAT(200, 400), 0); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { mon->pev->skin = 1; mon->m_IsPlayerAlly = TRUE; } @@ -939,7 +946,7 @@ void CShockTrooper::HandleAnimEvent(MonsterEvent_t* pEvent) mon->pev->velocity = Vector(RANDOM_FLOAT(-20, 20), RANDOM_FLOAT(-20, 20), RANDOM_FLOAT(20, 30)); mon->pev->avelocity = Vector(0, RANDOM_FLOAT(20, 40), 0); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { mon->pev->skin = 1; mon->m_IsPlayerAlly = TRUE; } diff --git a/dlls/monster/CTalkSquadMonster.cpp b/dlls/monster/CTalkSquadMonster.cpp index 57068387..71ac61e9 100644 --- a/dlls/monster/CTalkSquadMonster.cpp +++ b/dlls/monster/CTalkSquadMonster.cpp @@ -478,7 +478,7 @@ void CTalkSquadMonster :: RunTask( Task_t *pTask ) break; case TASK_TLK_EYECONTACT: - if (!IsMoving() && IsTalking() && m_hTalkTarget != NULL) + if (!IsMoving() && IsTalking() && m_hTalkTarget != NULL && !IsFollowing()) { // ALERT( at_console, "waiting %f\n", m_flStopTalkTime - gpGlobals->time ); IdleHeadTurn( m_hTalkTarget->pev->origin ); @@ -546,7 +546,7 @@ void CTalkSquadMonster :: Killed( entvars_t *pevAttacker, int iGib ) // If a client killed me (unless I was already Barnacle'd), make everyone else mad/afraid of him if ((pevAttacker->flags & FL_CLIENT) && m_MonsterState != MONSTERSTATE_PRONE ) { - AlertFriends(); + AlertFriends((CBaseEntity*)GET_PRIVATE(ENT(pevAttacker))); //LimitFollowers( CBaseEntity::Instance(pevAttacker), 0 ); } @@ -604,7 +604,7 @@ CBaseEntity *CTalkSquadMonster::EnumFriends( CBaseEntity *pPrevious, int listNum } -void CTalkSquadMonster::AlertFriends( void ) +void CTalkSquadMonster::AlertFriends(CBaseEntity* attacker) { CBaseEntity *pFriend = NULL; int i; @@ -618,25 +618,12 @@ void CTalkSquadMonster::AlertFriends( void ) if (pMonster && pMonster->IsAlive() && pMonster->canBeMadAtPlayer) { // don't provoke a friend that's playing a death animation. They're a goner pMonster->m_afMemory |= bits_MEMORY_PROVOKED; - } - } - } -} -void CTalkSquadMonster::Unprovoke(bool friendsToo) { - Forget(bits_MEMORY_PROVOKED); - - if (m_hEnemy) { - int irel = IRelationship(m_hEnemy); - - if (m_hEnemy && m_hEnemy->IsPlayer() && (irel == R_NO || irel == R_AL)) { - m_hEnemy = NULL; + if (attacker) + pMonster->m_bMadPlayer[attacker->entindex()-1] = true; + } } } - - if (friendsToo) { - UnprovokeFriends(); - } } void CTalkSquadMonster::UnprovokeFriends(void) { @@ -1125,7 +1112,7 @@ Schedule_t* CTalkSquadMonster :: GetScheduleOfType ( int Type ) // speak during 'use' if (RANDOM_LONG(0,99) < 2) //ALERT ( at_console, "target chase speak\n" ); - return slIdleSpeakWait; + return IsFollowing() ? slIdleSpeak : slIdleSpeakWait; else return slFaceTarget; @@ -1248,16 +1235,6 @@ void CTalkSquadMonster :: TrySmellTalk( void ) } - -int CTalkSquadMonster::IRelationship( CBaseEntity *pTarget ) -{ - if ( pTarget->IsPlayer() ) - if ( m_afMemory & bits_MEMORY_PROVOKED ) - return R_HT; - return CBaseMonster::IRelationship( pTarget ); -} - - void CTalkSquadMonster::KeyValue( KeyValueData *pkvd ) { if (FStrEq(pkvd->szKeyName, "UseSentence")) diff --git a/dlls/monster/CTalkSquadMonster.h b/dlls/monster/CTalkSquadMonster.h index b5c388a6..8b89e2c2 100644 --- a/dlls/monster/CTalkSquadMonster.h +++ b/dlls/monster/CTalkSquadMonster.h @@ -124,7 +124,6 @@ class EXPORT CTalkSquadMonster : public CBaseMonster virtual void Precache( void ); int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); void Killed( entvars_t *pevAttacker, int iGib ); - int IRelationship ( CBaseEntity *pTarget ); virtual int CanPlaySentence( BOOL fDisregardState ); virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ); @@ -150,9 +149,8 @@ class EXPORT CTalkSquadMonster : public CBaseMonster int FOkToSpeak( void ); void TrySmellTalk( void ); CBaseEntity *EnumFriends( CBaseEntity *pentPrevious, int listNumber, BOOL bTrace ); - void AlertFriends( void ); - void Unprovoke( bool friendsToo ); - void UnprovokeFriends( void ); // calms an npc and friends down that was provoked by a player's friendly fire + void AlertFriends( CBaseEntity* attacker); + virtual void UnprovokeFriends( void ); // calms an npc and friends down that was provoked by a player's friendly fire void ShutUpFriends( void ); BOOL IsTalking( void ); void Talk( float flDuration ); diff --git a/dlls/monster/CTor.cpp b/dlls/monster/CTor.cpp index c9eae33f..6bbad047 100644 --- a/dlls/monster/CTor.cpp +++ b/dlls/monster/CTor.cpp @@ -542,7 +542,7 @@ void CTor::Spawn() MonsterInit(); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { beamColor1 = Vector(16, 255, 255); beamColor2 = Vector(128, 255, 255); } diff --git a/dlls/monster/CTurret.cpp b/dlls/monster/CTurret.cpp index 4d8fb35b..790feae3 100644 --- a/dlls/monster/CTurret.cpp +++ b/dlls/monster/CTurret.cpp @@ -61,7 +61,7 @@ void CTurret::Spawn() // setup friendly glow bool oldOn = m_iOn; m_iOn = true; - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { eye->SetTransparency(kRenderGlow, 0, 255, 0, 0, kRenderFxNoDissipation); } else { diff --git a/dlls/monster/CVoltigore.cpp b/dlls/monster/CVoltigore.cpp index e26a3c19..df107465 100644 --- a/dlls/monster/CVoltigore.cpp +++ b/dlls/monster/CVoltigore.cpp @@ -286,7 +286,7 @@ void CVoltigore::Spawn() beam->EntsInit(entindex(), entindex()); beam->SetStartAttachment(i+1); // head, left hand, right hand beam->SetEndAttachment(4); - if (CBaseMonster::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { + if (CBaseEntity::IRelationship(Classify(), CLASS_PLAYER) == R_AL) { beam->SetColor(140, 255, 96); } else { @@ -558,7 +558,7 @@ void CVoltigoreShock::Spawn(void) CBaseEntity* owner = CBaseEntity::Instance(pev->owner); CBaseMonster* mon = owner ? owner->MyMonsterPointer() : NULL; - bool isAllyShock = mon && CBaseMonster::IRelationship(mon->Classify(), CLASS_PLAYER) == R_AL; + bool isAllyShock = mon && CBaseEntity::IRelationship(mon->Classify(), CLASS_PLAYER) == R_AL; for (int i = 0; i < VOLTI_SHOCK_FLY_BEAMS; i++) { CBeam* beam = CBeam::BeamCreate(VOLTI_BEAM_SPRITE, 30); diff --git a/dlls/triggers/CTriggerCamera.cpp b/dlls/triggers/CTriggerCamera.cpp index bd2e885b..fffeb59a 100644 --- a/dlls/triggers/CTriggerCamera.cpp +++ b/dlls/triggers/CTriggerCamera.cpp @@ -12,7 +12,7 @@ #define SF_CAMERA_PLAYER_TAKECONTROL 4 // freeze viewers #define SF_CAMERA_ALL_PLAYERS 8 // force everyone to view, dead or alive #define SF_CAMERA_FORCE_VIEW 16 // activator is forced to view even if dead ("all players" also does this) -#define SF_CAMERA_NO_INSTANT_TURN 32 // if enabled, smoothly rotate to face targets +#define SF_CAMERA_INSTANT_TURN 32 // if enabled, don't smoothly rotate to face target #define SF_CAMERA_PLAYER_INVULNERABLE 256 // disable viewer damage while camera is active class CTriggerCamera : public CBaseDelay @@ -257,7 +257,7 @@ void CTriggerCamera::FollowTarget() Vector vecGoal = UTIL_VecToAngles(m_hTarget->pev->origin - pev->origin); vecGoal.x = -vecGoal.x; - if (pev->spawnflags & SF_CAMERA_NO_INSTANT_TURN) { + if (!(pev->spawnflags & SF_CAMERA_INSTANT_TURN)) { if (pev->angles.y > 360) pev->angles.y -= 360;