void BuildableComponent::HandleDie(gentity_t* killer, meansOfDeath_t meansOfDeath) {
	// Note that this->state is adjusted in (Alien|Human)BuildableComponent::HandleDie so they have
	// access to its current value.

	TeamComponent::team_t team = GetTeamComponent().Team();

	// TODO: Move animation code to BuildableComponent.
	G_SetBuildableAnim(entity.oldEnt, Powered() ? BANIM_DESTROY : BANIM_DESTROY_UNPOWERED, true);
	G_SetIdleBuildableAnim(entity.oldEnt, BANIM_DESTROYED);

	entity.oldEnt->killedBy = killer->s.number;

	G_LogDestruction(entity.oldEnt, killer, meansOfDeath);

	// TODO: Handle in TaggableComponent.
	Beacon::DetachTags(entity.oldEnt);

	// Report an attack to the defending team if the buildable was powered and there is a main
	// buildable that can report it. Note that the main buildables itself issues its own warnings.
	if (Powered() && entity.Get<MainBuildableComponent>() == nullptr &&
	    G_IsWarnableMOD(meansOfDeath) && G_ActiveMainBuildable(team)) {
		// Get a nearby location entity.
		gentity_t *location = GetCloseLocationEntity(entity.oldEnt);

		// Fall back to fake location entity if necessary.
		if (!location) location = level.fakeLocation;

		// Warn if there was no warning for this location recently.
		if (level.time > location->warnTimer) {
			bool inBase = G_InsideBase(entity.oldEnt);

			G_BroadcastEvent(EV_WARN_ATTACK, inBase ? 0 : location->s.number, team);
			Beacon::NewArea(BCT_DEFEND, entity.oldEnt->s.origin, team);
			location->warnTimer = level.time + ATTACKWARN_NEARBY_PERIOD;
		}
	}

	// If not deconstructed, add all build points to queue.
	if (meansOfDeath != MOD_DECONSTRUCT && meansOfDeath != MOD_REPLACE) {
		G_FreeBudget(team, 0, BG_Buildable(entity.oldEnt->s.modelindex)->buildPoints);
	}
}
Beispiel #2
0
void CheckTeamStatus()
{
	int       i;
	gentity_t *loc, *ent;

	if ( level.time - level.lastTeamLocationTime > TEAM_LOCATION_UPDATE_TIME )
	{
		level.lastTeamLocationTime = level.time;

		for ( i = 0; i < level.maxclients; i++ )
		{
			ent = g_entities + i;

			if ( ent->client->pers.connected != CON_CONNECTED )
			{
				continue;
			}

			if ( ent->inuse && ( ent->client->pers.team == TEAM_HUMANS ||
			                     ent->client->pers.team == TEAM_ALIENS ) )
			{
				loc = GetCloseLocationEntity( ent );

				if ( loc )
				{
					if( ent->client->pers.location != loc->s.generic1 )
					{
						ent->client->pers.infoChangeTime = level.time;
						ent->client->pers.location = loc->s.generic1;
					}
				}
				else if ( ent->client->pers.location != 0 )
				{
					ent->client->pers.infoChangeTime = level.time;
					ent->client->pers.location = 0;
				}
			}
		}

		for ( i = 0; i < level.maxclients; i++ )
		{
			ent = g_entities + i;

			if ( ent->client->pers.connected != CON_CONNECTED )
			{
				continue;
			}

			if ( ent->inuse )
			{
				TeamplayInfoMessage( ent );
			}
		}
	}

	// Warn on imbalanced teams
	if ( g_teamImbalanceWarnings.integer && !level.intermissiontime &&
	     ( level.time - level.lastTeamImbalancedTime >
	       ( g_teamImbalanceWarnings.integer * 1000 ) ) &&
	     level.numTeamImbalanceWarnings < 3 && !level.restarted )
	{
		level.lastTeamImbalancedTime = level.time;

		if ( level.team[ TEAM_ALIENS ].numSpawns > 0 &&
		     level.team[ TEAM_HUMANS ].numClients - level.team[ TEAM_ALIENS ].numClients > 2 )
		{
			trap_SendServerCommand( -1, "print_tr \"" N_("Teams are imbalanced. "
			                        "Humans have more players.") "\"" );
			level.numTeamImbalanceWarnings++;
		}
		else if ( level.team[ TEAM_HUMANS ].numSpawns > 0 &&
		          level.team[ TEAM_ALIENS ].numClients - level.team[ TEAM_HUMANS ].numClients > 2 )
		{
			trap_SendServerCommand( -1, "print_tr \"" N_("Teams are imbalanced. "
			                        "Aliens have more players.") "\"" );
			level.numTeamImbalanceWarnings++;
		}
		else
		{
			level.numTeamImbalanceWarnings = 0;
		}
	}
}