Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ProdigySim/e0a9aeaa82d720f74493 to your computer and use it in GitHub Desktop.

Select an option

Save ProdigySim/e0a9aeaa82d720f74493 to your computer and use it in GitHub Desktop.
CTerrorPlayer::UpdateZombieFrustration()
// Reverse-engineered CTerrorPlayer::UpdateZombieFrustration().
// I can claim no copyright for this code.
// This representation of code was produced by reverse engineering for interoperability.
// Any resemblance to original source is completely accidental.
void CTerrorPlayer::UpdateZombieFrustration()
{
if ( !ZombieFrustration.GetBool())
|| this->GetTeamNumber() != 3
|| this->GetClass() != 8
|| this->IsBot()
|| this->IsGhost)()
|| !TheDirector->m_bTankFrustrationEnabled )
{
// Frustration is not currently enabled, reset the frustration var to 0% frustrated
goto RESET_FRUSTRATION;
}
if ( !this->m_FrustrationUpdateTimer.HasStarted()
|| !this->m_FrustrationUpdateTimer.IsElapsed()) )
{
// It's not time to update frustration yet
return;
}
// How long has it been since the tank last saw a player?
float flTimeSinceLastLOS = this->m_TimeSinceLastLOS.GetElapsedTime();
if ( flTimeSinceLastLOS <= ZombieFrustrationLOSDelay.GetFloat()) )
{
// It hasn't been at least z_frustration_los_delay seconds since the last LOS of the tank.
// Don't tick down the frustration yet.
return;
}
// Set the next frustration update to happen in another second.
this->m_FrustrationUpdateTimer.Start(1.0);
// LSCFLAG_SKIP_INCAPPED=1,
// LSCFLAG_ONLY_INCAPPED=2,
// LSCFLAG_SKIP_BOTS=4,
int liveSurvivorCount = ForEachTerrorPlayer<LiveSurvivorCounter>(LSCFLAG_SKIP_INCAPPED);
if ( !liveSurvivorCount )
{
RESET_FRUSTRATION:
// Networkvar update.
// Setting frustration to 0 means "full" rage meter, i.e. not going to pass.
this->.m_frustration = 0;
return;
}
if ( !TheDirector->HasAnySurvivorLeftSafeArea()
|| !CDirector::IsAnySurvivorInExitCheckpoint()
|| TheDirector->IsFinaleWon() )
{
// Freeze current frustration in these cases.
return;
}
int currentFrustration = a1->CTerrorPlayer.m_frustration;
// Calculate what one more tick of frustration will add as a percent of 100.
float newFrustration = currentFrustration + (100 / ZombieFrustrationLifetime.GetInt());
// Clamp the value to an upper bound of 100.
// (Note: this is probably done with a macro in original source, evidenced by duplicate calculations of the previous value)
newFrustration = newFrustration <= 100 ? newFrustration : 100;
if(currentFrustration != newFrustration)
{
// NetworkVar Update
this->m_frustration = newFrustration;
}
// If we're not at 100 frustration yet, or something something, we're done here.
if ( newFrustration <= 99 || this->unknown328[7] & 8 )
return;
// Otherwise, the tank is frustrated! Whatever shall we do!
if ( TheDirector->ChallengeModePtr->TankRun() )
{
// When a tank gets frustrated in "TankRun" mode, we apparently kill it.
CBasePlayer::CommitSuicide(a1, 0, 0);
return;
}
// This method was actually inlined, but it's just a big hunk of player looping code.
// Checks for: (GetTeamNumber() == 3 && !IsBot() && !IsAlive()) || GetTeamNumber() != 3 || GetClass() != 8)
// The conflicting conditionals point to a bug... But I'm not really sure.
int eligiblePassTargetCount = CountEligibleTankTargets();
// I don't know why they don't just use IsElapsed()...
// There's some odd repetition here that suggests Macro usage
if(TheDirector->TankLotteryEntryTimer.GetRemainingRatio() == 0.0f)
{
// Fire the frustrated event so clients and other stuff know about it.
IGameEvent * event = gameeventmanager->CreateEvent("tank_frustrated");
if ( event )
{
// I don't really know how the edict_t reference is retrieved, but this is basically what's happening.
event->SetInt("userid", engine->GetPlayerUserId(this->GetEdict()));
gameeventmanager->FireEvent(event);
}
if ( eligiblePassTargetCount && TheDirector->m_iTankSwapCount <= 1 )
{
TheDirector->TryOfferingTankBot(this, false);
}
else
{
// Offering tank bot currently unavailable for some reason.
this->ReplaceWithBot(false);
this->SetPreSpawnClass(ZC_HUNTER); // Set to spawn as a hunter I guess...
this->State_Transition(CCSPlayerState_GHOST); // Transition to ghost state (state 8 anyway, I think it's ghost)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment