I spend some hours in the last days digging into the reaction fire, because it doesn't work in 2.3 as is quite well known by now.
I fixed some obvious bugs (about the same fixed in the commit link before) and did some other changes. And, surprise, it still didn't work.
Some debugging later I found the problem:
G_ReactionFireShoot() calls G_ClientShoot() to do the actual shooting, both for mock (probability determination) and the real action.
G_ClientShoot() calls in both cases G_ActionCheckWithoutTeam() to check whether taking a shot is actually a valid action.
G_ActionCheckWithoutTeam() calls G_ActionCheck() to, well, do what it's supposed to do.
G_ActionCheck() checks some stuff and at the end calls G_ActorUsableTUs() to look whether there are enough TUs left.
Thus far all is fine, so let's have a look at G_ActorUsableTUs():
int G_ActorUsableTUs (const edict_t *ent)
{
...
return ent->TU - G_ActorGetReservedTUs(ent);
}
Now have a look at G_ActorGetReservedTUs():
int G_ActorGetReservedTUs (const edict_t *ent)
{
const chrReservations_t *res = &ent->chr.reservedTus;
return res->reaction + res->shot + res->crouch;
}
Summary: G_ActorUsableTUs() returns the amount of TUs left and not reserved. If this is greater than the required TUs to fire the weapon, a shot taken. While this makes sense if you simply trigger a shot by clicking an enemy, it's quite bad in reaction fire. Because, obviously, this means that no reaction fire takes place if no unreserved TUs are left.
Executive summary: If you got exactly the amount of TUs left you need for reaction fire, no reaction fire will take place. If you got, by happy chance, after reservation still enough TUs left for that weapon, the actor will fire. As most players will optimize movement to not have any TUs spare, they will never see reaction fire.
What hence needs to be done:
G_ActorUsableTUs() must honor TU reservation only when actions under player control are taking place. During reaction fire, all reservations must be ignored.
If someone tells me who's responsible, I can probably submit a patch to solve that problem.