void AlienBuildableComponent::Blast(int timeDelta) {
	float          splashDamage = (float)entity.oldEnt->splashDamage;
	float          splashRadius = (float)entity.oldEnt->splashRadius;
	meansOfDeath_t splashMOD    = (meansOfDeath_t)entity.oldEnt->splashMethodOfDeath;

	// Damage close humans.
	Utility::AntiHumanRadiusDamage(entity, splashDamage, splashRadius, splashMOD);

	// Reward attackers.
	G_RewardAttackers(entity.oldEnt);

	// Stop collisions, add blast event and update buildable state.
	entity.oldEnt->r.contents = 0; trap_LinkEntity(entity.oldEnt);
	G_AddEvent(entity.oldEnt, EV_ALIEN_BUILDABLE_EXPLOSION, DirToByte(entity.oldEnt->s.origin2));
	GetBuildableComponent().SetState(BuildableComponent::POST_BLAST); // Makes entity invisible.

	// Start creep recede with a brief delay.
	GetBuildableComponent().REGISTER_THINKER(CreepRecede, ThinkingComponent::SCHEDULER_AVERAGE, 500);
	GetBuildableComponent().GetThinkingComponent().UnregisterActiveThinker();
}
예제 #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;
}
예제 #3
0
파일: g_combat.c 프로젝트: ZdrytchX/cuboid
/*
==================
player_die
==================
*/
void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath )
{
  gentity_t *ent, *ent2;
  int       anim;
  int       killer;
  int       i;
  char      *killerName, *obit;
  vec3_t    dir;

  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 >= sizeof( modNames ) / sizeof( modNames[0] ) )
    // 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,
    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 );

  // kill all player's buildables if they havent spawned yet
  // this should eliminate build timer hacks for ever
  dir[0] = dir[1] = 0.0f;
  dir[2] = 1.0f;
   
  for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ )
  {
    if( ent->s.eType != ET_BUILDABLE )
      continue;

    if( ent == self )
      continue;

    if( ent->spawned )
      continue;

    if( ent->builtBy != self->client->ps.clientNum )
      continue;
    
    G_Damage( ent, self, attacker, dir, dir, ent->health, 0, MOD_DECONSTRUCT );
  }
  
  // broadcast the death event to everyone
  ent = G_TempEntity( 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

  self->enemy = attacker;
  self->client->ps.persistant[ PERS_KILLED ]++;

  if( attacker && attacker->client )
  {
    attacker->client->lastkilled_client = self->s.number;

    if( ( attacker == self || OnSameTeam( self, attacker ) ) && meansOfDeath != MOD_HSPAWN )
    {
      //punish team kills and suicides
      if( attacker->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
      {
        G_AddCreditToClient( attacker->client, -ALIEN_TK_SUICIDE_PENALTY, qtrue );
        AddScore( attacker, -ALIEN_TK_SUICIDE_PENALTY );
      }
      else if( attacker->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
      {
        G_AddCreditToClient( attacker->client, -HUMAN_TK_SUICIDE_PENALTY, qtrue );
        AddScore( attacker, -HUMAN_TK_SUICIDE_PENALTY );
      }
    }
  }
  else if( attacker->s.eType != ET_BUILDABLE )
  {
    if( self->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
      AddScore( self, -ALIEN_TK_SUICIDE_PENALTY );
    else if( self->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
      AddScore( 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;
  self->r.contents = CONTENTS_CORPSE;

  self->s.angles[ PITCH ] = 0;
  self->s.angles[ ROLL ] = 0;
  self->s.angles[ YAW ] = self->s.apos.trBase[ YAW ];
  
  if( meansOfDeath != MOD_ALIEN_HATCH ) //don't look at the alien that jumped out of your chest, it screws up the camera
   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 ) );

  {
    // normal death
    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 );
}