Beispiel #1
0
void game_score_act( gentity_t *self, gentity_t*, gentity_t *activator )
{
	if ( !activator )
	{
		return;
	}

	G_AddCreditsToScore( activator, self->config.amount );
}
Beispiel #2
0
/*
==================
player_die
==================
*/
void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int meansOfDeath )
{
	gentity_t *ent;
	int       anim;
	int       killer;
	int       i;
	const char *killerName, *obit;

	if ( self->client->ps.pm_type == PM_DEAD )
	{
		return;
	}

	if ( level.intermissiontime )
	{
		return;
	}

	self->client->ps.pm_type = PM_DEAD;
	self->suicideTime = 0;

	if ( attacker )
	{
		killer = attacker->s.number;

		if ( attacker->client )
		{
			killerName = attacker->client->pers.netname;
		}
		else
		{
			killerName = "<world>";
		}
	}
	else
	{
		killer = ENTITYNUM_WORLD;
		killerName = "<world>";
	}

	if ( meansOfDeath < 0 || meansOfDeath >= ARRAY_LEN( modNames ) )
	{
		// fall back on the number
		obit = va( "%d", meansOfDeath );
	}
	else
	{
		obit = modNames[ meansOfDeath ];
	}

	G_LogPrintf( "Die: %d %d %s: %s" S_COLOR_WHITE " killed %s\n",
	             killer,
	             ( int )( self - g_entities ),
	             obit,
	             killerName,
	             self->client->pers.netname );

	// deactivate all upgrades
	for ( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
	{
		BG_DeactivateUpgrade( i, self->client->ps.stats );
	}

	// broadcast the death event to everyone
	ent = G_NewTempEntity( self->r.currentOrigin, EV_OBITUARY );
	ent->s.eventParm = meansOfDeath;
	ent->s.otherEntityNum = self->s.number;
	ent->s.otherEntityNum2 = killer;
	ent->r.svFlags = SVF_BROADCAST; // send to everyone

	if ( attacker && attacker->client )
	{
		if ( ( attacker == self || OnSameTeam( self, attacker ) ) )
		{
			//punish team kills and suicides
			if ( attacker->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
			{
				G_AddCreditToClient( attacker->client, -ALIEN_TK_SUICIDE_PENALTY, qtrue );
				G_AddCreditsToScore( attacker, -ALIEN_TK_SUICIDE_PENALTY );
			}
			else if ( attacker->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
			{
				G_AddCreditToClient( attacker->client, -HUMAN_TK_SUICIDE_PENALTY, qtrue );
				G_AddCreditsToScore( attacker, -HUMAN_TK_SUICIDE_PENALTY );
			}
		}
		else if ( g_showKillerHP.integer )
		{
			trap_SendServerCommand( self - g_entities, va( "print_tr %s %s %3i", QQ( N_("Your killer, $1$^7, had $2$ HP.\n") ),
			                        Quote( killerName ),
			                        attacker->health ) );
		}
	}
	else if ( attacker->s.eType != ET_BUILDABLE )
	{
		if ( self->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
		{
			G_AddCreditsToScore( self, -ALIEN_TK_SUICIDE_PENALTY );
		}
		else if ( self->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
		{
			G_AddCreditsToScore( self, -HUMAN_TK_SUICIDE_PENALTY );
		}
	}

	// give credits for killing this player
	G_RewardAttackers( self );

	ScoreboardMessage( self );  // show scores

	// send updated scores to any clients that are following this one,
	// or they would get stale scoreboards
	for ( i = 0; i < level.maxclients; i++ )
	{
		gclient_t *client;

		client = &level.clients[ i ];

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

		if ( client->sess.spectatorState == SPECTATOR_NOT )
		{
			continue;
		}

		if ( client->sess.spectatorClient == self->s.number )
		{
			ScoreboardMessage( g_entities + i );
		}
	}

	VectorCopy( self->s.origin, self->client->pers.lastDeathLocation );

	self->takedamage = qfalse; // can still be gibbed

	self->s.weapon = WP_NONE;
	if ( self->client->noclip )
	{
		self->client->cliprcontents = CONTENTS_CORPSE;
	}
	else
	{
		self->r.contents = CONTENTS_CORPSE;
	}

	self->s.angles[ PITCH ] = 0;
	self->s.angles[ ROLL ] = 0;
	self->s.angles[ YAW ] = self->s.apos.trBase[ YAW ];
	LookAtKiller( self, inflictor, attacker );

	VectorCopy( self->s.angles, self->client->ps.viewangles );

	self->s.loopSound = 0;

	self->r.maxs[ 2 ] = -8;

	// don't allow respawn until the death anim is done
	// g_forcerespawn may force spawning at some later time
	self->client->respawnTime = level.time + 1700;

	// clear misc
	memset( self->client->ps.misc, 0, sizeof( self->client->ps.misc ) );

	{
		static int i;

		if ( !( self->client->ps.persistant[ PERS_STATE ] & PS_NONSEGMODEL ) )
		{
			switch ( i )
			{
				case 0:
					anim = BOTH_DEATH1;
					break;

				case 1:
					anim = BOTH_DEATH2;
					break;

				case 2:
				default:
					anim = BOTH_DEATH3;
					break;
			}
		}
		else
		{
			switch ( i )
			{
				case 0:
					anim = NSPA_DEATH1;
					break;

				case 1:
					anim = NSPA_DEATH2;
					break;

				case 2:
				default:
					anim = NSPA_DEATH3;
					break;
			}
		}

		self->client->ps.legsAnim =
		  ( ( self->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;

		if ( !( self->client->ps.persistant[ PERS_STATE ] & PS_NONSEGMODEL ) )
		{
			self->client->ps.torsoAnim =
			  ( ( self->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
		}

		// use own entityid if killed by non-client to prevent uint8_t overflow
		G_AddEvent( self, EV_DEATH1 + i,
		            ( killer < MAX_CLIENTS ) ? killer : self - g_entities );

		// globally cycle through the different death animations
		i = ( i + 1 ) % 3;
	}

	trap_LinkEntity( self );

	self->client->pers.infoChangeTime = level.time;
}
Beispiel #3
0
/*
==================
G_RewardAttackers

Function to distribute rewards to entities that killed this one.
==================
*/
void G_RewardAttackers( gentity_t *self )
{
	float     value, reward;
	int       playerNum, enemyDamage, maxHealth, damageShare;
	gentity_t *player;
	team_t    ownTeam, playerTeam;
	confidence_reason_t    reason;
	confidence_qualifier_t qualifier;

	// Only reward killing players and buildables
	if ( self->client )
	{
		ownTeam = self->client->pers.teamSelection;
		maxHealth = self->client->ps.stats[ STAT_MAX_HEALTH ];
		value = ( float )BG_GetValueOfPlayer( &self->client->ps );
	}
	else if ( self->s.eType == ET_BUILDABLE )
	{
		ownTeam = self->buildableTeam;
		maxHealth = BG_Buildable( self->s.modelindex )->health;
		value = ( float )BG_Buildable( self->s.modelindex )->value;

		// Give partial credits for buildables in construction
		if ( !self->spawned )
		{
			value *= ( float )( level.time - self->creationTime ) / BG_Buildable( self->s.modelindex )->buildTime;
		}
	}
	else
	{
		return;
	}

	enemyDamage = 0;

	// Sum up damage dealt by enemies
	for ( playerNum = 0; playerNum < level.maxclients; playerNum++ )
	{
		player = &g_entities[ playerNum ];
		playerTeam = player->client->pers.teamSelection;

		// Player must be on the other team
		if ( playerTeam == ownTeam || playerTeam <= TEAM_NONE || playerTeam >= NUM_TEAMS )
		{
			continue;
		}

		enemyDamage += self->credits[ playerNum ];
	}

	if ( enemyDamage <= 0 )
	{
		return;
	}

	// Give individual rewards
	for ( playerNum = 0; playerNum < level.maxclients; playerNum++ )
	{
		player = &g_entities[ playerNum ];
		playerTeam = player->client->pers.teamSelection;
		damageShare = self->credits[ playerNum ];

		// Clear reward array
		self->credits[ playerNum ] = 0;

		// Player must be on the other team
		if ( playerTeam == ownTeam || playerTeam <= TEAM_NONE || playerTeam >= NUM_TEAMS )
		{
			continue;
		}

		// Player must have dealt damage
		if ( damageShare <= 0 )
		{
			continue;
		}

		reward = value * ( damageShare / ( float )maxHealth );

		if ( reward <= 0.0f )
		{
			continue;
		}

		if ( self->s.eType == ET_BUILDABLE )
		{
			G_AddConfidenceToScore( player, reward );

			switch ( self->s.modelindex )
			{
				case BA_A_OVERMIND:
				case BA_H_REACTOR:
					reason = CONF_REAS_DESTR_CRUCIAL;
					break;

				case BA_A_ACIDTUBE:
				case BA_A_TRAPPER:
				case BA_A_HIVE:
				case BA_H_MGTURRET:
				case BA_H_TESLAGEN:
					reason = CONF_REAS_DESTR_AGGRESSIVE;
					break;

				default:
					reason = CONF_REAS_DESTR_SUPPORT;
			}

			qualifier = CONF_QUAL_NONE;

			G_AddConfidence( playerTeam, CONFIDENCE_DESTRUCTION, reason, qualifier, reward, player );
		}
		else
		{
			G_AddCreditsToScore( player, ( int )reward );
			G_AddCreditToClient( player->client, ( short )reward, qtrue );

			// Give confidence for killing non-naked players outside the friendly base
			switch ( self->client->ps.stats[ STAT_CLASS ] )
			{
				case PCL_ALIEN_LEVEL0:
				case PCL_ALIEN_BUILDER0:
				case PCL_ALIEN_BUILDER0_UPG:
					break;

				case PCL_HUMAN:
					// Treat a human just wearing light armor as naked
					if ( ( int )value <= BG_Class( PCL_HUMAN )->value +
					                     ( BG_Upgrade( UP_LIGHTARMOUR )->price / 2 ) )
					{
						break;
					}

				default:
					if ( G_InsideBase( player, qtrue ) || G_InsideBase( self, qfalse ) )
					{
						break;
					}

					qualifier = CONF_QUAL_OUTSIDE_OWN_BASE;

					G_AddConfidence( playerTeam, CONFIDENCE_KILLING, CONF_REAS_KILLING,
					                 qualifier, reward * CONFIDENCE_PER_CREDIT, player );
			}
		}
	}
}
Beispiel #4
0
/**
 * @brief Function to distribute rewards to entities that killed this one.
 * @param self
 */
void G_RewardAttackers( gentity_t *self )
{
	float     value, share, reward, enemyDamage, damageShare;
	int       playerNum, maxHealth;
	gentity_t *player;
	team_t    ownTeam, playerTeam;

	// Only reward killing players and buildables
	if ( self->client )
	{
		ownTeam   = (team_t) self->client->pers.team;
		maxHealth = self->client->ps.stats[ STAT_MAX_HEALTH ];
		value     = BG_GetValueOfPlayer( &self->client->ps );
	}
	else if ( self->s.eType == ET_BUILDABLE )
	{
		ownTeam   = (team_t) self->buildableTeam;
		maxHealth = BG_Buildable( self->s.modelindex )->health;
		value     = BG_Buildable( self->s.modelindex )->value;

		// Give partial credits for buildables in construction
		if ( !self->spawned )
		{
			value *= ( level.time - self->creationTime ) /
			         ( float )BG_Buildable( self->s.modelindex )->buildTime;
		}
	}
	else
	{
		return;
	}

	// Sum up damage dealt by enemies
	enemyDamage = 0.0f;

	for ( playerNum = 0; playerNum < level.maxclients; playerNum++ )
	{
		player     = &g_entities[ playerNum ];
		playerTeam = (team_t) player->client->pers.team;

		// Player must be on the other team
		if ( playerTeam == ownTeam || playerTeam <= TEAM_NONE || playerTeam >= NUM_TEAMS )
		{
			continue;
		}

		enemyDamage += self->credits[ playerNum ];
	}

	if ( enemyDamage <= 0 )
	{
		return;
	}

	// Give individual rewards
	for ( playerNum = 0; playerNum < level.maxclients; playerNum++ )
	{
		player      = &g_entities[ playerNum ];
		playerTeam  = (team_t) player->client->pers.team;
		damageShare = self->credits[ playerNum ];

		// Clear reward array
		self->credits[ playerNum ] = 0.0f;

		// Player must be on the other team
		if ( playerTeam == ownTeam || playerTeam <= TEAM_NONE || playerTeam >= NUM_TEAMS )
		{
			continue;
		}

		// Player must have dealt damage
		if ( damageShare <= 0.0f )
		{
			continue;
		}

		share  = damageShare / ( float )maxHealth;
		reward = value * share;

		if ( self->s.eType == ET_BUILDABLE )
		{
			// Add score
			G_AddMomentumToScore( player, reward );

			// Add momentum
			G_AddMomentumForDestroyingStep( self, player, share );
		}
		else
		{
			// Add score
			G_AddCreditsToScore( player, ( int )reward );

			// Add credits
			G_AddCreditToClient( player->client, ( short )reward, qtrue );

			// Add momentum
			G_AddMomentumForKillingStep( self, player, share );
		}
	}

	// Complete momentum modification
	G_AddMomentumEnd();
}