Skip to content

Commit

Permalink
fixes/tweaks
Browse files Browse the repository at this point in the history
fixes:
- extremely high HP not showing in status bar
- crowbar creating ricochet effects on grunt/tor armor
- tor never flinching
- floating spore ammo
- voltigore beams not always removed when killed
- houndeyes damaging each other
- invisible but nearby objects not making sounds (outside PVS or world)
- scripted_sequence moving monsters upwards

tweaks:
- predator class prioritizes player targets over itself (bullsquid)
- rename "Explosives (explosives only)" to "Breakable (explosives only)"
- spore grenades don't damage gargs
- remove barney/otis explosives resistance
- npc ranged attacks are interrupted by heavy damage, not just any damage
- spore does timed poison damage
- monsters in combat take more more damage before flinching (20 -> 50)
  • Loading branch information
wootguy committed Oct 16, 2024
1 parent 017e1b1 commit d83c56f
Show file tree
Hide file tree
Showing 17 changed files with 117 additions and 59 deletions.
6 changes: 5 additions & 1 deletion dlls/CBaseEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ int CBaseEntity::IRelationship(int attackerClass, int victimClass) {
/*ALIENPASSIVE*/{ R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO, R_NO, R_NO },
/*ALIENMONSTER*/{ R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_NO, R_NO },
/*ALIENPREY */{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_FR ,R_NO ,R_DL, R_NO, R_NO, R_NO, R_NO },
/*ALIENPREDATO*/{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_DL, R_NO, R_NO, R_DL, R_DL },
/*ALIENPREDATO*/{ R_NO ,R_NO ,R_HT ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_HT ,R_DL ,R_NO ,R_HT, R_NO, R_NO, R_DL, R_DL },
/*INSECT*/ { R_FR ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR, R_NO, R_NO, R_NO, R_NO },
/*PLAYERALLY*/ { R_NO ,R_DL ,R_AL ,R_AL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_NO, R_NO, R_DL, R_DL },
/*PBIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_NO, R_DL, R_DL, R_DL },
Expand Down Expand Up @@ -986,4 +986,8 @@ bool CBaseEntity::CanReach(CBaseEntity* toucher) {
bool enteredItemBox = boxesIntersect(pev->absmin, pev->absmax, tr.vecEndPos, tr.vecEndPos);

return hitItemSurface || enteredItemBox;
}

bool CBaseEntity::IsVisibleTo(edict_t* player) {
return m_visiblePlayers & PLRBIT(player);
}
5 changes: 3 additions & 2 deletions dlls/CBasePlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2019,7 +2019,7 @@ void CBasePlayer::UpdateStatusBar()
}
else if (pEntity->IsMonster() && pEntity->IsAlive() && !ignoreMonster) {
name = replaceString(pEntity->DisplayName(), "\n", " ");
int hp = roundf(pEntity->pev->health);
long long hp = roundf(pEntity->pev->health);

int irel = IRelationship(pEntity);

Expand Down Expand Up @@ -2051,7 +2051,8 @@ void CBasePlayer::UpdateStatusBar()
hp = 1; // client won't show health text if this is 0
}
else {
strcpy_safe(sbuf0, UTIL_VarArgs("2 Health: %d", hp), SBAR_STRING_SIZE);
strcpy_safe(sbuf0, UTIL_VarArgs("2 Health: %lld", hp), SBAR_STRING_SIZE);
hp = 1;
}

newSBarState[SBAR_ID_TARGETNAME] = entindex();
Expand Down
3 changes: 3 additions & 0 deletions dlls/cbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,9 @@ class EXPORT CBaseEntity
// or is there something in the way? (player use code assumes arms have noclip)
bool CanReach(CBaseEntity* toucher);

// true if the player can potentially see this entity
bool IsVisibleTo(edict_t* player);

//We use this variables to store each ammo count.
int ammo_9mm;
int ammo_357;
Expand Down
2 changes: 1 addition & 1 deletion dlls/func/CBreakable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ const char* CBreakable::DisplayName() {
if (m_displayName) {
return STRING(m_displayName);
}
return Explodable() ? "Explosives" : "Breakable";
return Explodable() && !(pev->spawnflags & SF_BREAK_EXPLOSIVES_ONLY) ? "Explosives" : "Breakable";
}

void CBreakable::BreakTouch(CBaseEntity* pOther)
Expand Down
2 changes: 1 addition & 1 deletion dlls/monster/CAGrunt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void CAGrunt :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecD
pev->dmgtime = gpGlobals->time;
}

if ( RANDOM_LONG( 0, 1 ) == 0 )
if ( (bitsDamageType & DMG_BULLET) && RANDOM_LONG( 0, 1 ) == 0 )
{
Vector vecTracerDir = vecDir;

Expand Down
2 changes: 1 addition & 1 deletion dlls/monster/CBarney.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ void CBarney::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
{
case HITGROUP_CHEST:
case HITGROUP_STOMACH:
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
if (bitsDamageType & (DMG_BULLET | DMG_SLASH))
{
flDamage = flDamage / 2;
}
Expand Down
19 changes: 13 additions & 6 deletions dlls/monster/CBaseMonster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4607,7 +4607,10 @@ int CBaseMonster::TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, fl
SetConditions(bits_COND_LIGHT_DAMAGE);
}

if (flDamage >= 20)
// HL sets this to 20, but monsters are getting stunlocked often in co-op
int flinchAmount = (m_IdealMonsterState == MONSTERSTATE_COMBAT) ? 50 : 20;

if (flDamage >= flinchAmount)
{
SetConditions(bits_COND_HEAVY_DAMAGE);
}
Expand Down Expand Up @@ -6484,7 +6487,11 @@ void CBaseMonster::StartTask(Task_t* pTask)
{
if (m_hTargetEnt != NULL)
{
pev->origin = m_hTargetEnt->pev->origin; // Plant on target
Vector scriptOri = m_hTargetEnt->pev->origin;
TraceResult tr;
TRACE_MONSTER_HULL(edict(), scriptOri, scriptOri - Vector(0, 0, 512), ignore_monsters, edict(), &tr);

pev->origin = tr.vecEndPos; // Plant on floor under script
}

TaskComplete();
Expand Down Expand Up @@ -7427,14 +7434,14 @@ const char* CBaseMonster::DisplayName() {
}

bool CBaseMonster::IsImmune(entvars_t* attacker) {
if (!IsAlive()) {
return false;
}

if (!pev->takedamage || (pev->flags & FL_GODMODE)) {
return true;
}

if (!IsAlive()) {
return false;
}

if (pev->flags & FL_CLIENT) {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions dlls/monster/CGargantua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,10 @@ int CGargantua::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, flo
if (IsImmune(pevAttacker))
return 0;

if (!(bitsDamageType & GARG_DAMAGE)) {
flDamage = 0;
}

if ( IsAlive() )
{
if ( !(bitsDamageType & GARG_DAMAGE) )
Expand Down
2 changes: 1 addition & 1 deletion dlls/monster/CHoundeye.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ void CHoundeye :: SonicAttack ( void )
continue;
}

if (FClassnameIs(pEntity->pev, "monster_houndeye") && IRelationship(pEntity) == R_AL) {
if (FClassnameIs(pEntity->pev, "monster_houndeye") && IRelationship(pEntity) <= R_NO) {
continue; // houndeyes don't hurt other houndeyes with their attack, unless they're enemies
}

Expand Down
2 changes: 1 addition & 1 deletion dlls/monster/COtis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ void COtis::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir,
{
case HITGROUP_CHEST:
case HITGROUP_STOMACH:
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
if (bitsDamageType & (DMG_BULLET | DMG_SLASH))
{
flDamage = flDamage / 2;
}
Expand Down
39 changes: 16 additions & 23 deletions dlls/monster/CTor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class CTor : public CBaseMonster
int Classify(void);
const char* DisplayName();
void HandleAnimEvent(MonsterEvent_t* pEvent);
Schedule_t* GetSchedule(void);
Schedule_t* GetScheduleOfType(int Type);
Schedule_t* GetMonsterStateSchedule(void);

void MonsterThink(void);
BOOL CheckRangeAttack1(float flDot, float flDist);
Expand Down Expand Up @@ -286,30 +286,15 @@ void CTor::HandleAnimEvent(MonsterEvent_t* pEvent)
}
}

Schedule_t* CTor::GetScheduleOfType(int Type) {
if (Type == SCHED_RANGE_ATTACK2) {
return slSummonAttack;
}
if (Type == SCHED_MELEE_ATTACK2) {
AttackSound();
}

return CBaseMonster::GetScheduleOfType(Type);
}

Schedule_t* CTor::GetMonsterStateSchedule(void) {
Schedule_t* CTor::GetSchedule(void)
{
if (HasConditions(bits_COND_HEAVY_DAMAGE))
{
// flinch for heavy damage but not too often
if (RANDOM_LONG(0, 2) == 0) {
return GetScheduleOfType(SCHED_SMALL_FLINCH);
}
else {
ClearConditions(bits_COND_HEAVY_DAMAGE);
return CBaseMonster::GetSchedule();
}
ClearConditions(bits_COND_HEAVY_DAMAGE);
return GetScheduleOfType(SCHED_SMALL_FLINCH);
}
else if (HasConditions(bits_COND_LIGHT_DAMAGE))

if (HasConditions(bits_COND_LIGHT_DAMAGE))
{
ClearConditions(bits_COND_LIGHT_DAMAGE);
// never flinch or retreat from light damage
Expand All @@ -319,6 +304,14 @@ Schedule_t* CTor::GetMonsterStateSchedule(void) {
return CBaseMonster::GetSchedule();
}

Schedule_t* CTor::GetScheduleOfType(int Type) {
if (Type == SCHED_MELEE_ATTACK2) {
AttackSound();
}

return CBaseMonster::GetScheduleOfType(Type);
}

void CTor::MonsterThink(void) {
if (nextBeamBurst && nextBeamBurst < gpGlobals->time) {
pev->framerate = 0.001f;
Expand Down Expand Up @@ -474,7 +467,7 @@ void CTor::TraceAttack(entvars_t* pevAttacker, float flDamage, Vector vecDir, Tr
pev->dmgtime = gpGlobals->time;
}

if (RANDOM_LONG(0, 1) == 0)
if ((bitsDamageType & DMG_BULLET) && RANDOM_LONG(0, 1) == 0)
{
Vector vecTracerDir = vecDir;

Expand Down
39 changes: 26 additions & 13 deletions dlls/monster/CVoltigore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class CVoltigore : public CBaseMonster
const char* GetDeathNoticeWeapon() {
return IsAlive() ? "weapon_crowbar" : "grenade";
}
void UpdateOnRemove(void);

private:
float m_rangeAttackCooldown; // next time a range attack can be considered
Expand Down Expand Up @@ -368,11 +369,6 @@ void CVoltigore::ExplodeThink(void) {
CBaseMonster::MonsterThink();

if (explodeTime < gpGlobals->time) {
for (int i = 0; i < VOLTI_SHOCK_DEATH_BEAMS; i++) {
UTIL_Remove(m_pDeathBeam[i]);
m_pDeathBeam[i] = NULL;
}

EMIT_SOUND(ENT(pev), CHAN_BODY, VOLTI_SPORE_EXPLODE_SOUND, 1, ATTN_NORM);
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "common/bodysplat.wav", 0.5, ATTN_NORM);

Expand Down Expand Up @@ -430,15 +426,18 @@ void CVoltigore::Killed(entvars_t* pevAttacker, int iGib)
m_pBeam[i] = NULL;
}

for (int i = 0; i < VOLTI_SHOCK_DEATH_BEAMS; i++) {
CBeam* beam = CBeam::BeamCreate(VOLTI_BEAM_SPRITE, 30);
beam->PointsInit(RandomBeamPoint(pev), pev->origin + Vector(0,0,32));
beam->SetColor(255, 16, 128);
beam->SetBrightness(128);
beam->SetNoise(80);
m_pDeathBeam[i] = beam;
}
if (!m_pDeathBeam[0]) {
for (int i = 0; i < VOLTI_SHOCK_DEATH_BEAMS; i++) {

CBeam* beam = CBeam::BeamCreate(VOLTI_BEAM_SPRITE, 30);
beam->PointsInit(RandomBeamPoint(pev), pev->origin + Vector(0, 0, 32));
beam->SetColor(255, 16, 128);
beam->SetBrightness(128);
beam->SetNoise(80);
m_pDeathBeam[i] = beam;
}
}

CBaseMonster::Killed(pevAttacker, GIB_NEVER);

if (ShouldGibMonster(iGib)) {
Expand Down Expand Up @@ -513,6 +512,20 @@ void CVoltigore::CantFollowSound() {
EMIT_SOUND(ENT(pev), CHAN_ITEM, RANDOM_SOUND_ARRAY(pPainSounds), 1, ATTN_NORM);
}

void CVoltigore::UpdateOnRemove(void) {
UTIL_Remove(m_handShock);
for (int i = 0; i < VOLTI_SHOCK_CHARGE_BEAMS; i++) {
UTIL_Remove(m_pBeam[i]);
m_pBeam[i] = NULL;
}
for (int i = 0; i < VOLTI_SHOCK_DEATH_BEAMS; i++) {
UTIL_Remove(m_pDeathBeam[i]);
m_pDeathBeam[i] = NULL;
}

CBaseEntity::UpdateOnRemove();
}

//
// voltigore shock
//
Expand Down
4 changes: 2 additions & 2 deletions dlls/monster/defaultai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ Schedule_t slRangeAttack1[] =
ARRAYSIZE ( tlRangeAttack1 ),
bits_COND_NEW_ENEMY |
bits_COND_ENEMY_DEAD |
bits_COND_LIGHT_DAMAGE |
//bits_COND_LIGHT_DAMAGE | // TODO: may want to selectively disable this per monster
bits_COND_HEAVY_DAMAGE |
bits_COND_ENEMY_OCCLUDED |
bits_COND_NO_AMMO_LOADED |
Expand All @@ -511,7 +511,7 @@ Schedule_t slRangeAttack2[] =
ARRAYSIZE ( tlRangeAttack2 ),
bits_COND_NEW_ENEMY |
bits_COND_ENEMY_DEAD |
bits_COND_LIGHT_DAMAGE |
//bits_COND_LIGHT_DAMAGE | // TODO: may want to selectively disable this per monster
bits_COND_HEAVY_DAMAGE |
bits_COND_ENEMY_OCCLUDED |
bits_COND_HEAR_SOUND,
Expand Down
24 changes: 23 additions & 1 deletion dlls/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,30 @@ void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volu
else
ALERT( at_aiconsole, "Unable to find %s in sentences.txt\n", sample );
}
else
else {
EMIT_SOUND_DYN2(entity, channel, sample, volume, attenuation, flags, pitch);

CBaseEntity* bent = CBaseEntity::Instance(entity);
if (channel == CHAN_STATIC) {
// the static channel is special because it ignores the PAS. However, clients won't hear
// the sound if they can't see the entity, even if it's nearby. This block will emit
// positional sounds for those cases. This has the drawback of sound not following the
// entity, but is better than hearing nothing at all.

Vector ori = entity->v.origin + (entity->v.maxs + entity->v.mins) * 0.5f;

for (int i = 1; i <= gpGlobals->maxClients; i++) {
edict_t* plr = INDEXENT(i);
if (!IsValidPlayer(plr)) {
continue;
}

if (!bent->IsVisibleTo(plr)) {
ambientsound_msg(entity, ori, sample, volume, attenuation, flags, pitch, MSG_ONE, plr);
}
}
}
}
}

void PLAY_DISTANT_SOUND(edict_t* emitter, int soundType) {
Expand Down
4 changes: 4 additions & 0 deletions dlls/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,10 @@ EXPORT void UTIL_ShowMessageAll ( const char *pString );
EXPORT void UTIL_ScreenFadeAll ( const Vector &color, float fadeTime, float holdTime, int alpha, int flags );
EXPORT void UTIL_ScreenFade ( CBaseEntity *pEntity, const Vector &color, float fadeTime, float fadeHold, int alpha, int flags );

// duplicate of the engine function with the ability to change the message mode and target entity
EXPORT void ambientsound_msg(edict_t* entity, float* pos, const char* samp, float vol, float attenuation,
int fFlags, int pitch, int msgDst, edict_t* dest);

// leave target NULL to play music for all players
EXPORT void UTIL_PlayGlobalMp3(const char* path, bool loop, edict_t* target=NULL);

Expand Down
6 changes: 3 additions & 3 deletions dlls/weapon/CSpore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void CSpore::IgniteThink()
WRITE_BYTE( 80 );
MESSAGE_END();

::RadiusDamage( pev->origin, pev, VARS( pev->owner ), pev->dmg, 200, CLASS_NONE, DMG_ALWAYSGIB | DMG_BLAST );
::RadiusDamage( pev->origin, pev, VARS( pev->owner ), pev->dmg, 200, CLASS_NONE, DMG_ALWAYSGIB | DMG_POISON);

SetThink( &CSpore::SUB_Remove );

Expand Down Expand Up @@ -228,7 +228,7 @@ void CSpore::RocketTouch( CBaseEntity* pOther )
{
if( pOther->pev->takedamage != DAMAGE_NO )
{
pOther->TakeDamage( pev, VARS( pev->owner ), gSkillData.sk_plr_spore, DMG_GENERIC );
pOther->TakeDamage( pev, VARS( pev->owner ), gSkillData.sk_plr_spore, DMG_ACID);
}

IgniteThink();
Expand Down Expand Up @@ -259,7 +259,7 @@ void CSpore::MyBounceTouch( CBaseEntity* pOther )
}
else
{
pOther->TakeDamage( pev, VARS( pev->owner ), gSkillData.sk_plr_spore, DMG_GENERIC );
pOther->TakeDamage( pev, VARS( pev->owner ), gSkillData.sk_plr_spore, DMG_ACID);

IgniteThink();
}
Expand Down
13 changes: 10 additions & 3 deletions dlls/weapon/CSporeAmmo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,18 @@ class CSporeAmmo : public CBasePlayerAmmo

UTIL_SetSize(pev, Vector(-16, -16, -16), Vector(16, 16, 16));

pev->origin.z += 16;
pev->angles.x -= 90;

UTIL_SetOrigin(pev, pev->origin);
// align to the floor/ceiling (TODO: this is stupid, ripent the maps)
MAKE_VECTORS(pev->angles);
if (gpGlobals->v_up.z > 0.9f) {
pev->origin.z -= 16;
}
else if (gpGlobals->v_up.z < -0.9f) {
pev->origin.z += 16;
}

pev->angles.x -= 90;
UTIL_SetOrigin(pev, pev->origin);

pev->sequence = SPOREAMMO_SPAWNDN;

Expand Down

0 comments on commit d83c56f

Please sign in to comment.