ValveSoftware / source-sdk-2013

The 2013 edition of the Source SDK
https://developer.valvesoftware.com/wiki/SDK2013_GettingStarted
Other
3.84k stars 2.01k forks source link

Combine Soldier Fail Schedule is not very...robust (and can break legacy content) #589

Open ihonnyboy opened 2 months ago

ihonnyboy commented 2 months ago

The fail schedule in question is the one at line 1880 of npc_combine.cpp

if( failedSchedule == SCHED_COMBINE_TAKE_COVER1 )
    {
        if( IsInSquad() && IsStrategySlotRangeOccupied(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2) && HasCondition(COND_SEE_ENEMY) )
        {
            // This eases the effects of an unfortunate bug that usually plagues shotgunners. Since their rate of fire is low,
            // they spend relatively long periods of time without an attack squad slot. If you corner a shotgunner, usually 
            // the other memebers of the squad will hog all of the attack slots and pick schedules to move to establish line of
            // fire. During this time, the shotgunner is prevented from attacking. If he also cannot find cover (the fallback case)
            // he will stand around like an idiot, right in front of you. Instead of this, we have him run up to you for a melee attack.
            return SCHED_COMBINE_MOVE_TO_MELEE;
        }
    }

This is plagued by several different issues with the implementation, but it can mostly rear its ugly head in older Half-Life 2 levels such as the coast. A combine may make a poor cover choice, such as a pole or tree, and if the player simply strafes left or right, the cover chosen would invalidate, failing the schedule, and triggering the above code. In earlier builds, the Combine would pause for a second, and then restart their decision making. It is most noticeable in the opening corridor of "d2_prison_04", however. The Combine there use Hint Groups, and in older builds, they would stay in place and shoot from cover, but the hint groups limit their cover search, triggering the above line of code.

This can be really bad in mods where Half-Life 2's typical level design can be--ahem--stretched outside of what it typically does. I have attempted to work around this in the past with custom code, while still looking out for the original situation described in the comment block. I could list the numerous fixes I've done, but there are multiple ways to tackle this. The main issues are:

  1. The fail schedule "SCHED_COMBINE_MOVE_TO_MELEE" doesn't really do what it says it does and is remarkably similar to "SCHED_COMBINE_PRESS_ATTACK".

The fail schedule will cause the NPC to charge to a save position, not the enemy in question, so it could--conceivably--not even get the ai to melee. The schedule itself is also very strict, and doesn't have the looser break conditions of press_attack. This can lead to very stilted and often suicidal behavior. Additionally, considering the issue has to do with squad slots, there are no checks in the schedule to see if a quad slot has opened up. This could result in a Combine Soldier running a very long way, and arriving at his destination long after a squad slot opens (thankfully, the move-and-shoot code still works).

  1. The conditions to trigger "SCHED_COMBINE_MOVE_TO_MELEE" are very generalized (especially for such a specific fix).

The fail schedule conditions make no considerations for fail codes, weapon ranges, equipped weapon, or hint grouping. Unlike in something like the base zombie code, the Combine code does not check the failure codes to see why the cover schedule failed. The comment block seems to describe situations where the NPC has no cover, but the failure can trigger on multiple conditions, such as cover being invalidated. There are situations where, for example, a hint grouped (not nav limited) npc could see the player from miles away (outside of weapon range), not have a squad slot, and as long as they can path to the player, the NPC could run all that distance to the punch the player. Or, an npc could be running to a piece of breakable cover, that cover is broken, and instead of running to a new piece of cover (or using a non-weapon attack such as grenades), they will charge straight at the enemy.

Some of this comes down to designer intent and Quality of Life decisions for modders, but the odd behavior it can trigger in some of the more open-ended encounters of Half-Life 2 (behavior that did not exist previously) should be considered.