Ejemplo n.º 1
0
void
G_domethink(gentity_t *ent)
{
  vec3_t origin, mins ,maxs;
  gentity_t *otherEnt;
  int radius, numListedEntities;
  int entityList[MAX_GENTITIES];
  int e,i;
  float dist;
  vec3_t v;

  ent->nextthink = level.time + 1000;

  if(level.time > ent->dieTime)
  {
    ent->freeAfterEvent = qtrue;
    ent->parent->numDomes -= 1;
    return;
  }

  VectorCopy(ent->s.origin, origin);
  radius = DOME_RANGE;

  for(i = 0;i < 3;i++)
  {
    mins[i] = origin[i] - radius;
    maxs[i] = origin[i] + radius;
  }

  numListedEntities = trap_EntitiesInBox(mins, maxs, entityList, MAX_GENTITIES);

  for(e = 0;e < numListedEntities;e++)
  {
    otherEnt = &g_entities[entityList[e]];

    if(!otherEnt)
      continue;
    if(!otherEnt->client)
      continue;
    if (otherEnt->client->sess.sessionTeam == TEAM_SPECTATOR)
      continue;
    if(otherEnt->health <= 0)
      continue;

    // find the distance from the edge of the bounding box
    for(i = 0;i < 3;i++)
    {
      if (origin[i] < ent->r.absmin[i])
        v[i] = ent->r.absmin[i] - origin[i];
      else if (origin[i] > ent->r.absmax[i])
        v[i] = origin[i] - ent->r.absmax[i];
      else
        v[i] = 0;
    }

    dist = VectorLength(v);
    if (dist >= radius)
      continue;


    if(otherEnt->client->ps.stats[STAT_PTEAM] != PTE_HUMANS)
    {
      otherEnt->client->ps.stats[STAT_STATE] |= SS_CREEPSLOWED;
      continue;
    }

    if (otherEnt->health < 100)
    {
      otherEnt->health = otherEnt->client->ps.stats[STAT_HEALTH]
          = otherEnt->health + 3;
		if ( (otherEnt->client->pers.badges[ 18 ] != 1) && (otherEnt->health >= 75) && otherEnt->client->pers.onehp)
		{
			G_WinBadge( otherEnt, 18 );
			otherEnt->client->pers.badgeupdate[18] = 1;
			otherEnt->client->pers.badges[18] = 1;
		}
      if(otherEnt->health >=100)
      {
        otherEnt->health = otherEnt->client->ps.stats[STAT_HEALTH] = 100;
        //G_AddEvent(otherEnt, EV_MEDKIT_USED, 0);
      }
    }
  }
}
Ejemplo n.º 2
0
/*
============
G_MoverPush

Objects need to be moved back on a failed push,
otherwise riders would continue to slide.
If qfalse is returned, *obstacle will be the blocking entity
============
*/
qboolean G_MoverPush( gentity_t *pusher, vec3_t move, vec3_t amove, gentity_t **obstacle ) {
	int			i, e;
	gentity_t	*check;
	vec3_t		mins, maxs;
	pushed_t	*p;
	int			entityList[MAX_GENTITIES];
	int			listedEntities;
	vec3_t		totalMins, totalMaxs;

	*obstacle = NULL;


	// mins/maxs are the bounds at the destination
	// totalMins / totalMaxs are the bounds for the entire move
	if ( pusher->r.currentAngles[0] || pusher->r.currentAngles[1] || pusher->r.currentAngles[2]
		|| amove[0] || amove[1] || amove[2] ) {
		float		radius;

		radius = RadiusFromBounds( pusher->s.mins, pusher->s.maxs );
		for ( i = 0 ; i < 3 ; i++ ) {
			mins[i] = pusher->r.currentOrigin[i] + move[i] - radius;
			maxs[i] = pusher->r.currentOrigin[i] + move[i] + radius;
			totalMins[i] = mins[i] - move[i];
			totalMaxs[i] = maxs[i] - move[i];
		}
	} else {
		for (i=0 ; i<3 ; i++) {
			mins[i] = pusher->r.absmin[i] + move[i];
			maxs[i] = pusher->r.absmax[i] + move[i];
		}

		VectorCopy( pusher->r.absmin, totalMins );
		VectorCopy( pusher->r.absmax, totalMaxs );
		for (i=0 ; i<3 ; i++) {
			if ( move[i] > 0 ) {
				totalMaxs[i] += move[i];
			} else {
				totalMins[i] += move[i];
			}
		}
	}

	// unlink the pusher so we don't get it in the entityList
	trap_UnlinkEntity( pusher );

	listedEntities = trap_EntitiesInBox( totalMins, totalMaxs, entityList, MAX_GENTITIES );

	// move the pusher to its final position
	VectorAdd( pusher->r.currentOrigin, move, pusher->r.currentOrigin );
	VectorAdd( pusher->r.currentAngles, amove, pusher->r.currentAngles );
	trap_LinkEntity( pusher );

	// see if any solid entities are inside the final position
	for ( e = 0 ; e < listedEntities ; e++ ) {
		check = &g_entities[ entityList[ e ] ];

#ifdef MISSIONPACK
		if ( check->s.eType == ET_MISSILE ) {
			// if it is a prox mine
			if ( !strcmp(check->classname, "prox mine") ) {
				// if this prox mine is attached to this mover try to move it with the pusher
				if ( check->enemy == pusher ) {
					if (!G_TryPushingProxMine( check, pusher, move, amove )) {
						//explode
						check->s.loopSound = 0;
						G_AddEvent( check, EV_PROXIMITY_MINE_TRIGGER, 0 );
						G_ExplodeMissile(check);
						if (check->activator) {
							G_FreeEntity(check->activator);
							check->activator = NULL;
						}
						//G_Printf("prox mine explodes\n");
					}
				}
				else {
					//check if the prox mine is crushed by the mover
					if (!G_CheckProxMinePosition( check )) {
						//explode
						check->s.loopSound = 0;
						G_AddEvent( check, EV_PROXIMITY_MINE_TRIGGER, 0 );
						G_ExplodeMissile(check);
						if (check->activator) {
							G_FreeEntity(check->activator);
							check->activator = NULL;
						}
						//G_Printf("prox mine explodes\n");
					}
				}
				continue;
			}
		}
#endif
		// only push items and players
		if ( check->s.eType != ET_ITEM && check->s.eType != ET_PLAYER && !check->physicsObject ) {
			continue;
		}

		// if the entity is standing on the pusher, it will definitely be moved
		if ( check->s.groundEntityNum != pusher->s.number ) {
			// see if the ent needs to be tested
			if ( check->r.absmin[0] >= maxs[0]
			|| check->r.absmin[1] >= maxs[1]
			|| check->r.absmin[2] >= maxs[2]
			|| check->r.absmax[0] <= mins[0]
			|| check->r.absmax[1] <= mins[1]
			|| check->r.absmax[2] <= mins[2] ) {
				continue;
			}
			// see if the ent's bbox is inside the pusher's final position
			// this does allow a fast moving object to pass through a thin entity...
			if (!G_TestEntityPosition (check)) {
				continue;
			}
		}

		// the entity needs to be pushed
		if ( G_TryPushingEntity( check, pusher, move, amove ) ) {
			continue;
		}

		// the move was blocked an entity

		// bobbing entities are instant-kill and never get blocked
		if ( pusher->s.pos.trType == TR_SINE || pusher->s.apos.trType == TR_SINE ) {
			G_Damage( check, pusher, pusher, NULL, NULL, 99999, 0, MOD_CRUSH );
			continue;
		}

		
		// save off the obstacle so we can call the block function (crush, etc)
		*obstacle = check;

		// move back any entities we already moved
		// go backwards, so if the same entity was pushed
		// twice, it goes back to the original position
		for ( p=pushed_p-1 ; p>=pushed ; p-- ) {
			VectorCopy (p->origin, p->ent->s.pos.trBase);
			VectorCopy (p->angles, p->ent->s.apos.trBase);
			if ( p->ent->client ) {
				p->ent->client->ps.delta_angles[YAW] = p->deltayaw;
				VectorCopy (p->origin, p->ent->client->ps.origin);
			}
			trap_LinkEntity (p->ent);
		}
		return qfalse;
	}

	return qtrue;
}
Ejemplo n.º 3
0
/*
================
G_SetEntState

  sets the entstate of an entity.
================
*/
void G_SetEntState(gentity_t *ent, entState_t state)
{
	if (ent->entstate == state)
	{
		G_DPrintf("G_SetEntState: entity %i [%s] already in desired state [%i]\n", ent->s.number, ent->classname, state);
		return;
	}

	switch (state)
	{
	case STATE_DEFAULT:
		if (ent->entstate == STATE_UNDERCONSTRUCTION)
		{
			ent->clipmask   = ent->realClipmask;
			ent->r.contents = ent->realContents;
			if (!ent->realNonSolidBModel)
			{
				ent->s.eFlags &= ~EF_NONSOLID_BMODEL;
			}
		}

		ent->entstate   = STATE_DEFAULT;
		ent->s.powerups = STATE_DEFAULT;

		if (ent->s.eType == ET_WOLF_OBJECTIVE)
		{
			char cs[MAX_STRING_CHARS];

			trap_GetConfigstring(ent->count, cs, sizeof(cs));
			ent->count2 &= ~256;
			Info_SetValueForKey(cs, "t", va("%i", ent->count2));
			trap_SetConfigstring(ent->count, cs);
		}

		if (ent->s.eType != ET_COMMANDMAP_MARKER)
		{
			trap_LinkEntity(ent);
		}

		// deal with any entities in the solid
		{
			int       listedEntities, e;
			int       entityList[MAX_GENTITIES];
			gentity_t *check, *block;

			listedEntities = trap_EntitiesInBox(ent->r.absmin, ent->r.absmax, entityList, MAX_GENTITIES);

			for (e = 0; e < listedEntities; e++)
			{
				check = &g_entities[entityList[e]];

				// ignore everything but items, players and missiles (grenades too)
				if (check->s.eType != ET_MISSILE && check->s.eType != ET_ITEM && check->s.eType != ET_PLAYER && !check->physicsObject)
				{
					continue;
				}

				if ((block = G_TestEntityPosition(check)) == NULL)
				{
					continue;
				}

				if (block != ent)
				{
					// the entity is blocked by another entity - that block this should take care of this itself
					continue;
				}

				if (check->client || check->s.eType == ET_CORPSE)
				{
					// gibs anything player like
					G_Damage(check, ent, ent, NULL, NULL, 9999, DAMAGE_NO_PROTECTION, MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER);
				}
				else if (check->s.eType == ET_ITEM && check->item->giType == IT_TEAM)
				{
					// see if it's a critical entity, one that we can't just simply kill (basically flags)
					Team_DroppedFlagThink(check);
				}
				else
				{
					// remove the landmine from both teamlists
					if (check->s.eType == ET_MISSILE && check->methodOfDeath == MOD_LANDMINE)
					{
						mapEntityData_t *mEnt;

						if ((mEnt = G_FindMapEntityData(&mapEntityData[0], check - g_entities)) != NULL)
						{
							G_FreeMapEntityData(&mapEntityData[0], mEnt);
						}

						if ((mEnt = G_FindMapEntityData(&mapEntityData[1], check - g_entities)) != NULL)
						{
							G_FreeMapEntityData(&mapEntityData[1], mEnt);
						}
					}

					// just get rid of it
					G_FreeEntity(check);
				}
			}
		}

		break;
	case STATE_UNDERCONSTRUCTION:
		ent->entstate     = STATE_UNDERCONSTRUCTION;
		ent->s.powerups   = STATE_UNDERCONSTRUCTION;
		ent->realClipmask = ent->clipmask;
		if (ent->s.eType != ET_CONSTRUCTIBLE)                               // don't make nonsolid as we want to make them partially solid for staged construction
		{
			ent->clipmask = 0;
		}
		ent->realContents = ent->r.contents;
		if (ent->s.eType != ET_CONSTRUCTIBLE)
		{
			ent->r.contents = 0;
		}
		if (ent->s.eFlags & EF_NONSOLID_BMODEL)
		{
			ent->realNonSolidBModel = qtrue;
		}
		else if (ent->s.eType != ET_CONSTRUCTIBLE)
		{
			ent->s.eFlags |= EF_NONSOLID_BMODEL;
		}

		if (!Q_stricmp(ent->classname, "misc_mg42"))
		{
			// stop using the mg42
			mg42_stopusing(ent);
		}
		else if (!Q_stricmp(ent->classname, "misc_aagun"))
		{
			aagun_stopusing(ent);
		}

		if (ent->s.eType == ET_COMMANDMAP_MARKER)
		{
			mapEntityData_t *mEnt;

			if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[0], mEnt);
			}
			if ((mEnt = G_FindMapEntityData(&mapEntityData[1], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[1], mEnt);
			}
		}

		trap_LinkEntity(ent);
		break;
	case STATE_INVISIBLE:
		if (ent->entstate == STATE_UNDERCONSTRUCTION)
		{
			ent->clipmask   = ent->realClipmask;
			ent->r.contents = ent->realContents;
			if (!ent->realNonSolidBModel)
			{
				ent->s.eFlags &= ~EF_NONSOLID_BMODEL;
			}
		}

		ent->entstate   = STATE_INVISIBLE;
		ent->s.powerups = STATE_INVISIBLE;

		if (!Q_stricmp(ent->classname, "misc_mg42"))
		{
			mg42_stopusing(ent);
		}
		else if (!Q_stricmp(ent->classname, "misc_aagun"))
		{
			aagun_stopusing(ent);
		}
		else if (ent->s.eType == ET_WOLF_OBJECTIVE)
		{
			char cs[MAX_STRING_CHARS];

			trap_GetConfigstring(ent->count, cs, sizeof(cs));
			ent->count2 |= 256;
			Info_SetValueForKey(cs, "t", va("%i", ent->count2));
			trap_SetConfigstring(ent->count, cs);
		}

		if (ent->s.eType == ET_COMMANDMAP_MARKER)
		{
			mapEntityData_t *mEnt;

			if ((mEnt = G_FindMapEntityData(&mapEntityData[0], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[0], mEnt);
			}
			if ((mEnt = G_FindMapEntityData(&mapEntityData[1], ent - g_entities)) != NULL)
			{
				G_FreeMapEntityData(&mapEntityData[1], mEnt);
			}
		}

		trap_UnlinkEntity(ent);
		break;
	}
}
Ejemplo n.º 4
0
/*
============
G_TouchTriggers

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters.
============
*/
void    G_TouchTriggers( gentity_t *ent ) {
	int i, num;
	int touch[MAX_GENTITIES];
	gentity_t   *hit;
	trace_t trace;
	vec3_t mins, maxs;
	static vec3_t range = { 40, 40, 52 };

	if ( !ent->client ) {
		return;
	}

	// dead clients don't activate triggers!
	if ( ent->client->ps.stats[STAT_HEALTH] <= 0 ) {
		return;
	}

	VectorSubtract( ent->client->ps.origin, range, mins );
	VectorAdd( ent->client->ps.origin, range, maxs );

	num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

	// can't use ent->absmin, because that has a one unit pad
	VectorAdd( ent->client->ps.origin, ent->r.mins, mins );
	VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs );

	for ( i = 0 ; i < num ; i++ ) {
		hit = &g_entities[touch[i]];

		if ( !hit->touch && !ent->touch ) {
			continue;
		}
		if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) {
			continue;
		}

		// ignore most entities if a spectator
		if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
			if ( hit->s.eType != ET_TELEPORT_TRIGGER ) {
				continue;
			}
		}

		// use seperate code for determining if an item is picked up
		// so you don't have to actually contact its bounding box
		if ( hit->s.eType == ET_ITEM ) {
			if ( !BG_PlayerTouchesItem( &ent->client->ps, &hit->s, level.time ) ) {
				continue;
			}
		} else {
			// MrE: always use capsule for player
			//if ( !trap_EntityContactCapsule( mins, maxs, hit ) ) {
			if ( !trap_EntityContact( mins, maxs, hit ) ) {
				continue;
			}
		}

		memset( &trace, 0, sizeof( trace ) );

		if ( hit->touch ) {
			hit->touch( hit, ent, &trace );
		}

		if ( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) ) {
			ent->touch( ent, hit, &trace );
		}
	}
}
Ejemplo n.º 5
0
int Team_TouchOurFlag( gentity_t *ent, gentity_t *other, int team ) {
	int			i, num, j, enemyTeam;
	gentity_t	*player;
	gclient_t	*cl = other->client;
	int			enemy_flag;
	vec3_t		mins, maxs;
	int			touch[MAX_GENTITIES];
	gentity_t*	enemy;
	float		enemyDist, dist;

	if (cl->sess.sessionTeam == TEAM_RED) {
		enemy_flag = PW_BLUEFLAG;
	} else {
		enemy_flag = PW_REDFLAG;
	}

	if ( ent->flags & FL_DROPPED_ITEM ) {
		// hey, its not home.  return it by teleporting it back
		//PrintMsg( NULL, "%s" S_COLOR_WHITE " returned the %s flag!\n", 
		//	cl->pers.netname, TeamName(team));
		PrintCTFMessage(other->s.number, team, CTFMESSAGE_PLAYER_RETURNED_FLAG);

		AddScore(other, ent->r.currentOrigin, CTF_RECOVERY_BONUS);
		other->client->pers.teamState.flagrecovery++;
		other->client->pers.teamState.lastreturnedflag = level.time;
		//ResetFlag will remove this entity!  We must return zero
		Team_ReturnFlagSound(Team_ResetFlag(team), team);
		return 0;
	}

	// the flag is at home base.  if the player has the enemy
	// flag, he's just won!
	if (!cl->ps.powerups[enemy_flag])
		return 0; // We don't have the flag

	// fix: captures after timelimit hit could 
	// cause game ending with tied score
	if ( level.intermissionQueued ) {
		return 0;
	}

	// check for enemy closer to grab the flag
	VectorSubtract( ent->s.pos.trBase, minFlagRange, mins );
	VectorAdd( ent->s.pos.trBase, maxFlagRange, maxs );

	num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

	dist = Distance(ent->s.pos.trBase, other->client->ps.origin);
		
	if (other->client->sess.sessionTeam == TEAM_RED){
		enemyTeam = TEAM_BLUE;
	} else {
		enemyTeam = TEAM_RED;
	}	

	for ( j=0 ; j<num ; j++ ) {
		enemy = (g_entities + touch[j]);

		if (!enemy || !enemy->inuse || !enemy->client){
			continue;
		}

		//check if its alive
		if (enemy->health < 1)
			continue;		// dead people can't pickup

		//ignore specs
		if (enemy->client->sess.sessionTeam == TEAM_SPECTATOR)
			continue;

		//check if this is enemy
		if ((enemy->client->sess.sessionTeam != TEAM_RED && enemy->client->sess.sessionTeam != TEAM_BLUE) ||
			enemy->client->sess.sessionTeam != enemyTeam){
			continue;
		}
			
		//check if enemy is closer to our flag than us
		enemyDist = Distance(ent->s.pos.trBase,enemy->client->ps.origin);
		if (enemyDist < dist){
			// possible recursion is hidden in this, but 
			// infinite recursion wont happen, because we cant 
			// have a < b and b < a at the same time
			return Team_TouchEnemyFlag( ent, enemy, team );
		}
	}

	//PrintMsg( NULL, "%s" S_COLOR_WHITE " captured the %s flag!\n", cl->pers.netname, TeamName(OtherTeam(team)));
	PrintCTFMessage(other->s.number, team, CTFMESSAGE_PLAYER_CAPTURED_FLAG);

	cl->ps.powerups[enemy_flag] = 0;

	teamgame.last_flag_capture = level.time;
	teamgame.last_capture_team = team;

	// Increase the team's score
	AddTeamScore(ent->s.pos.trBase, other->client->sess.sessionTeam, 1);
//	Team_ForceGesture(other->client->sess.sessionTeam);
	//rww - don't really want to do this now. Mainly because performing a gesture disables your upper torso animations until it's done and you can't fire

	other->client->pers.teamState.captures++;
	other->client->rewardTime = level.time + REWARD_SPRITE_TIME;
	other->client->ps.persistant[PERS_CAPTURES]++;

	// other gets another 10 frag bonus
	AddScore(other, ent->r.currentOrigin, CTF_CAPTURE_BONUS);

	Team_CaptureFlagSound( ent, team );

	// Ok, let's do the player loop, hand out the bonuses
	for (i = 0; i < sv_maxclients.integer; i++) {
		player = &g_entities[i];
		if (!player->inuse || player == other)
			continue;

		if (player->client->sess.sessionTeam !=
			cl->sess.sessionTeam) {
			player->client->pers.teamState.lasthurtcarrier = -5;
		} else if (player->client->sess.sessionTeam ==
			cl->sess.sessionTeam) {
			AddScore(player, ent->r.currentOrigin, CTF_TEAM_BONUS);
			// award extra points for capture assists
			if (player->client->pers.teamState.lastreturnedflag + 
				CTF_RETURN_FLAG_ASSIST_TIMEOUT > level.time) {
				AddScore (player, ent->r.currentOrigin, CTF_RETURN_FLAG_ASSIST_BONUS);
				other->client->pers.teamState.assists++;

				player->client->ps.persistant[PERS_ASSIST_COUNT]++;
				player->client->rewardTime = level.time + REWARD_SPRITE_TIME;

			}
			//Raz: Was 'else if' meaning people were missing out on some assist scores
			if (player->client->pers.teamState.lastfraggedcarrier + 
				CTF_FRAG_CARRIER_ASSIST_TIMEOUT > level.time) {
				AddScore(player, ent->r.currentOrigin, CTF_FRAG_CARRIER_ASSIST_BONUS);
				other->client->pers.teamState.assists++;
				player->client->ps.persistant[PERS_ASSIST_COUNT]++;
				player->client->rewardTime = level.time + REWARD_SPRITE_TIME;
			}
		}
	}
	Team_ResetFlags();

	CalculateRanks();

	return 0; // Do not respawn this automatically
}
Ejemplo n.º 6
0
qboolean G_RadiusDamage( vec3_t origin, gentity_t *attacker, float damage,
                         float radius, gentity_t *ignore, int mod )
{
	float     points, dist;
	gentity_t *ent;
	int       entityList[ MAX_GENTITIES ];
	int       numListedEntities;
	vec3_t    mins, maxs;
	vec3_t    v;
	vec3_t    dir;
	int       i, e;
	qboolean  hitClient = qfalse;

	if ( radius < 1 )
	{
		radius = 1;
	}

	for ( i = 0; i < 3; i++ )
	{
		mins[ i ] = origin[ i ] - radius;
		maxs[ i ] = origin[ i ] + radius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0; e < numListedEntities; e++ )
	{
		ent = &g_entities[ entityList[ e ] ];

		if ( ent == ignore )
		{
			continue;
		}

		if ( !ent->takedamage )
		{
			continue;
		}

		// find the distance from the edge of the bounding box
		for ( i = 0; i < 3; i++ )
		{
			if ( origin[ i ] < ent->r.absmin[ i ] )
			{
				v[ i ] = ent->r.absmin[ i ] - origin[ i ];
			}
			else if ( origin[ i ] > ent->r.absmax[ i ] )
			{
				v[ i ] = origin[ i ] - ent->r.absmax[ i ];
			}
			else
			{
				v[ i ] = 0;
			}
		}

		dist = VectorLength( v );

		if ( dist >= radius )
		{
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

		if ( G_CanDamage( ent, origin ) )
		{
			VectorSubtract( ent->r.currentOrigin, origin, dir );
			// push the center of mass higher than the origin so players
			// get knocked into the air more
			dir[ 2 ] += 24;
			VectorNormalize( dir );
			hitClient = qtrue;
			G_Damage( ent, NULL, attacker, dir, origin,
			          ( int ) points, DAMAGE_RADIUS | DAMAGE_NO_LOCDAMAGE, mod );
		}
	}

	return hitClient;
}
Ejemplo n.º 7
0
/*
===============
RailSphereShockWave
===============
*/
static void RailSphereShockWave(vec3_t origin, gentity_t * attacker, float damage, float push, float radius)
{
	float           dist;
	gentity_t      *ent;
	int             entityList[MAX_GENTITIES];
	int             numListedEntities;
	vec3_t          mins, maxs;
	vec3_t          v;
	vec3_t          dir;
	int             i, e;

	if(radius < 1)
		radius = 1;

	for(i = 0; i < 3; i++)
	{
		mins[i] = origin[i] - radius;
		maxs[i] = origin[i] + radius;
	}

	numListedEntities = trap_EntitiesInBox(mins, maxs, entityList, MAX_GENTITIES);

	for(e = 0; e < numListedEntities; e++)
	{
		ent = &g_entities[entityList[e]];

		// dont hit things we have already hit
		if(ent->kamikazeShockTime > level.time)
		{
			continue;
		}

		// find the distance from the edge of the bounding box
		for(i = 0; i < 3; i++)
		{
			if(origin[i] < ent->r.absmin[i])
			{
				v[i] = ent->r.absmin[i] - origin[i];
			}
			else if(origin[i] > ent->r.absmax[i])
			{
				v[i] = origin[i] - ent->r.absmax[i];
			}
			else
			{
				v[i] = 0;
			}
		}

		dist = VectorLength(v);
		if(dist >= radius)
		{
			continue;
		}

//      if( CanDamage (ent, origin) ) {
		VectorSubtract(ent->r.currentOrigin, origin, dir);
		dir[2] += 24;
		G_Damage(ent, NULL, attacker, dir, origin, damage, DAMAGE_RADIUS | DAMAGE_NO_TEAM_PROTECTION, MOD_KAMIKAZE);
		//
		dir[2] = 0;
		VectorNormalize(dir);
		if(ent->client)
		{
			ent->client->ps.velocity[0] = dir[0] * push;
			ent->client->ps.velocity[1] = dir[1] * push;
			ent->client->ps.velocity[2] = 100;
		}
		ent->kamikazeShockTime = level.time + 3000;
//      }
	}
}
Ejemplo n.º 8
0
static void
KamikazeShockWave(Vec3 origin, Gentity *attacker, float damage, float push,
		  float radius)
{
	float dist;
	Gentity       *ent;
	int entityList[MAX_GENTITIES];
	int numListedEntities;
	Vec3 mins, maxs;
	Vec3 v;
	Vec3 dir;
	int i, e;

	if(radius < 1)
		radius = 1;

	for(i = 0; i < 3; i++){
		mins[i] = origin[i] - radius;
		maxs[i] = origin[i] + radius;
	}

	numListedEntities = trap_EntitiesInBox(mins, maxs, entityList,
		MAX_GENTITIES);

	for(e = 0; e < numListedEntities; e++){
		ent = &g_entities[entityList[ e ]];

		/* dont hit things we have already hit */
		if(ent->kamikazeShockTime > level.time)
			continue;

		/* find the distance from the edge of the bounding box */
		for(i = 0; i < 3; i++){
			if(origin[i] < ent->r.absmin[i])
				v[i] = ent->r.absmin[i] - origin[i];
			else if(origin[i] > ent->r.absmax[i])
				v[i] = origin[i] - ent->r.absmax[i];
			else
				v[i] = 0;
		}

		dist = lenv3(v);
		if(dist >= radius)
			continue;

/*		if( CanDamage (ent, origin) ) { */
		subv3 (ent->r.currentOrigin, origin, dir);
		dir[2] += 24;
		G_Damage(ent, NULL, attacker, dir, origin, damage,
			DAMAGE_RADIUS|DAMAGE_NO_TEAM_PROTECTION,
			MOD_KAMIKAZE);
		dir[2] = 0;
		normv3(dir);
		if(ent->client){
			ent->client->ps.velocity[0] = dir[0] * push;
			ent->client->ps.velocity[1] = dir[1] * push;
			ent->client->ps.velocity[2] = 100;
		}
		ent->kamikazeShockTime = level.time + 3000;
/*		} */
	}
}
Ejemplo n.º 9
0
/*
============
G_MoverTouchTriggers

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters.
============
*/
void G_MoverTouchPushTriggers( gentity_t *ent, vec3_t oldOrg ) 
{
	int			i, num;
	float		step, stepSize, dist;
	int			touch[MAX_GENTITIES];
	gentity_t	*hit;
	trace_t		trace;
	vec3_t		mins, maxs, dir, size, checkSpot;
	const vec3_t	range = { 40, 40, 52 };

	// non-moving movers don't hit triggers!
	if ( !VectorLengthSquared( ent->s.pos.trDelta ) ) 
	{
		return;
	}

	VectorSubtract( ent->r.mins, ent->r.maxs, size );
	stepSize = VectorLength( size );
	if ( stepSize < 1 )
	{
		stepSize = 1;
	}

	VectorSubtract( ent->r.currentOrigin, oldOrg, dir );
	dist = VectorNormalize( dir );
	for ( step = 0; step <= dist; step += stepSize )
	{
		VectorMA( ent->r.currentOrigin, step, dir, checkSpot );
		VectorSubtract( checkSpot, range, mins );
		VectorAdd( checkSpot, range, maxs );

		num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

		// can't use ent->r.absmin, because that has a one unit pad
		VectorAdd( checkSpot, ent->r.mins, mins );
		VectorAdd( checkSpot, ent->r.maxs, maxs );

		for ( i=0 ; i<num ; i++ ) 
		{
			hit = &g_entities[touch[i]];

			if ( hit->s.eType != ET_PUSH_TRIGGER )
			{
				continue;
			}

			if ( hit->touch == NULL ) 
			{
				continue;
			}

			if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) 
			{
				continue;
			}


			if ( !trap_EntityContact( mins, maxs, hit ) ) 
			{
				continue;
			}

			memset( &trace, 0, sizeof(trace) );

			if ( hit->touch != NULL ) 
			{
				hit->touch(hit, ent, &trace);
			}
		}
	}
}
Ejemplo n.º 10
0
/*
==================
ClientTimerActions

Actions that happen once a second
==================
*/
void ClientTimerActions( gentity_t *ent, int msec )
{
  gclient_t *client;
  usercmd_t *ucmd;
  int       aForward, aRight;

  ucmd = &ent->client->pers.cmd;

  aForward  = abs( ucmd->forwardmove );
  aRight    = abs( ucmd->rightmove );

  client = ent->client;
  client->time100 += msec;
  client->time1000 += msec;
  client->time10000 += msec;

  while ( client->time100 >= 100 )
  {
    client->time100 -= 100;

    //if not trying to run then not trying to sprint
    if( aForward <= 64 )
      client->ps.stats[ STAT_STATE ] &= ~SS_SPEEDBOOST;

    if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) && BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) )
      client->ps.stats[ STAT_STATE ] &= ~SS_SPEEDBOOST;

    if( ( client->ps.stats[ STAT_STATE ] & SS_SPEEDBOOST ) &&  ucmd->upmove >= 0 )
    {
      //subtract stamina
      if( BG_InventoryContainsUpgrade( UP_LIGHTARMOUR, client->ps.stats ) )
        client->ps.stats[ STAT_STAMINA ] -= STAMINA_LARMOUR_TAKE;
      else
        client->ps.stats[ STAT_STAMINA ] -= STAMINA_SPRINT_TAKE;

      if( client->ps.stats[ STAT_STAMINA ] < -MAX_STAMINA )
        client->ps.stats[ STAT_STAMINA ] = -MAX_STAMINA;
    }

    if( ( aForward <= 64 && aForward > 5 ) || ( aRight <= 64 && aRight > 5 ) )
    {
      //restore stamina
      client->ps.stats[ STAT_STAMINA ] += STAMINA_WALK_RESTORE;

      if( client->ps.stats[ STAT_STAMINA ] > MAX_STAMINA )
        client->ps.stats[ STAT_STAMINA ] = MAX_STAMINA;
    }
    else if( aForward <= 5 && aRight <= 5 )
    {
      //restore stamina faster
      client->ps.stats[ STAT_STAMINA ] += STAMINA_STOP_RESTORE;

      if( client->ps.stats[ STAT_STAMINA ] > MAX_STAMINA )
        client->ps.stats[ STAT_STAMINA ] = MAX_STAMINA;
    }

    //client is charging up for a pounce
    if( client->ps.weapon == WP_ALEVEL3 || client->ps.weapon == WP_ALEVEL3_UPG )
    {
      int pounceSpeed = 0;

      if( client->ps.weapon == WP_ALEVEL3 )
        pounceSpeed = LEVEL3_POUNCE_SPEED;
      else if( client->ps.weapon == WP_ALEVEL3_UPG )
        pounceSpeed = LEVEL3_POUNCE_UPG_SPEED;

      if( client->ps.stats[ STAT_MISC ] < pounceSpeed && ucmd->buttons & BUTTON_ATTACK2 )
        client->ps.stats[ STAT_MISC ] += ( 100.0f / (float)LEVEL3_POUNCE_CHARGE_TIME ) * pounceSpeed;

      if( !( ucmd->buttons & BUTTON_ATTACK2 ) )
      {
        if( client->ps.stats[ STAT_MISC ] > 0 )
        {
          client->allowedToPounce = qtrue;
          client->pouncePayload = client->ps.stats[ STAT_MISC ];
        }

        client->ps.stats[ STAT_MISC ] = 0;
      }

      if( client->ps.stats[ STAT_MISC ] > pounceSpeed )
        client->ps.stats[ STAT_MISC ] = pounceSpeed;
    }

    //client is charging up for a... charge
    if( client->ps.weapon == WP_ALEVEL4 )
    {
      if( client->ps.stats[ STAT_MISC ] < LEVEL4_CHARGE_TIME && ucmd->buttons & BUTTON_ATTACK2 &&
          !client->charging )
      {
        client->charging = qfalse; //should already be off, just making sure
        client->ps.stats[ STAT_STATE ] &= ~SS_CHARGING;

        if( ucmd->forwardmove > 0 )
        {
          //trigger charge sound...is quite annoying
          //if( client->ps.stats[ STAT_MISC ] <= 0 )
          //  G_AddEvent( ent, EV_LEV4_CHARGE_PREPARE, 0 );

          client->ps.stats[ STAT_MISC ] += (int)( 100 * (float)LEVEL4_CHARGE_CHARGE_RATIO );

          if( client->ps.stats[ STAT_MISC ] > LEVEL4_CHARGE_TIME )
            client->ps.stats[ STAT_MISC ] = LEVEL4_CHARGE_TIME;
        }
        else
          client->ps.stats[ STAT_MISC ] = 0;
      }

      if( !( ucmd->buttons & BUTTON_ATTACK2 ) || client->charging ||
          client->ps.stats[ STAT_MISC ] == LEVEL4_CHARGE_TIME )
      {
        if( client->ps.stats[ STAT_MISC ] > LEVEL4_MIN_CHARGE_TIME )
        {
          client->ps.stats[ STAT_MISC ] -= 100;

          if( client->charging == qfalse )
            G_AddEvent( ent, EV_LEV4_CHARGE_START, 0 );

          client->charging = qtrue;
          client->ps.stats[ STAT_STATE ] |= SS_CHARGING;

          //if the charger has stopped moving take a chunk of charge away
          if( VectorLength( client->ps.velocity ) < 64.0f || aRight )
            client->ps.stats[ STAT_MISC ] = client->ps.stats[ STAT_MISC ] / 2;

          //can't charge backwards
          if( ucmd->forwardmove < 0 )
            client->ps.stats[ STAT_MISC ] = 0;
        }
        else
          client->ps.stats[ STAT_MISC ] = 0;


        if( client->ps.stats[ STAT_MISC ] <= 0 )
        {
          client->ps.stats[ STAT_MISC ] = 0;
          client->charging = qfalse;
          client->ps.stats[ STAT_STATE ] &= ~SS_CHARGING;
        }
      }
    }

    //client is charging up an lcannon
    if( client->ps.weapon == WP_LUCIFER_CANNON )
    {
      int ammo;

      BG_UnpackAmmoArray( WP_LUCIFER_CANNON, client->ps.ammo, client->ps.powerups, &ammo, NULL );

      if( client->ps.stats[ STAT_MISC ] < LCANNON_TOTAL_CHARGE && ucmd->buttons & BUTTON_ATTACK )
        client->ps.stats[ STAT_MISC ] += ( 100.0f / LCANNON_CHARGE_TIME ) * LCANNON_TOTAL_CHARGE;

      if( client->ps.stats[ STAT_MISC ] > LCANNON_TOTAL_CHARGE )
        client->ps.stats[ STAT_MISC ] = LCANNON_TOTAL_CHARGE;

      if( client->ps.stats[ STAT_MISC ] > ( ammo * LCANNON_TOTAL_CHARGE ) / 10 )
        client->ps.stats[ STAT_MISC ] = ammo * LCANNON_TOTAL_CHARGE / 10;
    }

    switch( client->ps.weapon )
    {
      case WP_ABUILD:
      case WP_ABUILD2:
      case WP_HBUILD:
      case WP_HBUILD2:
        //set validity bit on buildable
        if( ( client->ps.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) > BA_NONE )
        {
          int     dist = BG_FindBuildDistForClass( ent->client->ps.stats[ STAT_PCLASS ] );
          vec3_t  dummy;

          if( G_itemFits( ent, (buildable_t)(client->ps.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT),
                          dist, dummy ) == IBE_NONE )
            client->ps.stats[ STAT_BUILDABLE ] |= SB_VALID_TOGGLEBIT;
          else
            client->ps.stats[ STAT_BUILDABLE ] &= ~SB_VALID_TOGGLEBIT;
        }

        //update build timer
        if( client->ps.stats[ STAT_MISC ] > 0 )
          client->ps.stats[ STAT_MISC ] -= 100;

        if( client->ps.stats[ STAT_MISC ] < 0 )
          client->ps.stats[ STAT_MISC ] = 0;
        break;

      default:
        break;
    }

    if( client->ps.stats[ STAT_STATE ] & SS_MEDKIT_ACTIVE )
    {
      int remainingStartupTime = MEDKIT_STARTUP_TIME - ( level.time - client->lastMedKitTime );

      if( remainingStartupTime < 0 )
      {
        if( ent->health < ent->client->ps.stats[ STAT_MAX_HEALTH ] &&
            ent->client->medKitHealthToRestore &&
            ent->client->ps.pm_type != PM_DEAD )
        {
          ent->client->medKitHealthToRestore--;
          ent->health++;
        }
        else
          ent->client->ps.stats[ STAT_STATE ] &= ~SS_MEDKIT_ACTIVE;
      }
      else
      {
        if( ent->health < ent->client->ps.stats[ STAT_MAX_HEALTH ] &&
            ent->client->medKitHealthToRestore &&
            ent->client->ps.pm_type != PM_DEAD )
        {
          //partial increase
          if( level.time > client->medKitIncrementTime )
          {
            ent->client->medKitHealthToRestore--;
            ent->health++;

            client->medKitIncrementTime = level.time +
              ( remainingStartupTime / MEDKIT_STARTUP_SPEED );
          }
        }
        else
          ent->client->ps.stats[ STAT_STATE ] &= ~SS_MEDKIT_ACTIVE;
      }
    }
  }

  while( client->time1000 >= 1000 )
  {
    client->time1000 -= 1000;

    //client is poison clouded
    if( client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED )
      G_Damage( ent, client->lastPoisonCloudedClient, client->lastPoisonCloudedClient, NULL, NULL,
                LEVEL1_PCLOUD_DMG, 0, MOD_LEVEL1_PCLOUD );

    //client is poisoned
    if( client->ps.stats[ STAT_STATE ] & SS_POISONED )
    {
      int i;
      int seconds = ( ( level.time - client->lastPoisonTime ) / 1000 ) + 1;
      int damage = ALIEN_POISON_DMG, damage2 = 0;

      for( i = 0; i < seconds; i++ )
      {
        if( i == seconds - 1 )
          damage2 = damage;

        damage *= ALIEN_POISON_DIVIDER;
      }

      damage = damage2 - damage;

      G_Damage( ent, client->lastPoisonClient, client->lastPoisonClient, NULL, NULL,
                damage, 0, MOD_POISON );
    }

    //replenish alien health
    if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
    {
      int       entityList[ MAX_GENTITIES ];
      vec3_t    range = { LEVEL4_REGEN_RANGE, LEVEL4_REGEN_RANGE, LEVEL4_REGEN_RANGE };
      vec3_t    mins, maxs;
      int       i, num;
      gentity_t *boostEntity;
      float     modifier = 1.0f;

      VectorAdd( client->ps.origin, range, maxs );
      VectorSubtract( client->ps.origin, range, mins );

      num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
      for( i = 0; i < num; i++ )
      {
        boostEntity = &g_entities[ entityList[ i ] ];

        if( boostEntity->client && boostEntity->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS &&
            boostEntity->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_LEVEL4 )
        {
          modifier = LEVEL4_REGEN_MOD;
          break;
        }
        else if( boostEntity->s.eType == ET_BUILDABLE &&
            boostEntity->s.modelindex == BA_A_BOOSTER &&
            boostEntity->spawned )
        {
          modifier = BOOSTER_REGEN_MOD;
          break;
        }
      }

      if( ent->health > 0 && ent->health < client->ps.stats[ STAT_MAX_HEALTH ] &&
          ( ent->lastDamageTime + ALIEN_REGEN_DAMAGE_TIME ) < level.time )
        ent->health += BG_FindRegenRateForClass( client->ps.stats[ STAT_PCLASS ] ) * modifier;

      if( ent->health > client->ps.stats[ STAT_MAX_HEALTH ] )
        ent->health = client->ps.stats[ STAT_MAX_HEALTH ];
    }
  }

  while( client->time10000 >= 10000 )
  {
    client->time10000 -= 10000;

    if( client->ps.weapon == WP_ALEVEL3_UPG )
    {
      int ammo, maxAmmo;

      BG_FindAmmoForWeapon( WP_ALEVEL3_UPG, &maxAmmo, NULL );
      BG_UnpackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, &ammo, NULL );

      if( ammo < maxAmmo )
      {
        ammo++;
        BG_PackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, ammo, 0 );
      }
    }
  }
}
Ejemplo n.º 11
0
/*
==============
ClientThink

This will be called once for each client frame, which will
usually be a couple times for each server frame on fast clients.

If "g_synchronousClients 1" is set, this will be called exactly
once for each server frame, which makes for smooth demo recording.
==============
*/
void ClientThink_real( gentity_t *ent )
{
  gclient_t *client;
  pmove_t   pm;
  int       oldEventSequence;
  int       msec;
  usercmd_t *ucmd;

  client = ent->client;

  // don't think if the client is not yet connected (and thus not yet spawned in)
  if( client->pers.connected != CON_CONNECTED )
    return;

  // mark the time, so the connection sprite can be removed
  ucmd = &ent->client->pers.cmd;

  // sanity check the command time to prevent speedup cheating
  if( ucmd->serverTime > level.time + 200 )
  {
    ucmd->serverTime = level.time + 200;
//    G_Printf("serverTime <<<<<\n" );
  }

  if( ucmd->serverTime < level.time - 1000 )
  {
    ucmd->serverTime = level.time - 1000;
//    G_Printf("serverTime >>>>>\n" );
  }

  msec = ucmd->serverTime - client->ps.commandTime;
  // following others may result in bad times, but we still want
  // to check for follow toggles
  if( msec < 1 && client->sess.spectatorState != SPECTATOR_FOLLOW )
    return;

  if( msec > 200 )
    msec = 200;

  if( pmove_msec.integer < 8 )
    trap_Cvar_Set( "pmove_msec", "8" );
  else if( pmove_msec.integer > 33 )
    trap_Cvar_Set( "pmove_msec", "33" );

  if( pmove_fixed.integer || client->pers.pmoveFixed )
  {
    ucmd->serverTime = ( ( ucmd->serverTime + pmove_msec.integer - 1 ) / pmove_msec.integer ) * pmove_msec.integer;
    //if (ucmd->serverTime - client->ps.commandTime <= 0)
    //  return;
  }

  //
  // check for exiting intermission
  //
  if( level.intermissiontime )
  {
    ClientIntermissionThink( client );
    return;
  }

  // spectators don't do much
  if( client->sess.sessionTeam == TEAM_SPECTATOR )
  {
    if( client->sess.spectatorState == SPECTATOR_SCOREBOARD )
      return;

    SpectatorThink( ent, ucmd );
    return;
  }

  G_UpdatePTRConnection( client );

  // check for inactivity timer, but never drop the local client of a non-dedicated server
  if( !ClientInactivityTimer( client ) )
    return;

  if( client->noclip )
    client->ps.pm_type = PM_NOCLIP;
  else if( client->ps.stats[ STAT_HEALTH ] <= 0 )
    client->ps.pm_type = PM_DEAD;
  else if( client->ps.stats[ STAT_STATE ] & SS_INFESTING ||
           client->ps.stats[ STAT_STATE ] & SS_HOVELING )
    client->ps.pm_type = PM_FREEZE;
  else if( client->ps.stats[ STAT_STATE ] & SS_BLOBLOCKED ||
           client->ps.stats[ STAT_STATE ] & SS_GRABBED )
    client->ps.pm_type = PM_GRABBED;
  else if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) && BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) )
    client->ps.pm_type = PM_JETPACK;
  else
    client->ps.pm_type = PM_NORMAL;

  if( client->ps.stats[ STAT_STATE ] & SS_GRABBED &&
      client->grabExpiryTime < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_GRABBED;

  if( client->ps.stats[ STAT_STATE ] & SS_BLOBLOCKED &&
      client->lastLockTime + 5000 < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_BLOBLOCKED;

  if( client->ps.stats[ STAT_STATE ] & SS_SLOWLOCKED &&
      client->lastLockTime + ABUILDER_BLOB_TIME < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_SLOWLOCKED;

  client->ps.stats[ STAT_BOOSTTIME ] = level.time - client->lastBoostedTime;

  if( client->ps.stats[ STAT_STATE ] & SS_BOOSTED &&
      client->lastBoostedTime + BOOST_TIME < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_BOOSTED;

  if( client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED &&
      client->lastPoisonCloudedTime + LEVEL1_PCLOUD_TIME < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_POISONCLOUDED;

  if( client->ps.stats[ STAT_STATE ] & SS_POISONED &&
      client->lastPoisonTime + ALIEN_POISON_TIME < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_POISONED;

  client->ps.gravity = g_gravity.value;

  if( BG_InventoryContainsUpgrade( UP_MEDKIT, client->ps.stats ) &&
      BG_UpgradeIsActive( UP_MEDKIT, client->ps.stats ) )
  {
    //if currently using a medkit or have no need for a medkit now
    if( client->ps.stats[ STAT_STATE ] & SS_MEDKIT_ACTIVE ||
        ( client->ps.stats[ STAT_HEALTH ] == client->ps.stats[ STAT_MAX_HEALTH ] &&
          !( client->ps.stats[ STAT_STATE ] & SS_POISONED ) ) )
    {
      BG_DeactivateUpgrade( UP_MEDKIT, client->ps.stats );
    }
    else if( client->ps.stats[ STAT_HEALTH ] > 0 )
    {
      //remove anti toxin
      BG_DeactivateUpgrade( UP_MEDKIT, client->ps.stats );
      BG_RemoveUpgradeFromInventory( UP_MEDKIT, client->ps.stats );

      client->ps.stats[ STAT_STATE ] &= ~SS_POISONED;
      client->poisonImmunityTime = level.time + MEDKIT_POISON_IMMUNITY_TIME;

      client->ps.stats[ STAT_STATE ] |= SS_MEDKIT_ACTIVE;
      client->lastMedKitTime = level.time;
      client->medKitHealthToRestore =
        client->ps.stats[ STAT_MAX_HEALTH ] - client->ps.stats[ STAT_HEALTH ];
      client->medKitIncrementTime = level.time +
        ( MEDKIT_STARTUP_TIME / MEDKIT_STARTUP_SPEED );

      G_AddEvent( ent, EV_MEDKIT_USED, 0 );
    }
  }

  if( BG_InventoryContainsUpgrade( UP_GRENADE, client->ps.stats ) &&
      BG_UpgradeIsActive( UP_GRENADE, client->ps.stats ) )
  {
    int lastWeapon = ent->s.weapon;

    //remove grenade
    BG_DeactivateUpgrade( UP_GRENADE, client->ps.stats );
    BG_RemoveUpgradeFromInventory( UP_GRENADE, client->ps.stats );

    //M-M-M-M-MONSTER HACK
    ent->s.weapon = WP_GRENADE;
    FireWeapon( ent );
    ent->s.weapon = lastWeapon;
  }

  // set speed
  client->ps.speed = g_speed.value * BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] );

  if( client->lastCreepSlowTime + CREEP_TIMEOUT < level.time )
    client->ps.stats[ STAT_STATE ] &= ~SS_CREEPSLOWED;

  //randomly disable the jet pack if damaged
  if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) &&
      BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) )
  {
    if( ent->lastDamageTime + JETPACK_DISABLE_TIME > level.time )
    {
      if( random( ) > JETPACK_DISABLE_CHANCE )
        client->ps.pm_type = PM_NORMAL;
    }

    //switch jetpack off if no reactor
    if( !level.reactorPresent )
      BG_DeactivateUpgrade( UP_JETPACK, client->ps.stats );
  }

  // set up for pmove
  oldEventSequence = client->ps.eventSequence;

  memset( &pm, 0, sizeof( pm ) );

  if( !( ucmd->buttons & BUTTON_TALK ) ) //&& client->ps.weaponTime <= 0 ) //TA: erk more server load
  {
    switch( client->ps.weapon )
    {
      case WP_ALEVEL0:
        if( client->ps.weaponTime <= 0 )
          pm.autoWeaponHit[ client->ps.weapon ] = CheckVenomAttack( ent );
        break;

      case WP_ALEVEL1:
      case WP_ALEVEL1_UPG:
        CheckGrabAttack( ent );
        break;

      case WP_ALEVEL3:
      case WP_ALEVEL3_UPG:
        if( client->ps.weaponTime <= 0 )
          pm.autoWeaponHit[ client->ps.weapon ] = CheckPounceAttack( ent );
        break;

      default:
        break;
    }
  }

  if( ent->flags & FL_FORCE_GESTURE )
  {
    ent->flags &= ~FL_FORCE_GESTURE;
    ent->client->pers.cmd.buttons |= BUTTON_GESTURE;
  }

  pm.ps = &client->ps;
  pm.cmd = *ucmd;

  if( pm.ps->pm_type == PM_DEAD )
    pm.tracemask = MASK_PLAYERSOLID; // & ~CONTENTS_BODY;

  if( pm.ps->stats[ STAT_STATE ] & SS_INFESTING ||
      pm.ps->stats[ STAT_STATE ] & SS_HOVELING )
    pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
  else
    pm.tracemask = MASK_PLAYERSOLID;

  pm.trace = trap_Trace;
  pm.pointcontents = trap_PointContents;
  pm.debugLevel = g_debugMove.integer;
  pm.noFootsteps = (qboolean)0;

  pm.pmove_fixed = pmove_fixed.integer | client->pers.pmoveFixed;
  pm.pmove_msec = pmove_msec.integer;

  VectorCopy( client->ps.origin, client->oldOrigin );

  // moved from after Pmove -- potentially the cause of
  // future triggering bugs
  if( !ent->client->noclip )
    G_TouchTriggers( ent );

  Pmove( &pm );

  // save results of pmove
  if( ent->client->ps.eventSequence != oldEventSequence )
    ent->eventTime = level.time;

  if( g_smoothClients.integer )
    BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue );
  else
    BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue );

  SendPendingPredictableEvents( &ent->client->ps );

  if( !( ent->client->ps.eFlags & EF_FIRING ) )
    client->fireHeld = qfalse;    // for grapple
  if( !( ent->client->ps.eFlags & EF_FIRING2 ) )
    client->fire2Held = qfalse;

  // use the snapped origin for linking so it matches client predicted versions
  VectorCopy( ent->s.pos.trBase, ent->r.currentOrigin );

  VectorCopy( pm.mins, ent->r.mins );
  VectorCopy( pm.maxs, ent->r.maxs );

  ent->waterlevel = pm.waterlevel;
  ent->watertype = pm.watertype;

  // execute client events
  ClientEvents( ent, oldEventSequence );

  // link entity now, after any personal teleporters have been used
  trap_LinkEntity( ent );

  // NOTE: now copy the exact origin over otherwise clients can be snapped into solid
  VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
  VectorCopy( ent->client->ps.origin, ent->s.origin );

  // touch other objects
  ClientImpacts( ent, &pm );

  // save results of triggers and client events
  if( ent->client->ps.eventSequence != oldEventSequence )
    ent->eventTime = level.time;

  // swap and latch button actions
  client->oldbuttons = client->buttons;
  client->buttons = ucmd->buttons;
  client->latched_buttons |= client->buttons & ~client->oldbuttons;

  if( ( client->buttons & BUTTON_GETFLAG ) && !( client->oldbuttons & BUTTON_GETFLAG ) &&
       client->ps.stats[ STAT_HEALTH ] > 0 )
  {
    trace_t   trace;
    vec3_t    view, point;
    gentity_t *traceEnt;

    if( client->ps.stats[ STAT_STATE ] & SS_HOVELING )
    {
      gentity_t *hovel = client->hovel;

      //only let the player out if there is room
      if( !AHovel_Blocked( hovel, ent, qtrue ) )
      {
        //prevent lerping
        client->ps.eFlags ^= EF_TELEPORT_BIT;
        client->ps.eFlags &= ~EF_NODRAW;

        //client leaves hovel
        client->ps.stats[ STAT_STATE ] &= ~SS_HOVELING;

        //hovel is empty
        G_setBuildableAnim( hovel, BANIM_ATTACK2, qfalse );
        hovel->active = qfalse;
      }
      else
      {
        //exit is blocked
        G_TriggerMenu( ent->client->ps.clientNum, MN_A_HOVEL_BLOCKED );
      }
    }
    else
    {
#define USE_OBJECT_RANGE 64

      int       entityList[ MAX_GENTITIES ];
      vec3_t    range = { USE_OBJECT_RANGE, USE_OBJECT_RANGE, USE_OBJECT_RANGE };
      vec3_t    mins, maxs;
      int       i, num;

      //TA: look for object infront of player
      AngleVectors( client->ps.viewangles, view, NULL, NULL );
      VectorMA( client->ps.origin, USE_OBJECT_RANGE, view, point );
      trap_Trace( &trace, client->ps.origin, NULL, NULL, point, ent->s.number, MASK_SHOT );

      traceEnt = &g_entities[ trace.entityNum ];

      if( traceEnt && traceEnt->biteam == client->ps.stats[ STAT_PTEAM ] && traceEnt->use )
        traceEnt->use( traceEnt, ent, ent ); //other and activator are the same in this context
      else
      {
        //no entity in front of player - do a small area search

        VectorAdd( client->ps.origin, range, maxs );
        VectorSubtract( client->ps.origin, range, mins );

        num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
        for( i = 0; i < num; i++ )
        {
          traceEnt = &g_entities[ entityList[ i ] ];

          if( traceEnt && traceEnt->biteam == client->ps.stats[ STAT_PTEAM ] && traceEnt->use )
          {
            traceEnt->use( traceEnt, ent, ent ); //other and activator are the same in this context
            break;
          }
        }

        if( i == num && client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
        {
          if( BG_UpgradeClassAvailable( &client->ps ) )
          {
            //no nearby objects and alien - show class menu
            G_TriggerMenu( ent->client->ps.clientNum, MN_A_INFEST );
          }
          else
          {
            //flash frags
            G_AddEvent( ent, EV_ALIEN_EVOLVE_FAILED, 0 );
          }
        }
      }
    }
  }

  // check for respawning
  if( client->ps.stats[ STAT_HEALTH ] <= 0 )
  {
    // wait for the attack button to be pressed
    if( level.time > client->respawnTime )
    {
      // forcerespawn is to prevent users from waiting out powerups
      if( g_forcerespawn.integer > 0 &&
        ( level.time - client->respawnTime ) > 0 )
      {
        respawn( ent );
        return;
      }

      // pressing attack or use is the normal respawn method
      if( ucmd->buttons & ( BUTTON_ATTACK | BUTTON_USE_HOLDABLE ) )
      {
        respawn( ent );
      }
    }
    return;
  }

  if( level.framenum > client->retriggerArmouryMenu && client->retriggerArmouryMenu )
  {
    G_TriggerMenu( client->ps.clientNum, MN_H_ARMOURY );

    client->retriggerArmouryMenu = 0;
  }

  // Give clients some credit periodically
  if( ent->client->lastKillTime + FREEKILL_PERIOD < level.time )
  {
    if( g_suddenDeathTime.integer &&
        ( level.time - level.startTime >= g_suddenDeathTime.integer * 60000 ) )
    {
      //gotta love logic like this eh?
    }
    else if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
      G_AddCreditToClient( ent->client, FREEKILL_ALIEN, qtrue );
    else if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
      G_AddCreditToClient( ent->client, FREEKILL_HUMAN, qtrue );

    ent->client->lastKillTime = level.time;
  }

  // perform once-a-second actions
  ClientTimerActions( ent, msec );
  
  if( ent->suicideTime > 0 && ent->suicideTime < level.time )
  {
    ent->flags &= ~FL_GODMODE;
    ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0;
    player_die( ent, ent, ent, 100000, MOD_SUICIDE );

    ent->suicideTime = 0;
  }
}
Ejemplo n.º 12
0
/*
============
G_TouchTriggers

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters.
============
*/
void  G_TouchTriggers( gentity_t *ent )
{
  int       i, num;
  int       touch[MAX_GENTITIES];
  gentity_t *hit;
  trace_t   trace;
  vec3_t    mins, maxs;
  vec3_t    pmins, pmaxs;
  static    vec3_t range = { 10, 10, 10 };

  if( !ent->client )
    return;

  // dead clients don't activate triggers!
  if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 )
    return;

  BG_FindBBoxForClass( ent->client->ps.stats[ STAT_PCLASS ],
                       pmins, pmaxs, NULL, NULL, NULL );

  VectorAdd( ent->client->ps.origin, pmins, mins );
  VectorAdd( ent->client->ps.origin, pmaxs, maxs );

  VectorSubtract( mins, range, mins );
  VectorAdd( maxs, range, maxs );

  num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

  // can't use ent->absmin, because that has a one unit pad
  VectorAdd( ent->client->ps.origin, ent->r.mins, mins );
  VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs );

  for( i = 0; i < num; i++ )
  {
    hit = &g_entities[ touch[ i ] ];

    if( !hit->touch && !ent->touch )
      continue;

    if( !( hit->r.contents & CONTENTS_TRIGGER ) )
      continue;

    // ignore most entities if a spectator
    if( ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) ||
        ( ent->client->ps.stats[ STAT_STATE ] & SS_INFESTING ) ||
        ( ent->client->ps.stats[ STAT_STATE ] & SS_HOVELING ) )
    {
      if( hit->s.eType != ET_TELEPORT_TRIGGER &&
          // this is ugly but adding a new ET_? type will
          // most likely cause network incompatibilities
          hit->touch != Touch_DoorTrigger )
      {
        //check for manually triggered doors
        manualTriggerSpectator( hit, ent );
        continue;
      }
    }

    if( !trap_EntityContact( mins, maxs, hit ) )
      continue;

    memset( &trace, 0, sizeof( trace ) );

    if( hit->touch )
      hit->touch( hit, ent, &trace );

    if( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) )
      ent->touch( ent, hit, &trace );
  }

  // if we didn't touch a jump pad this pmove frame
  if( ent->client->ps.jumppad_frame != ent->client->ps.pmove_framecount )
  {
    ent->client->ps.jumppad_frame = 0;
    ent->client->ps.jumppad_ent = 0;
  }
}
Ejemplo n.º 13
0
/*
============
etpro_RadiusDamage
mutation of G_RadiusDamage which lets us selectively damage only clients or only non clients
============
*/
qboolean etpro_RadiusDamage( vec3_t origin, gentity_t *inflictor, gentity_t *attacker, float damage, float radius, gentity_t *ignore, int mod, RadiusScope scope ) {
	float		points, dist;
	gentity_t	*ent;
	int			entityList[MAX_GENTITIES];
	int			numListedEntities;
	vec3_t		mins, maxs;
	vec3_t		v;
	vec3_t		dir;
	int			i, e;
	qboolean	hitClient = qfalse;
	float		boxradius;
	vec3_t		dest; 
	trace_t		tr;
	vec3_t		midpoint;
	int			flags = DAMAGE_RADIUS;

	if( mod == MOD_SATCHEL || mod == MOD_LANDMINE ) {
		flags |= DAMAGE_HALF_KNOCKBACK;
	}

	if( radius < 1 ) {
		radius = 1;
	}

	boxradius = 1.41421356 * radius; // radius * sqrt(2) for bounding box enlargement -- 
	// bounding box was checking against radius / sqrt(2) if collision is along box plane
	for( i = 0 ; i < 3 ; i++ ) {
		mins[i] = origin[i] - boxradius;
		maxs[i] = origin[i] + boxradius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for( e = 0 ; e < numListedEntities ; e++ ) {
		ent = &g_entities[entityList[ e ]];

		if( ent == ignore ) {
			continue;
		}
		if( !ent->takedamage && ( !ent->dmgparent || !ent->dmgparent->takedamage )) {
			continue;
		}

        switch (scope) {
            default:
            case RADIUS_SCOPE_ANY:
                break;

            case RADIUS_SCOPE_CLIENTS:
		        if (!ent->client && ent->s.eType != ET_CORPSE )
                    continue;
                break;

            case RADIUS_SCOPE_NOCLIENTS:
		        if (ent->client)
                    continue;
                break;
		}

		if(	ent->waterlevel == 3 && mod == MOD_POISON_GAS) {
			continue;
		}

		G_AdjustedDamageVec( ent, origin, v );

		dist = VectorLength( v );
		if ( dist >= radius ) {
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

		if( CanDamage( ent, origin ) ) {
			if( ent->dmgparent ) {
				ent = ent->dmgparent;
			}

			if( AccuracyHit( ent, attacker ) ) {
				hitClient = qtrue;
			}
			VectorSubtract (ent->r.currentOrigin, origin, dir);
			// push the center of mass higher than the origin so players
			// get knocked into the air more
			dir[2] += 24;

			G_Damage( ent, inflictor, attacker, dir, origin, (int)points, flags, mod );
		} else {
			VectorAdd( ent->r.absmin, ent->r.absmax, midpoint );
			VectorScale( midpoint, 0.5, midpoint );
			VectorCopy( midpoint, dest );
		
			trap_Trace( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID );
			if( tr.fraction < 1.0 ) {
				VectorSubtract( dest, origin, dest );
				dist = VectorLength( dest );
				if( dist < radius * 0.2f ) { // closer than 1/4 dist
					if( ent->dmgparent ) {
						ent = ent->dmgparent;
					}

					if( AccuracyHit( ent, attacker ) ) {
						hitClient = qtrue;
					}
					VectorSubtract (ent->r.currentOrigin, origin, dir);
					dir[2] += 24;
					G_Damage( ent, inflictor, attacker, dir, origin, (int)(points*0.1f), flags, mod );
				}
			}
		}
	}

	return hitClient;
}
Ejemplo n.º 14
0
/*
==============
BotBlastDamage

Determine how much damage a blast from "weapon" detonating
at "center" deals, not dealing damage to entity "ignore".
The information is stored in the "blast" input argument.
==============
*/
void BotBlastDamage(bot_state_t *bs, int weapon, vec3_t center, damage_multi_t *blast, gentity_t *ignore)
{
	int i, num_contacted;
	int contacted[MAX_GENTITIES];
	float radius, dist, damage;
	vec3_t offset, mins, maxs;
	gentity_t *ent;
	damage_catagory_t *group;

	// Reset the damage information
	memset(blast, 0, sizeof(damage_multi_t));

	// Only check for weapons with blast radius
	radius = weapon_stats[weapon].radius;
	if (radius <= 0)
		return;

	// Compute the bounding box containing all entities that could possibly be
	// damaged from the blast radius.
	VectorSet     (offset, radius, radius, radius);
	VectorAdd     (center, offset, maxs);
	VectorSubtract(center, offset, mins);

	// Get a list of all entities possibly within this bounding box
	num_contacted = trap_EntitiesInBox(mins, maxs, contacted, MAX_GENTITIES);

	// Estimate damage dealt to each nearby entity
	//
	// NOTE: This duplicates much of the code in G_RadiusDamage() in g_combat.c.
	for (i = 0; i < num_contacted; i++)
	{
		// Do not tracked the ignored entity
		ent = &g_entities[contacted[i]];
		if (ent == ignore)
			continue;

		// Check if the entity is on the enemy team
		//
		// NOTE: This includes damagable structures on the enemy team,
		// like the Obelisk in Overload.
		if (BotEnemyTeam(bs, ent))
			group = &blast->enemy;

		// Also check for players on the same team that the bot can damage.
		//
		// NOTE: This function purposely ignores self-damage.  It also
		// ignores damagable team structures, like the Obelisk in Overload
		// (which players can't damage even when friend fire is turned on).
		else if (g_friendlyFire.integer &&
				 ent->client &&
				 BotSameTeam(bs, ent) &&
				 bs->ent != ent)
			group = &blast->team;

		// Never count damage to neutrally aligned entities, even if they are
		// damagable (like shot-activated buttons)
		else
			continue;

		// Determine how close the blast shot was to the target's bounding box
		// (in real world coordinates)
		EntityWorldBounds(ent, mins, maxs);
		dist = point_bound_distance(center, mins, maxs);

		// Compute how much damage the blast would deal to entities at this distance
		damage = WeaponBlast(weapon, dist);

		// Update the specific catagory data...
		group->hits++;
		group->total += damage;
		if (group->max < damage)
			group->max = damage;

		// ... And the aggregate data
		blast->all.hits++;
		blast->all.total += damage;
		if (blast->all.max < damage)
			blast->all.max = damage;
	}
}
Ejemplo n.º 15
0
/*
============
G_TouchTriggers

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters.
============
*/
void    G_TouchTriggers(gentity_t *ent) {
	int           i, num;
	int           touch[MAX_GENTITIES];
	gentity_t     *hit;
	trace_t       trace;
	vec3_t        mins, maxs;
	static vec3_t range = { 40, 40, 52 };

	if (!ent->client) {
		return;
	}

	// Arnout: reset the pointer that keeps track of trigger_objective_info tracking
	ent->client->touchingTOI = NULL;

	// dead clients don't activate triggers!
	if (ent->client->ps.stats[STAT_HEALTH] <= 0) {
		return;
	}

	VectorSubtract(ent->client->ps.origin, range, mins);
	VectorAdd(ent->client->ps.origin, range, maxs);

	num = trap_EntitiesInBox(mins, maxs, touch, MAX_GENTITIES);

	// can't use ent->absmin, because that has a one unit pad
	VectorAdd(ent->client->ps.origin, ent->r.mins, mins);
	VectorAdd(ent->client->ps.origin, ent->r.maxs, maxs);

	for (i = 0 ; i < num ; ++i) {
		hit = &g_entities[touch[i]];

		if (!hit->touch && !ent->touch) {
			continue;
		}
		if (!(hit->r.contents & CONTENTS_TRIGGER)) {
			continue;
		}

		// Arnout: invisible entities can't be touched
		// Gordon: radiant tabs arnout! ;)
		if (hit->entstate == STATE_INVISIBLE ||
		    hit->entstate == STATE_UNDERCONSTRUCTION) {
			continue;
		}

		// ignore most entities if a spectator
		if (ent->client->sess.sessionTeam == TEAM_SPECTATOR && hit->s.eType != ET_TELEPORT_TRIGGER) {
			continue;
		}

		// use seperate code for determining if an item is picked up
		// so you don't have to actually contact its bounding box
		if (hit->s.eType == ET_ITEM) {
			if (!BG_PlayerTouchesItem(&ent->client->ps, &hit->s, level.time)) {
				continue;
			}
		} else {
			// MrE: always use capsule for player
			if (!trap_EntityContactCapsule(mins, maxs, hit)) {
				continue;
			}
		}

		memset(&trace, 0, sizeof (trace));

		if (hit->touch) {
			hit->touch(hit, ent, &trace);
		}
	}
}
Ejemplo n.º 16
0
void explodedretch(gentity_t *ent)
{
    int       i;
    int         entityList[ MAX_GENTITIES ];
		vec3_t      range;
		vec3_t      mins, maxs;
		int         num;
		gentity_t   *enemy;
		float       creepSize = (float)650;
		int freezedcounter = 0;
    
    //gentity_t *gren;
    if(ent->client->ps.persistant[ PERS_CREDIT ] < 1) //Neeeddd fix <3
    {
        trap_SendServerCommand( ent-g_entities, "print \"^5Overmind: ^7You need 1 evos to explode.\n\"" );
    }
    else
    {
        ent->client->ps.persistant[ PERS_CREDIT ] -= 1;
        G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, 0 );
        G_RadiusDamage( ent->r.currentOrigin, ent, 200,
                     200, ent, MOD_GRENADE);
        G_Damage( ent, ent, ent, NULL, NULL, 10000, 0, MOD_UNKNOWN );
        
        
        //Slow down enemy around.
        VectorSet( range, creepSize, creepSize, creepSize );

        VectorAdd( ent->s.origin, range, maxs );
        VectorSubtract( ent->s.origin, range, mins );

        //find enemys around me
        num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
        for( i = 0; i < num; i++ )
        {
            enemy = &g_entities[ entityList[ i ] ];

            if( enemy->flags & FL_NOTARGET )
                continue;
            if( enemy->client && (enemy->client->ps.stats[ STAT_PTEAM ] != ent->client->ps.stats[ STAT_PTEAM ] ) && G_Visible( ent, enemy ) )
            {
                //enemy->client->ps.stats[ STAT_STATE ] |= SS_CREEPSLOWED;
                enemy->client->ps.stats[ STAT_STATE ] |= SS_ICEWAVED;
                enemy->client->lastCreepSlowTime = level.time + 5000;
                freezedcounter++;
                //G_SelectiveRadiusDamage( ent->s.pos.trBase, ent, (float)dmg, (float)500, ent, MOD_SLOWBLOB, ent->client->ps.stats[ STAT_PTEAM ] );
            }
        }
        if(ent->client){
        //29  	Freezing Field  	Icewave over 5 enemies in 1 icewave 
			if(ent->client->pers.badges[ 29 ] != 1  && freezedcounter >= 5)
			{
				ent->client->pers.badgeupdate[29] = 1;
				ent->client->pers.badges[29] = 1;
				G_WinBadge( ent, 29 );
			}
		}
    }
    /*
    
    if(ent->client->pers.teamSelection != PTE_HUMANS
    && ent->client->pers.teamSelection != PTE_ALIENS )
    {  
        trap_SendServerCommand( ent-g_entities, va(
        "print \"^1You must be on a team\n\"" ) );
                return qfalse;
    }

    if(ent->client->pers.classSelection == PCL_NONE)
    {  
        trap_SendServerCommand( ent-g_entities, va(
        "print \"^1You must be alive\n\"" ) );
                return qfalse;
    }
    if(ent->client->pers.energy >= 500)
    {  
        if(ent->client->pers.teamSelection == PTE_HUMANS)
        {
            dmg = 3;
        }
        if(ent->client->pers.teamSelection == PTE_ALIENS)
        {
            dmg = 1;
        }

        ent->client->pers.energy-= 500;
        G_AddEvent( ent, EV_ALIEN_BUILDABLE_EXPLOSION, 0 );

        VectorSet( range, creepSize, creepSize, creepSize );

        VectorAdd( ent->s.origin, range, maxs );
        VectorSubtract( ent->s.origin, range, mins );

        //find enemys around me
        num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
        for( i = 0; i < num; i++ )
        {
            enemy = &g_entities[ entityList[ i ] ];

            if( enemy->flags & FL_NOTARGET )
                continue;
            if( enemy->client && (enemy->client->ps.stats[ STAT_PTEAM ] != ent->client->ps.stats[ STAT_PTEAM ] ) && G_Visible( ent, enemy ) )
            {
                //enemy->client->ps.stats[ STAT_STATE ] |= SS_CREEPSLOWED;
                enemy->client->ps.stats[ STAT_STATE ] |= SS_ICEWAVED;
                enemy->client->lastCreepSlowTime = level.time + 5000;
                //G_SelectiveRadiusDamage( ent->s.pos.trBase, ent, (float)dmg, (float)500, ent, MOD_SLOWBLOB, ent->client->ps.stats[ STAT_PTEAM ] );
            }
        }
        return qtrue;
    }*/
}
Ejemplo n.º 17
0
qboolean G_SelectiveRadiusDamage( vec3_t origin, gentity_t *attacker, float damage,
                                  float radius, gentity_t *ignore, int mod, int ignoreTeam )
{
	float     points, dist;
	gentity_t *ent;
	int       entityList[ MAX_GENTITIES ];
	int       numListedEntities;
	vec3_t    mins, maxs;
	vec3_t    v;
	int       i, e;
	qboolean  hitClient = qfalse;

	if ( radius < 1 )
	{
		radius = 1;
	}

	for ( i = 0; i < 3; i++ )
	{
		mins[ i ] = origin[ i ] - radius;
		maxs[ i ] = origin[ i ] + radius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0; e < numListedEntities; e++ )
	{
		ent = &g_entities[ entityList[ e ] ];

		if ( ent == ignore )
		{
			continue;
		}

		if ( !ent->takedamage )
		{
			continue;
		}

		if ( ent->flags & FL_NOTARGET )
		{
			continue;
		}

		// find the distance from the edge of the bounding box
		for ( i = 0; i < 3; i++ )
		{
			if ( origin[ i ] < ent->r.absmin[ i ] )
			{
				v[ i ] = ent->r.absmin[ i ] - origin[ i ];
			}
			else if ( origin[ i ] > ent->r.absmax[ i ] )
			{
				v[ i ] = origin[ i ] - ent->r.absmax[ i ];
			}
			else
			{
				v[ i ] = 0;
			}
		}

		dist = VectorLength( v );

		if ( dist >= radius )
		{
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

		if ( G_CanDamage( ent, origin ) && ent->client &&
		     ent->client->pers.team != ignoreTeam )
		{
			hitClient = qtrue;

			// don't do knockback, since an attack that spares one team is most likely
			// not based on kinetic energy
			G_Damage( ent, NULL, attacker, NULL, origin, ( int ) points,
			          DAMAGE_RADIUS | DAMAGE_NO_LOCDAMAGE | DAMAGE_NO_KNOCKBACK, mod );
		}
	}

	return hitClient;
}
Ejemplo n.º 18
0
/*
============
G_TouchTriggers

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters.
============
*/
void G_TouchTriggers( gentity_t *ent ) 
{
	int				num;
	int				touch[MAX_GENTITIES];
	vec3_t			mins;
	vec3_t			maxs;
	static vec3_t	range = { 20, 20, 40 };

	if ( !ent->client ) 
	{
		return;
	}

	// dead clients don't activate triggers!
	if ( G_IsClientDead ( ent->client ) ) 
	{
		return;
	}

	VectorSubtract( ent->client->ps.origin, range, mins );
	VectorAdd( ent->client->ps.origin, range, maxs );

	num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

	// can't use ent->r.absmin, because that has a one unit pad
	VectorAdd( ent->client->ps.origin, ent->r.mins, mins );
	VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs );

	// Reset the players can use flag
	ent->client->ps.pm_flags &= ~(PMF_CAN_USE);
	ent->s.modelindex  = 0;

	for ( int i=0 ; i<num ; i++ ) 
	{
		gentity_t		*hit = &g_entities[touch[i]];

		// pmove would have to have detected siamese twins first
		if ( hit->client && hit != ent && !hit->client->siameseTwin && (ent->client->ps.pm_flags & PMF_SIAMESETWINS) )
		{
			// See if this client has a twin
			if ( !G_IsClientSiameseTwin ( ent, hit ) )
			{
				continue;
			}

			// About time these twins were separated!!
			ent->client->siameseTwin = hit;
			hit->client->siameseTwin = ent;
		}

		if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) 
		{
			continue;
		}

		if ( !hit->touch && !ent->touch ) 
		{
			continue;
		}

		// ignore most entities if a spectator
		if ( G_IsClientSpectating ( ent->client ) ) 
		{
			if ( hit->s.eType != ET_TELEPORT_TRIGGER &&
				// this is ugly but adding a new ET_? type will
				// most likely cause network incompatibilities
				hit->touch != Touch_DoorTrigger) 
			{
				continue;
			}
		}

		// use seperate code for determining if an item is picked up
		// so you don't have to actually contact its bounding box
		if ( hit->s.eType == ET_ITEM ) 
		{
			if ( !BG_PlayerTouchesItem( &ent->client->ps, &hit->s, level.time ) ) 
			{
				continue;
			}
		} 
		else 
		{
			if ( !trap_EntityContact( mins, maxs, hit ) ) 
			{
				continue;
			}
		}
		trace_t	trace;
		memset( &trace, 0, sizeof(trace) );

		if ( hit->touch ) 
		{
			hit->touch (hit, ent, &trace);
		}

		if ( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) ) 
		{
			ent->touch( ent, hit, &trace );
		}
	}

	// Dont bother looking for twins again unless pmove says so
	ent->client->ps.pm_flags &= (~PMF_SIAMESETWINS);
}
Ejemplo n.º 19
0
/*
===============
RailSphereRadiusDamage
===============
*/
static void RailSphereRadiusDamage(vec3_t origin, gentity_t * attacker, float damage, float radius)
{
	float           dist;
	gentity_t      *ent;
	int             entityList[MAX_GENTITIES];
	int             numListedEntities;
	vec3_t          mins, maxs;
	vec3_t          v;
	vec3_t          dir;
	int             i, e;

	if(radius < 1)
	{
		radius = 1;
	}

	for(i = 0; i < 3; i++)
	{
		mins[i] = origin[i] - radius;
		maxs[i] = origin[i] + radius;
	}

	numListedEntities = trap_EntitiesInBox(mins, maxs, entityList, MAX_GENTITIES);

	for(e = 0; e < numListedEntities; e++)
	{
		ent = &g_entities[entityList[e]];

		if(!ent->takedamage)
		{
			continue;
		}

		// dont hit things we have already hit
		if(ent->kamikazeTime > level.time)
		{
			continue;
		}

		// find the distance from the edge of the bounding box
		for(i = 0; i < 3; i++)
		{
			if(origin[i] < ent->r.absmin[i])
			{
				v[i] = ent->r.absmin[i] - origin[i];
			}
			else if(origin[i] > ent->r.absmax[i])
			{
				v[i] = origin[i] - ent->r.absmax[i];
			}
			else
			{
				v[i] = 0;
			}
		}

		dist = VectorLength(v);
		if(dist >= radius)
		{
			continue;
		}

//      if( CanDamage (ent, origin) ) {
		VectorSubtract(ent->r.currentOrigin, origin, dir);
		// push the center of mass higher than the origin so players
		// get knocked into the air more
		dir[2] += 24;
		G_Damage(ent, NULL, attacker, dir, origin, damage, DAMAGE_RADIUS | DAMAGE_NO_TEAM_PROTECTION, MOD_KAMIKAZE);
		ent->kamikazeTime = level.time + 3000;
//      }
	}
}
Ejemplo n.º 20
0
/*
================
G_ExplodeMissile

Explode a missile without an impact
================
*/
void G_ExplodeMissile( gentity_t *ent ) {
	vec3_t dir;
	vec3_t origin;
	qboolean small = qfalse;
	qboolean zombiespit = qfalse;
	int etype;

	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
	SnapVector( origin );
	G_SetOrigin( ent, origin );

	// we don't have a valid direction, so just point straight up
	dir[0] = dir[1] = 0;
	dir[2] = 1;

	etype = ent->s.eType;

	ent->s.eType = ET_GENERAL;

	if ( !Q_stricmp( ent->classname, "props_explosion" ) ) {
		G_AddEvent( ent, EV_MISSILE_MISS_SMALL, DirToByte( dir ) );
		small = qtrue;
	}
// JPW NERVE
	else if ( !Q_stricmp( ent->classname, "air strike" ) ) {
		G_AddEvent( ent, EV_MISSILE_MISS_LARGE, DirToByte( dir ) );
		small = qfalse;
	}
// jpw
	else if ( !Q_stricmp( ent->classname, "props_explosion_large" ) ) {
		G_AddEvent( ent, EV_MISSILE_MISS_LARGE, DirToByte( dir ) );
		small = qfalse;
	} else if ( !Q_stricmp( ent->classname, "zombiespit" ) )      {
		G_AddEvent( ent, EV_SPIT_MISS, DirToByte( dir ) );
		zombiespit = qtrue;
	} else if ( !Q_stricmp( ent->classname, "flamebarrel" ) )      {
		ent->freeAfterEvent = qtrue;
		trap_LinkEntity( ent );
		return;
	} else {
		G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( dir ) );
	}

	ent->freeAfterEvent = qtrue;

	// splash damage
	if ( ent->splashDamage ) {
		if ( G_RadiusDamage( ent->r.currentOrigin, ent->parent, ent->splashDamage, ent->splashRadius, ent, ent->splashMethodOfDeath ) ) {    //----(SA)
			if ( g_entities[ent->r.ownerNum].client ) {
				g_entities[ent->r.ownerNum].client->ps.persistant[PERS_ACCURACY_HITS]++;
			}
		}
	}

	trap_LinkEntity( ent );

	if ( etype == ET_MISSILE ) {
		// DHM - Nerve :: ... in single player anyway
		if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
			if ( ent->s.weapon == WP_VENOM_FULL ) { // no default impact smoke
				zombiespit = qtrue;
			} else if ( ent->s.weapon == WP_DYNAMITE || ent->s.weapon == WP_DYNAMITE2 ) {
//				// shot heard round the world...
				gentity_t *player;
				player = AICast_FindEntityForName( "player" );
				Concussive_fx( player->r.currentOrigin );
			}
		}
// JPW NERVE -- big nasty dynamite scoring section
		else {
			if ( g_gametype.integer >= GT_WOLF ) {
				if ( ent->s.weapon == WP_DYNAMITE ) { // do some scoring
// check if dynamite is in trigger_objective_info field
					vec3_t mins, maxs;
					//static vec3_t	range = { 18, 18, 18 }; // NOTE can use this to massage throw distance outside trigger field // TTimo unused
					int i,num,touch[MAX_GENTITIES];
					gentity_t   *hit;

					// NERVE - SMF - made this the actual bounding box of dynamite instead of range
					VectorAdd( ent->r.currentOrigin, ent->r.mins, mins );
					VectorAdd( ent->r.currentOrigin, ent->r.maxs, maxs );
					num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
					VectorAdd( ent->r.currentOrigin, ent->r.mins, mins );
					VectorAdd( ent->r.currentOrigin, ent->r.maxs, maxs );

					for ( i = 0 ; i < num ; i++ ) {
						hit = &g_entities[touch[i]];
						if ( !hit->target ) {
							continue;
						}

						if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) {
							continue;
						}
						if ( !strcmp( hit->classname,"trigger_objective_info" ) ) {
							if ( !( hit->spawnflags & ( AXIS_OBJECTIVE | ALLIED_OBJECTIVE ) ) ) {
								continue;
							}

							if ( ( ( hit->spawnflags & AXIS_OBJECTIVE ) && ( ent->s.teamNum == TEAM_BLUE ) ) ||
								 ( ( hit->spawnflags & ALLIED_OBJECTIVE ) && ( ent->s.teamNum == TEAM_RED ) ) ) {
								G_UseTargets( hit,ent );
								hit->think = G_FreeEntity;
								hit->nextthink = level.time + FRAMETIME;

								if ( ent->parent->client ) {
									if ( ent->s.teamNum == ent->parent->client->sess.sessionTeam ) { // make sure player hasn't changed teams -- per atvi req
										AddScore( ent->parent, hit->accuracy ); // set from map, see g_trigger
									}
								}
							}
						}
					}
				}
			}
			// give big weapons the shakey shakey
			if ( ent->s.weapon == WP_DYNAMITE || ent->s.weapon == WP_PANZERFAUST || ent->s.weapon == WP_GRENADE_LAUNCHER ||
				 ent->s.weapon == WP_GRENADE_PINEAPPLE || ent->s.weapon == WP_ROCKET_LAUNCHER || ent->s.weapon == WP_MORTAR ||
				 ent->s.weapon == WP_ARTY ) {
				Ground_Shaker( ent->r.currentOrigin, ent->splashDamage * 4 );
			}
			return;
		}
// jpw
	}


	if ( !zombiespit ) {
		gentity_t *Msmoke;

		Msmoke = G_Spawn();
		VectorCopy( ent->r.currentOrigin, Msmoke->s.origin );
		if ( small ) {
			Msmoke->s.density = 1;
		}
		Msmoke->think = M_think;
		Msmoke->nextthink = level.time + FRAMETIME;

		if ( ent->parent && !Q_stricmp( ent->parent->classname, "props_flamebarrel" ) ) {
			Msmoke->health = 10;
		} else {
			Msmoke->health = 5;
		}

		Concussive_fx( Msmoke->s.origin );
	}
}
Ejemplo n.º 21
0
void WolfReviveBbox( gentity_t *self ) {
	int touch[MAX_GENTITIES];
	int num,i, touchnum = 0;
	gentity_t   *hit = NULL;
	vec3_t mins, maxs;
	gentity_t   *capsulehit = NULL;

	VectorAdd( self->r.currentOrigin, playerMins, mins );
	VectorAdd( self->r.currentOrigin, playerMaxs, maxs );

	num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

	// Arnout, we really should be using capsules, do a quick, more refined test using mover collision
	if ( num ) {
		capsulehit = G_TestEntityPosition( self );
	}

	for ( i = 0 ; i < num ; i++ ) {
		hit = &g_entities[touch[i]];
		if ( hit->client ) {
			// ATVI Wolfenstein Misc #467
			// don't look at yourself when counting the hits
			if ( hit->client->ps.persistant[PERS_HWEAPON_USE] && hit != self ) {
				touchnum++;
				// Move corpse directly to the person who revived them
				if ( self->props_frame_state >= 0 ) {
					trap_UnlinkEntity( self );
					VectorCopy( g_entities[self->props_frame_state].client->ps.origin, self->client->ps.origin );
					VectorCopy( self->client->ps.origin, self->r.currentOrigin );
					trap_LinkEntity( self );

					// Reset value so we don't continue to warp them
					self->props_frame_state = -1;
				}
			} else if ( hit->health > 0 ) {
				if ( hit->s.number != self->s.number ) {
					WolfRevivePushEnt( hit, self );
					touchnum++;
				}
			}
		} else if ( hit->r.contents & ( CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_PLAYERCLIP ) )   {
			// Arnout: if hit is a mover, use capsulehit (this will only work if we touch one mover at a time - situations where you hit two are
			// really rare anyway though. The real fix is to move everything to capsule collision detection though
			if ( hit->s.eType == ET_MOVER ) {
				if ( capsulehit && capsulehit != hit ) {
					continue;   // we collided with a mover, but we're not stuck in this one
				} else {
					continue;   // we didn't collide with any movers
				}
			}

			WolfRevivePushEnt( hit, self );
			touchnum++;
		}
	}

	if ( g_dbgRevive.integer ) {
		G_Printf( "WolfReviveBbox: touchnum: %d\n", touchnum );
	}

	if ( touchnum == 0 ) {
		if ( g_dbgRevive.integer ) {
			G_Printf( "WolfReviveBbox:  Player is solid now!\n" );
		}
		self->r.contents = CONTENTS_BODY;
	}
}
Ejemplo n.º 22
0
void G_FlameDamage( gentity_t *self ) {
	gentity_t   *body;
	int entityList[MAX_GENTITIES];
	int i, e, numListedEntities;
	float radius, boxradius, dist;
	vec3_t mins, maxs, point, v;
	trace_t tr;

	radius = self->speed;
	boxradius = 1.41421356 * radius; // radius * sqrt(2) for bounding box enlargement

	for ( i = 0 ; i < 3 ; i++ ) {
		mins[i] = self->r.currentOrigin[i] - boxradius;
		maxs[i] = self->r.currentOrigin[i] + boxradius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0 ; e < numListedEntities ; e++ ) {
		body = &g_entities[entityList[ e ]];

		if ( !body->takedamage ) {
			continue;
		}

// JPW NERVE don't catch fire if invulnerable or same team in no FF
		if ( body->client ) {
			if ( body->client->ps.powerups[PW_INVULNERABLE] >= level.time ) {
				body->flameQuota = 0;
				body->s.onFireEnd = level.time - 1;
				continue;
			}
			if ( !( g_friendlyFire.integer ) && OnSameTeam( body,self->parent ) ) {
				continue;
			}
		}
// jpw

// JPW NERVE don't catch fire if under water or invulnerable
		if ( body->waterlevel >= 3 ) {
			body->flameQuota = 0;
			body->s.onFireEnd = level.time - 1;
			continue;
		}
// jpw

		if ( !body->r.bmodel ) {
			VectorCopy( body->r.currentOrigin, point );
			if ( body->client ) {
				point[2] += body->client->ps.viewheight;
			}
			VectorSubtract( point, self->r.currentOrigin, v );
		} else {
			for ( i = 0 ; i < 3 ; i++ ) {
				if ( self->s.origin[i] < body->r.absmin[i] ) {
					v[i] = body->r.absmin[i] - self->r.currentOrigin[i];
				} else if ( self->r.currentOrigin[i] > body->r.absmax[i] ) {
					v[i] = self->r.currentOrigin[i] - body->r.absmax[i];
				} else {
					v[i] = 0;
				}
			}
		}

		dist = VectorLength( v );

		// The person who shot the flame only burns when within 1/2 the radius
		if ( body->s.number == self->r.ownerNum && dist >= ( radius * 0.5 ) ) {
			continue;
		}
		if ( dist >= radius ) {
			continue;
		}

		// Non-clients that take damage get damaged here
		if ( !body->client ) {
			if ( body->health > 0 ) {
				G_Damage( body, self->parent, self->parent, vec3_origin, self->r.currentOrigin, 2, 0, MOD_FLAMETHROWER );
			}
			continue;
		}

		// JPW NERVE -- do a trace to see if there's a wall btwn. body & flame centroid -- prevents damage through walls
		trap_Trace( &tr, self->r.currentOrigin, NULL, NULL, point, body->s.number, MASK_SHOT );
		if ( tr.fraction < 1.0 ) {
			continue;
		}
		// jpw

		// now check the damageQuota to see if we should play a pain animation
		// first reduce the current damageQuota with time
		if ( body->flameQuotaTime && body->flameQuota > 0 ) {
			body->flameQuota -= (int)( ( (float)( level.time - body->flameQuotaTime ) / 1000 ) * 2.5f );
			if ( body->flameQuota < 0 ) {
				body->flameQuota = 0;
			}
		}

		G_BurnMeGood( self, body );
	}
}
Ejemplo n.º 23
0
void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
			   vec3_t dir, vec3_t point, int damage, int dflags, int mod ) {
	gclient_t	*client;
	int			take;
	int			save;
	int			asave;
	int			knockback;
	int			max;
#ifdef MISSIONPACK
	vec3_t		bouncedir, impactpoint;
#endif

	if (!targ->takedamage) {
		return;
	}

	// the intermission has allready been qualified for, so don't
	// allow any extra scoring
	if ( level.intermissionQueued ) {
		return;
	}
#ifdef MISSIONPACK
	if ( targ->client && mod != MOD_JUICED) {
		if ( targ->client->invulnerabilityTime > level.time) {
			if ( dir && point ) {
				G_InvulnerabilityEffect( targ, dir, point, impactpoint, bouncedir );
			}
			return;
		}
	}
#endif
	if ( !inflictor ) {
		inflictor = &g_entities[ENTITYNUM_WORLD];
	}
	if ( !attacker ) {
		attacker = &g_entities[ENTITYNUM_WORLD];
	}

	// shootable doors / buttons don't actually have any health
	if ( targ->s.eType == ET_MOVER ) {
		if ( targ->use && targ->moverState == MOVER_POS1 ) {
			targ->use( targ, inflictor, attacker );
		}
		return;
	}
#ifdef MISSIONPACK
	if( g_gametype.integer == GT_OBELISK && CheckObeliskAttack( targ, attacker ) ) {
		return;
	}
#endif
	// reduce damage by the attacker's handicap value
	// unless they are rocket jumping
	if ( attacker->client && attacker != targ ) {
		max = attacker->client->ps.stats[STAT_MAX_HEALTH];
#ifdef MISSIONPACK
		if( bg_itemlist[attacker->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
			max /= 2;
		}
#endif
		damage = damage * max / 100;
	}

	client = targ->client;

	if ( client ) {
		if ( client->noclip ) {
			return;
		}
	}

	if ( !dir ) {
		dflags |= DAMAGE_NO_KNOCKBACK;
	} else {
		VectorNormalize(dir);
	}

	knockback = damage;
	if ( knockback > 200 ) {
		knockback = 200;
	}
	if ( targ->flags & FL_NO_KNOCKBACK ) {
		knockback = 0;
	}
	if ( dflags & DAMAGE_NO_KNOCKBACK ) {
		knockback = 0;
	}

	// figure momentum add, even if the damage won't be taken
	if ( knockback && targ->client ) {
		vec3_t	kvel;
		float	mass;

		mass = 200;

		VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
		VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);

		// set the timer so that the other client can't cancel
		// out the movement immediately
		if ( !targ->client->ps.pm_time ) {
			int		t;

			t = knockback * 2;
			if ( t < 50 ) {
				t = 50;
			}
			if ( t > 200 ) {
				t = 200;
			}
			targ->client->ps.pm_time = t;
			targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
		}
	}

	// check for completely getting out of the damage
	if ( !(dflags & DAMAGE_NO_PROTECTION) ) {

		// if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target
		// if the attacker was on the same team
#ifdef MISSIONPACK
		if ( mod != MOD_JUICED && targ != attacker && !(dflags & DAMAGE_NO_TEAM_PROTECTION) && OnSameTeam (targ, attacker)  ) {
#else	
		if ( targ != attacker && OnSameTeam (targ, attacker)  ) {
#endif
			if ( !g_friendlyFire.integer ) {
				return;
			}
		}
#ifdef MISSIONPACK
		if (mod == MOD_PROXIMITY_MINE) {
			if (inflictor && inflictor->parent && OnSameTeam(targ, inflictor->parent)) {
				return;
			}
			if (targ == attacker) {
				return;
			}
		}
#endif

		// check for godmode
		if ( targ->flags & FL_GODMODE ) {
			return;
		}
	}

	// battlesuit protects from all radius damage (but takes knockback)
	// and protects 50% against all damage
	if ( client && client->ps.powerups[PW_BATTLESUIT] ) {
		G_AddEvent( targ, EV_POWERUP_BATTLESUIT, 0 );
		if ( ( dflags & DAMAGE_RADIUS ) || ( mod == MOD_FALLING ) ) {
			return;
		}
		damage *= 0.5;
	}

	// add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
	if ( attacker->client && targ != attacker && targ->health > 0
			&& targ->s.eType != ET_MISSILE
			&& targ->s.eType != ET_GENERAL) {
		if ( OnSameTeam( targ, attacker ) ) {
			attacker->client->ps.persistant[PERS_HITS]--;
		} else {
			attacker->client->ps.persistant[PERS_HITS]++;
		}
		attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]);
	}

	// always give half damage if hurting self
	// calculated after knockback, so rocket jumping works
	if ( targ == attacker) {
		damage *= 0.5;
	}

	if ( damage < 1 ) {
		damage = 1;
	}
	take = damage;
	save = 0;

	// save some from armor
	asave = CheckArmor (targ, take, dflags);
	take -= asave;

	if ( g_debugDamage.integer ) {
		G_Printf( "%i: client:%i health:%i damage:%i armor:%i\n", level.time, targ->s.number,
			targ->health, take, asave );
	}

	// add to the damage inflicted on a player this frame
	// the total will be turned into screen blends and view angle kicks
	// at the end of the frame
	if ( client ) {
		if ( attacker ) {
			client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
		} else {
			client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
		}
		client->damage_armor += asave;
		client->damage_blood += take;
		client->damage_knockback += knockback;
		if ( dir ) {
			VectorCopy ( dir, client->damage_from );
			client->damage_fromWorld = qfalse;
		} else {
			VectorCopy ( targ->r.currentOrigin, client->damage_from );
			client->damage_fromWorld = qtrue;
		}
	}

	// See if it's the player hurting the emeny flag carrier
#ifdef MISSIONPACK
	if( g_gametype.integer == GT_CTF || g_gametype.integer == GT_1FCTF ) {
#else	
	if( g_gametype.integer == GT_CTF) {
#endif
		Team_CheckHurtCarrier(targ, attacker);
	}

	if (targ->client) {
		// set the last client who damaged the target
		targ->client->lasthurt_client = attacker->s.number;
		targ->client->lasthurt_mod = mod;
	}

	// do the damage
	if (take) {
		targ->health = targ->health - take;
		if ( targ->client ) {
			targ->client->ps.stats[STAT_HEALTH] = targ->health;
		}
			
		if ( targ->health <= 0 ) {
			if ( client )
				targ->flags |= FL_NO_KNOCKBACK;

			if (targ->health < -999)
				targ->health = -999;

			targ->enemy = attacker;
			targ->die (targ, inflictor, attacker, take, mod);
			return;
		} else if ( targ->pain ) {
			targ->pain (targ, attacker, take);
		}
	}

}


/*
============
CanDamage

Returns qtrue if the inflictor can directly damage the target.  Used for
explosions and melee attacks.
============
*/
qboolean CanDamage (gentity_t *targ, vec3_t origin) {
	vec3_t	dest;
	trace_t	tr;
	vec3_t	midpoint;

	// use the midpoint of the bounds instead of the origin, because
	// bmodels may have their origin is 0,0,0
	VectorAdd (targ->r.absmin, targ->r.absmax, midpoint);
	VectorScale (midpoint, 0.5, midpoint);

	VectorCopy (midpoint, dest);
	trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if (tr.fraction == 1.0 || tr.entityNum == targ->s.number)
		return qtrue;

	// this should probably check in the plane of projection, 
	// rather than in world coordinate, and also include Z
	VectorCopy (midpoint, dest);
	dest[0] += 15.0;
	dest[1] += 15.0;
	trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if (tr.fraction == 1.0)
		return qtrue;

	VectorCopy (midpoint, dest);
	dest[0] += 15.0;
	dest[1] -= 15.0;
	trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if (tr.fraction == 1.0)
		return qtrue;

	VectorCopy (midpoint, dest);
	dest[0] -= 15.0;
	dest[1] += 15.0;
	trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if (tr.fraction == 1.0)
		return qtrue;

	VectorCopy (midpoint, dest);
	dest[0] -= 15.0;
	dest[1] -= 15.0;
	trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if (tr.fraction == 1.0)
		return qtrue;


	return qfalse;
}


/*
============
G_RadiusDamage
============
*/
qboolean G_RadiusDamage ( vec3_t origin, gentity_t *attacker, float damage, float radius,
					 gentity_t *ignore, int mod) {
	float		points, dist;
	gentity_t	*ent;
	int			entityList[MAX_GENTITIES];
	int			numListedEntities;
	vec3_t		mins, maxs;
	vec3_t		v;
	vec3_t		dir;
	int			i, e;
	qboolean	hitClient = qfalse;

	if ( radius < 1 ) {
		radius = 1;
	}

	for ( i = 0 ; i < 3 ; i++ ) {
		mins[i] = origin[i] - radius;
		maxs[i] = origin[i] + radius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0 ; e < numListedEntities ; e++ ) {
		ent = &g_entities[entityList[ e ]];

		if (ent == ignore)
			continue;
		if (!ent->takedamage)
			continue;

		// find the distance from the edge of the bounding box
		for ( i = 0 ; i < 3 ; i++ ) {
			if ( origin[i] < ent->r.absmin[i] ) {
				v[i] = ent->r.absmin[i] - origin[i];
			} else if ( origin[i] > ent->r.absmax[i] ) {
				v[i] = origin[i] - ent->r.absmax[i];
			} else {
				v[i] = 0;
			}
		}

		dist = VectorLength( v );
		if ( dist >= radius ) {
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

		if( CanDamage (ent, origin) ) {
			if( LogAccuracyHit( ent, attacker ) ) {
				hitClient = qtrue;
			}
			VectorSubtract (ent->r.currentOrigin, origin, dir);
			// push the center of mass higher than the origin so players
			// get knocked into the air more
			dir[2] += 24;
			G_Damage (ent, NULL, attacker, dir, origin, (int)points, DAMAGE_RADIUS, mod);
		}
	}

	return hitClient;
}
Ejemplo n.º 24
0
void WP_GrenadeBlow(gentity_t*self)
{
	if(Q_stricmp(self->classname,"emp_grenade")==0
		||Q_stricmp(self->classname,"cryoban_grenade")==0
		||Q_stricmp(self->classname,"flash_grenade")==0)
	{
		vec3_t	dir={0,0,1};
		int entitys[1024];
		vec3_t mins,maxs,v;
		int num=0,i=0,dist=0,mpDamage=7;
		int e=0;
		gentity_t*ent;
		for ( i = 0 ; i < 3 ; i++ ) 
		{
			mins[i] = self->r.currentOrigin[i] - TD_SPLASH_RAD / 2;
			maxs[i] = self->r.currentOrigin[i] + TD_SPLASH_RAD / 2;
		}
		num = trap_EntitiesInBox(mins,maxs,entitys,MAX_GENTITIES);
		for ( i = 0 ; i < num ; i++ ) 
		{
			ent = &g_entities[entitys[ i ]];
			if (ent == self)
				continue;
			if (!ent->takedamage)
				continue;
			if(!ent->inuse || !ent->client)
				continue;

			// find the distance from the edge of the bounding box
			for ( e = 0 ; e < 3 ; e++ ) {
				if ( self->r.currentOrigin[e] < ent->r.absmin[e] ) {
					v[e] = ent->r.absmin[e] - self->r.currentOrigin[e];
				} else if ( self->r.currentOrigin[e] > ent->r.absmax[e] ) {
					v[e] = self->r.currentOrigin[e] - ent->r.absmax[e];
				} else {
					v[e] = 0;
				}
			}

			dist = VectorLength( v );
			if ( dist >= TD_SPLASH_RAD ) {
				continue;
			}

			if(Q_stricmp(self->classname,"cryoban_grenade") == 0)
				G_AddEvent(ent, EV_CRYOBAN, DirToByte(dir));

			if(Q_stricmp(self->classname,"emp_grenade")==0)
			{
				int shield = Q_irand(25,50);
				int ammo = Q_irand(15,30);
				G_DodgeDrain(ent, self, 15);//15 for nau
				ent->client->ps.saberAttackChainCount += mpDamage;
				if(ent->client->ps.stats[STAT_ARMOR]-shield >= 0)
					ent->client->ps.stats[STAT_ARMOR]-=shield;
				else
					ent->client->ps.stats[STAT_ARMOR]=0;

				if(ent->client->ps.ammo[weaponData[ent->client->ps.weapon].ammoIndex]-ammo >= 0)
					ent->client->ps.ammo[weaponData[ent->client->ps.weapon].ammoIndex]-=ammo;
				else
					ent->client->ps.ammo[weaponData[ent->client->ps.weapon].ammoIndex]=0;

				if(Q_stricmp(ent->classname,"item_seeker")==0||Q_stricmp(ent->classname,"item_sentry_gun")==0)
				{
					G_Damage( ent, ent, ent, NULL, NULL, 999, 0, MOD_UNKNOWN );
				}
				ent->client->ps.electrifyTime = level.time + Q_irand( 300, 800 );
			}
			else if(Q_stricmp(self->classname,"cryoban_grenade")==0)
			{
				ent->client->frozenTime = level.time+FROZEN_TIME;
				ent->client->ps.userInt3 |= (1 << FLAG_FROZEN);
				ent->client->ps.userInt1 |= LOCK_UP;
				ent->client->ps.userInt1 |= LOCK_DOWN;
				ent->client->ps.userInt1 |= LOCK_RIGHT;
				ent->client->ps.userInt1 |= LOCK_LEFT;
				ent->client->viewLockTime = level.time+FROZEN_TIME;
				ent->client->ps.legsTimer = ent->client->ps.torsoTimer=level.time+FROZEN_TIME;
				G_SetAnim(ent, NULL, SETANIM_BOTH, WeaponReadyAnim[ent->client->ps.weapon], SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD, 100);
			}
			else if(Q_stricmp(self->classname,"flash_grenade")==0)
				G_AddEvent( ent, EV_FLASHGRENADE, DirToByte( dir ) );
		}
		self->s.eType = ET_GENERAL;
		if(Q_stricmp(self->classname,"emp_grenade") == 0)
			G_AddEvent( self, EV_EMPGRENADE, DirToByte( dir ) );
		else if(Q_stricmp(self->classname,"cryoban_grenade") == 0)
			G_AddEvent( self, EV_CRYOBAN_EXPLODE, DirToByte( dir ) );
		self->freeAfterEvent = qtrue;
	}
	else if(Q_stricmp(self->classname,"smoke_grenade")==0)
	{
		vec3_t	dir={0,0,1};

			G_AddEvent( self, EV_SMOKEGRENADE, DirToByte( dir ) );
		self->freeAfterEvent = qtrue;
	}
	else
	{
		self->think = G_FreeEntity;
		self->nextthink = level.time;
	}
}
Ejemplo n.º 25
0
int Team_TouchEnemyFlag( gentity_t *ent, gentity_t *other, int team ) {
	gclient_t *cl = other->client;
	vec3_t		mins, maxs;
	int			num, j, ourFlag;
	int			touch[MAX_GENTITIES];
	gentity_t*	enemy;
	float		enemyDist, dist;

	VectorSubtract( ent->s.pos.trBase, minFlagRange, mins );
	VectorAdd( ent->s.pos.trBase, maxFlagRange, maxs );

	num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

	dist = Distance(ent->s.pos.trBase, other->client->ps.origin);

	if (other->client->sess.sessionTeam == TEAM_RED){
		ourFlag   = PW_REDFLAG;
	} else {
		ourFlag   = PW_BLUEFLAG;
	}		

	for(j = 0; j < num; ++j){
		enemy = (g_entities + touch[j]);

		if (!enemy || !enemy->inuse || !enemy->client){
			continue;
		}

		//ignore specs
		if (enemy->client->sess.sessionTeam == TEAM_SPECTATOR)
			continue;

		//check if its alive
		if (enemy->health < 1)
			continue;		// dead people can't pick up items

		//lets check if he has our flag
		if (!enemy->client->ps.powerups[ourFlag])
			continue;

		//check if enemy is closer to our flag than us
		enemyDist = Distance(ent->s.pos.trBase,enemy->client->ps.origin);
		if (enemyDist < dist){
			// possible recursion is hidden in this, but 
			// infinite recursion wont happen, because we cant 
			// have a < b and b < a at the same time
			return Team_TouchOurFlag( ent, enemy, team );
		}
	}

	//PrintMsg (NULL, "%s" S_COLOR_WHITE " got the %s flag!\n",
	//	other->client->pers.netname, TeamName(team));
	PrintCTFMessage(other->s.number, team, CTFMESSAGE_PLAYER_GOT_FLAG);

	if (team == TEAM_RED)
		cl->ps.powerups[PW_REDFLAG] = INT_MAX; // flags never expire
	else
		cl->ps.powerups[PW_BLUEFLAG] = INT_MAX; // flags never expire

	Team_SetFlagStatus( team, FLAG_TAKEN );

	AddScore(other, ent->r.currentOrigin, CTF_FLAG_BONUS);
	cl->pers.teamState.flagsince = level.time;
	Team_TakeFlagSound( ent, team );

	return -1; // Do not respawn this automatically, but do delete it if it was FL_DROPPED
}
Ejemplo n.º 26
0
bool G_SelectiveRadiusDamage( vec3_t origin, gentity_t *attacker, float damage,
                                  float radius, gentity_t *ignore, int mod, int ignoreTeam )
{
	float     points, dist;
	gentity_t *ent;
	int       entityList[ MAX_GENTITIES ];
	int       numListedEntities;
	vec3_t    mins, maxs;
	vec3_t    v;
	int       i, e;
	bool  hitClient = false;

	if ( radius < 1 )
	{
		radius = 1;
	}

	for ( i = 0; i < 3; i++ )
	{
		mins[ i ] = origin[ i ] - radius;
		maxs[ i ] = origin[ i ] + radius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0; e < numListedEntities; e++ )
	{
		ent = &g_entities[ entityList[ e ] ];

		if ( ent == ignore )
		{
			continue;
		}

		if ( !ent->takedamage )
		{
			continue;
		}

		if ( ent->flags & FL_NOTARGET )
		{
			continue;
		}

		// find the distance from the edge of the bounding box
		for ( i = 0; i < 3; i++ )
		{
			if ( origin[ i ] < ent->r.absmin[ i ] )
			{
				v[ i ] = ent->r.absmin[ i ] - origin[ i ];
			}
			else if ( origin[ i ] > ent->r.absmax[ i ] )
			{
				v[ i ] = origin[ i ] - ent->r.absmax[ i ];
			}
			else
			{
				v[ i ] = 0;
			}
		}

		dist = VectorLength( v );

		if ( dist >= radius )
		{
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

		if ( G_CanDamage( ent, origin ) && ent->client &&
		     ent->client->pers.team != ignoreTeam )
		{
			hitClient = true;

			G_Damage( ent, nullptr, attacker, nullptr, origin, ( int ) points,
			          DAMAGE_RADIUS | DAMAGE_NO_LOCDAMAGE, mod );
		}
	}

	return hitClient;
}
Ejemplo n.º 27
0
/*
============
G_TouchTriggers

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters (and door triggers for spectators)
============
*/
void G_TouchTriggers(gentity_t * ent)
{
	int i, num;
	int touch[MAX_GENTITIES];
	gentity_t *hit;
	trace_t trace;
	vec3_t mins, maxs;
	static vec3_t range = { 40, 40, 52 };

	if (!ent->client) {
		return;
	}
	// dead clients don't activate triggers!
	if (ent->client->ps.stats[STAT_HEALTH] <= 0) {
		return;
	}

	VectorSubtract(ent->client->ps.origin, range, mins);
	VectorAdd(ent->client->ps.origin, range, maxs);

	num = trap_EntitiesInBox(mins, maxs, touch, MAX_GENTITIES);

	// can't use ent->absmin, because that has a one unit pad
	VectorAdd(ent->client->ps.origin, ent->r.mins, mins);
	VectorAdd(ent->client->ps.origin, ent->r.maxs, maxs);

	for (i = 0; i < num; i++) {
		//Blaze: Print out some debug info
		if (&g_entities[touch[i]] == NULL) G_Printf("Ln 0429\n");

		hit = &g_entities[touch[i]];

		if (!hit->touch && !ent->touch) {
			continue;
		}
		if (!(hit->r.contents & CONTENTS_TRIGGER)) {
			continue;
		}
		// ignore most entities if a spectator
		if (ent->client->sess.sessionTeam == TEAM_SPECTATOR) {
			if (hit->s.eType != ET_TELEPORT_TRIGGER) {	//&&
				// this is ugly but adding a new ET_? type will
				// most likely cause network incompatibilities
				// NiceAss: changed Touch_DoorTrigger to Touch_DoorTriggerSpectator
				// hit->touch != Touch_DoorTriggerSpectator) {
				continue;
			}
		}
		// use seperate code for determining if an item is picked up
		// so you don't have to actually contact its bounding box
		if (hit->s.eType == ET_ITEM) {
			if (!BG_PlayerTouchesItem(&ent->client->ps, &hit->s, level.time)) {
				continue;
			}
		} else {
			if (!trap_EntityContact(mins, maxs, hit)) {
				continue;
			}
		}

		memset(&trace, 0, sizeof(trace));

		if (hit->touch) {
			hit->touch(hit, ent, &trace);
		}

		if ((ent->r.svFlags & SVF_BOT) && (ent->touch)) {
			ent->touch(ent, hit, &trace);
		}
	}

	// if we didn't touch a jump pad this pmove frame
	if (ent->client->ps.jumppad_frame != ent->client->ps.pmove_framecount) {
		ent->client->ps.jumppad_frame = 0;
		ent->client->ps.jumppad_ent = 0;
	}

	if (ent->client->openDoor == 2) {
		ent->client->openDoor = qfalse;
		ent->client->openDoorTime = 0;
	}
}
void Warzone_Flag_Think( gentity_t *ent )
{
	vec3_t mins;
	vec3_t maxs;
	int touch[MAX_GENTITIES];
	int num = 0;
	int i = 0;
	int radius = ent->s.otherEntityNum2;

	ent->s.eFlags |= EF_RADAROBJECT;

#ifdef __UNUSED__
	if (flag_file_loaded)
	{
		if (!flag_spawnpoints_done)
		{// Have we initialized spawnpoints yet?
			int z = 0;

			for (z=0;z<number_of_flags;z++)
			{
				gentity_t *flagent = flag_list[z].flagentity;
				
				PreCalculate_Flag_Spawnpoints( flagent->count, flagent->s.angles, flagent->s.origin );
				//G_Printf("Flagnum is %i. flagent->s.otherEntityNum is %i\n", flagent->count, flagent->s.otherEntityNum);
				flagent->alt_fire = qtrue;
			}
			flag_spawnpoints_done = qtrue;
		}
	}
	else if (!ent->alt_fire)
	{// Have we initialized spawnpoints yet?
		//if (level.numConnectedClients > 0)
		{
			PreCalculate_Flag_Spawnpoints( ent->count, ent->s.angles, ent->s.origin );
			//G_Printf("Flagnum is %i. ent->s.otherEntityNum is %i\n", ent->count, ent->s.otherEntityNum);
			ent->alt_fire = qtrue;
			flag_spawnpoints_done = qtrue;
		}
	}
#endif //__UNUSED__

	if (ent->nextthink > level.time)
		return;

	mins[0] = 0-radius;
	mins[1] = 0-radius;
	mins[2] = 0-(radius*0.5);

	maxs[0] = radius;
	maxs[1] = radius;
	maxs[2] = radius*0.5;

	VectorAdd( mins, ent->s.origin, mins );
	VectorAdd( maxs, ent->s.origin, maxs );

	// Run the think... Look for captures...
	num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

	for ( i=0 ; i<num ; i++ ) 
	{
		gentity_t *hit = &g_entities[touch[i]];

		if (!hit)
			continue;

		if (!hit->client)
			continue;

		if (!hit->health || hit->health <= 0)
			continue;

		if (hit->classname == "NPC_Vehicle")
			continue;

		//if (hit->s.eType == ET_NPC)
		//	hit->s.teamowner = hit->client->playerTeam;

		if (!EntityVisible(ent, hit))
		{
			hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = 0;
			continue;
		}

		if (ent->s.teamowner == TEAM_RED)
		{// Red flag...
			if ((hit->s.eType == ET_PLAYER || hit->s.eType == ET_NPC) && hit->s.teamowner == TEAM_RED)
			{// Red player consolidating a red flag for spawns... 
				//G_Printf("Consolidating flag!\n");

				ent->s.time2++;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;

				if (ent->s.time2 >= 100)
				{// Finished consolidating.. Set new team to blue and initialize...
					ent->s.teamowner = TEAM_RED;
					ent->s.time2 = 100;
					ent->s.genericenemyindex = TEAM_NONE;
				}
			}
			else if ((hit->s.eType == ET_PLAYER || hit->s.eType == ET_NPC) && hit->s.teamowner == TEAM_BLUE)
			{// Blue player undoing red flag...
				//G_Printf("Uncapturing flag!\n");

				ent->s.time2--;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;

				if (ent->s.time2 <= 0)
				{// Finished capture.. Set new team to blue...
					ent->s.teamowner = TEAM_NONE;
					ent->s.time2 = 0;
					ent->s.genericenemyindex = TEAM_NONE;
				}
			}
		}
		else if (ent->s.teamowner == TEAM_BLUE)
		{// Blue flag...
			if ((hit->s.eType == ET_PLAYER || hit->s.eType == ET_NPC) && hit->s.teamowner == TEAM_BLUE)
			{// Blue player consolidating a blue flag for spawns... 
				//G_Printf("Consolidating flag!\n");

				ent->s.time2++;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;

				if (ent->s.time2 >= 100)
				{// Finished consolidating.. Set new team to blue and initialize...
					ent->s.teamowner = TEAM_BLUE;
					ent->s.time2 = 100;
					ent->s.genericenemyindex = TEAM_NONE;
				}
			}
			else if ((hit->s.eType == ET_PLAYER || hit->s.eType == ET_NPC) && hit->s.teamowner == TEAM_RED)
			{// Red player undoing blue flag...
				//G_Printf("Uncapturing flag!\n");

				ent->s.time2--;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;

				if (ent->s.time2 <= 0)
				{// Finished capture.. Set new team to blue...
					ent->s.teamowner = TEAM_NONE;
					ent->s.time2 = 0;
					ent->s.genericenemyindex = TEAM_NONE;
				}
			}
		}
		else
		{// Neutral flag...
			if (!ent->s.genericenemyindex || ent->s.genericenemyindex == TEAM_NONE)
			{// Start capture... Set capturing team number...
				ent->s.genericenemyindex = hit->s.teamowner;
				ent->s.time2 = 0;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;
			}
			else if (ent->s.genericenemyindex == hit->s.teamowner)
			{// Continuing partial capture...
				ent->s.time2++;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;

				// Set the current capturing team number of a neutral flag..
				ent->s.genericenemyindex = hit->s.teamowner;

				//G_Printf("Capturing flag!\n");

				if ((hit->s.eType == ET_PLAYER || hit->s.eType == ET_NPC) 
					&& hit->s.teamowner == TEAM_BLUE && ent->s.time2 >= 50)
				{// Blue player capturing neutral flag... Finished capture.. Set new team to blue...
					ent->s.teamowner = TEAM_BLUE;
					ent->s.time2 = 0;
					ent->s.genericenemyindex = TEAM_NONE;
				}
				else if ((hit->s.eType == ET_PLAYER || hit->s.eType == ET_NPC) 
					&& hit->s.teamowner == TEAM_RED && ent->s.time2 >= 50)
				{// Red player capturing neutral flag... Finished capture.. Set new team to red...
					ent->s.teamowner = TEAM_RED;
					ent->s.time2 = 0;
					ent->s.genericenemyindex = TEAM_NONE;
				}
			}
			else if (ent->s.genericenemyindex != hit->s.teamowner)
			{// Undoing partial capture...
				ent->s.time2--;
				hit->client->ps.stats[STAT_CAPTURE_ENTITYNUM] = ent->s.number;

				//G_Printf("Undoing owned flag!\n");

				if (ent->s.time2 <= 0)
				{// Initialize back to untouched flag...
					ent->s.teamowner = TEAM_NONE;
					ent->s.time2 = 0;
					ent->s.genericenemyindex = TEAM_NONE;
				}
			}
		}
	}

	// Set next think...
	ent->nextthink = level.time + 500;
}
Ejemplo n.º 29
0
/*
============
G_RadiusDamage
============
*/
qboolean G_RadiusDamage( vec3_t origin, gentity_t *attacker, float damage, float radius,
						 gentity_t *ignore, int mod ) {
	float points, dist;
	gentity_t   *ent;
	int entityList[MAX_GENTITIES];
	int numListedEntities;
	vec3_t mins, maxs;
	vec3_t v;
	vec3_t dir;
	int i, e;
	qboolean hitClient = qfalse;
// JPW NERVE
	float boxradius;
	vec3_t dest;
	trace_t tr;
	vec3_t midpoint;
// jpw


	if ( radius < 1 ) {
		radius = 1;
	}

	boxradius = 1.41421356 * radius; // radius * sqrt(2) for bounding box enlargement --
	// bounding box was checking against radius / sqrt(2) if collision is along box plane
	for ( i = 0 ; i < 3 ; i++ ) {
		mins[i] = origin[i] - boxradius; // JPW NERVE
		maxs[i] = origin[i] + boxradius; // JPW NERVE
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0 ; e < numListedEntities ; e++ ) {
		ent = &g_entities[entityList[ e ]];

		if ( ent == ignore ) {
			continue;
		}
		if ( !ent->takedamage ) {
			continue;
		}

/* JPW NERVE -- we can put this back if we need to, but it kinna sucks for human-sized bboxes
		// find the distance from the edge of the bounding box
		for ( i = 0 ; i < 3 ; i++ ) {
			if ( origin[i] < ent->r.absmin[i] ) {
				v[i] = ent->r.absmin[i] - origin[i];
			} else if ( origin[i] > ent->r.absmax[i] ) {
				v[i] = origin[i] - ent->r.absmax[i];
			} else {
				v[i] = 0;
			}
		}
*/
// JPW NERVE
		if ( !ent->r.bmodel ) {
			VectorSubtract( ent->r.currentOrigin,origin,v ); // JPW NERVE simpler centroid check that doesn't have box alignment weirdness
		} else {
			for ( i = 0 ; i < 3 ; i++ ) {
				if ( origin[i] < ent->r.absmin[i] ) {
					v[i] = ent->r.absmin[i] - origin[i];
				} else if ( origin[i] > ent->r.absmax[i] ) {
					v[i] = origin[i] - ent->r.absmax[i];
				} else {
					v[i] = 0;
				}
			}
		}
// jpw
		dist = VectorLength( v );
		if ( dist >= radius ) {
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

// JPW NERVE -- different radiusdmg behavior for MP -- big explosions should do less damage (over less distance) through failed traces
		if ( CanDamage( ent, origin ) ) {
			if ( LogAccuracyHit( ent, attacker ) ) {
				hitClient = qtrue;
			}
			VectorSubtract( ent->r.currentOrigin, origin, dir );
			// push the center of mass higher than the origin so players
			// get knocked into the air more
			dir[2] += 24;
			G_Damage( ent, NULL, attacker, dir, origin, (int)points, DAMAGE_RADIUS, mod );
		}
// JPW NERVE --  MP weapons should do 1/8 damage through walls over 1/8th distance
		else {
			if ( g_gametype.integer != GT_SINGLE_PLAYER ) {
				VectorAdd( ent->r.absmin, ent->r.absmax, midpoint );
				VectorScale( midpoint, 0.5, midpoint );
				VectorCopy( midpoint, dest );

				trap_Trace( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID );
				if ( tr.fraction < 1.0 ) {
					VectorSubtract( dest,origin,dest );
					dist = VectorLength( dest );
					if ( dist < radius * 0.2f ) { // closer than 1/4 dist
						if ( LogAccuracyHit( ent, attacker ) ) {
							hitClient = qtrue;
						}
						VectorSubtract( ent->r.currentOrigin, origin, dir );
						dir[2] += 24;
						G_Damage( ent, NULL, attacker, dir, origin, (int)( points * 0.1f ), DAMAGE_RADIUS, mod );
					}
				}
			}
		}
// jpw
	}
	return hitClient;
}
Ejemplo n.º 30
0
bool G_RadiusDamage( vec3_t origin, gentity_t *attacker, float damage,
                         float radius, gentity_t *ignore, int dflags, int mod, team_t testHit )
{
	float     points, dist;
	gentity_t *ent;
	int       entityList[ MAX_GENTITIES ];
	int       numListedEntities;
	vec3_t    mins, maxs;
	vec3_t    v;
	vec3_t    dir;
	int       i, e;
	bool  hitSomething = false;

	if ( radius < 1 )
	{
		radius = 1;
	}

	for ( i = 0; i < 3; i++ )
	{
		mins[ i ] = origin[ i ] - radius;
		maxs[ i ] = origin[ i ] + radius;
	}

	numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );

	for ( e = 0; e < numListedEntities; e++ )
	{
		ent = &g_entities[ entityList[ e ] ];

		if ( ent == ignore )
		{
			continue;
		}

		// find the distance from the edge of the bounding box
		for ( i = 0; i < 3; i++ )
		{
			if ( origin[ i ] < ent->r.absmin[ i ] )
			{
				v[ i ] = ent->r.absmin[ i ] - origin[ i ];
			}
			else if ( origin[ i ] > ent->r.absmax[ i ] )
			{
				v[ i ] = origin[ i ] - ent->r.absmax[ i ];
			}
			else
			{
				v[ i ] = 0;
			}
		}

		dist = VectorLength( v );

		if ( dist >= radius )
		{
			continue;
		}

		points = damage * ( 1.0 - dist / radius );

		if ( G_CanDamage( ent, origin ) )
		{
			if ( testHit == TEAM_NONE )
			{
				VectorSubtract( ent->r.currentOrigin, origin, dir );
				// push the center of mass higher than the origin so players
				// get knocked into the air more
				dir[ 2 ] += 24;
				VectorNormalize( dir );

				hitSomething = ent->entity->Damage(points, attacker, Vec3::Load(origin), Vec3::Load(dir),
				                                   (DAMAGE_NO_LOCDAMAGE | dflags), (meansOfDeath_t)mod);
			}
			else if ( G_Team( ent ) == testHit && G_Alive( ent ) )
			{
				return true;
			}
		}
	}

	return hitSomething;
}