Esempio n. 1
0
void CG_GibPlayer(centity_t *cent, vec3_t playerOrigin, vec3_t gdir)
{
	int            i, count = 0, tagIndex, gibIndex;
	vec3_t         origin, velocity, dir;
	trace_t        trace;
	qboolean       foundtag;
	clientInfo_t   *ci;
	int            clientNum;
	bg_character_t *character;
	vec4_t         projection, color;

	// Rafael
	// BloodCloud
	qboolean newjunction[MAXJUNCTIONS];
	vec3_t   junctionOrigin[MAXJUNCTIONS];
	int      junction;
	int      j;
	vec3_t   axis[3], angles;

	char *JunctiongibTags[] =
	{
		// leg tag
		"tag_footright",
		"tag_footleft",
		"tag_legright",
		"tag_legleft",

		// torsotags
		"tag_armright",
		"tag_armleft",

		"tag_torso",
		"tag_chest"
	};

	char *ConnectTags[] =
	{
		// legs tags
		"tag_legright",
		"tag_legleft",
		"tag_torso",
		"tag_torso",

		// torso tags
		"tag_chest",
		"tag_chest",

		"tag_chest",
		"tag_torso",
	};

	char *gibTags[] =
	{
		// tags in the legs
		"tag_footright",
		"tag_footleft",
		"tag_legright",
		"tag_legleft",
		"tag_torso",

		// tags in the torso
		"tag_chest",
		"tag_armright",
		"tag_armleft",
		"tag_head",
		NULL
	};

	if (cg_blood.integer)
	{
		// Rafael
		for (i = 0; i < MAXJUNCTIONS; i++)
			newjunction[i] = qfalse;

		clientNum = cent->currentState.clientNum;
		if (clientNum < 0 || clientNum >= MAX_CLIENTS)
		{
			CG_Error("Bad clientNum on player entity");
		}
		ci        = &cgs.clientinfo[clientNum];
		character = CG_CharacterForClientinfo(ci, cent);

		// Ridah, fetch the various positions of the tag_gib*'s
		// and spawn the gibs from the correct places (especially the head)
		for (gibIndex = 0, count = 0, foundtag = qtrue; foundtag && gibIndex < MAX_GIB_MODELS && gibTags[gibIndex]; gibIndex++)
		{

			refEntity_t *re = 0;

			foundtag = qfalse;

			if (!character->gibModels[gibIndex])
			{
				continue;
			}

			re = &cent->pe.bodyRefEnt;

			for (tagIndex = 0; (tagIndex = CG_GetOriginForTag(cent, re, gibTags[gibIndex], tagIndex, origin, axis)) >= 0; count++, tagIndex++)
			{

				foundtag = qtrue;

				VectorSubtract(origin, re->origin, dir);
				VectorNormalize(dir);

				// spawn a gib
				velocity[0] = dir[0] * (0.5 + random()) * GIB_VELOCITY * 0.3;
				velocity[1] = dir[1] * (0.5 + random()) * GIB_VELOCITY * 0.3;
				velocity[2] = GIB_JUMP + dir[2] * (0.5 + random()) * GIB_VELOCITY * 0.5;

				VectorMA(velocity, GIB_VELOCITY, gdir, velocity);
				AxisToAngles(axis, angles);

				CG_LaunchGib(cent, origin, angles, velocity, character->gibModels[gibIndex], 1.0, 0);

				for (junction = 0; junction < MAXJUNCTIONS; junction++)
				{
					if (!Q_stricmp(gibTags[gibIndex], JunctiongibTags[junction]))
					{
						VectorCopy(origin, junctionOrigin[junction]);
						newjunction[junction] = qtrue;
					}
				}
			}
		}

		for (i = 0; i < MAXJUNCTIONS; i++)
		{
			if (newjunction[i] == qtrue)
			{
				for (j = 0; j < MAXJUNCTIONS; j++)
				{
					if (!Q_stricmp(JunctiongibTags[j], ConnectTags[i]))
					{
						if (newjunction[j] == qtrue)
						{
							// spawn a blood cloud somewhere on the vec from
							VectorSubtract(junctionOrigin[i], junctionOrigin[j], dir);
							CG_ParticleBloodCloud(cent, junctionOrigin[i], dir);
						}
					}
				}
			}
		}

		// Ridah, spawn a bunch of blood dots around the place
		#define GIB_BLOOD_DOTS  3
		for (i = 0, count = 0; i < GIB_BLOOD_DOTS * 2; i++)
		{
			// TTimo: unused
			//static vec3_t mins = {-10,-10,-10};
			//static vec3_t maxs = { 10, 10, 10};

			if (i > 0)
			{
				velocity[0] = ((i % 2) * 2 - 1) * (40 + 40 * random());
				velocity[1] = (((i / 2) % 2) * 2 - 1) * (40 + 40 * random());
				velocity[2] = (((i < GIB_BLOOD_DOTS) * 2) - 1) * 40;
			}
			else
			{
				VectorClear(velocity);
				velocity[2] = -64;
			}

			VectorAdd(playerOrigin, velocity, origin);

			CG_Trace(&trace, playerOrigin, NULL, NULL, origin, -1, CONTENTS_SOLID);
			if (trace.fraction < 1.0)
			{
				//%	BG_GetMarkDir( velocity, trace.plane.normal, velocity );
				//%	CG_ImpactMark( cgs.media.bloodDotShaders[rand()%5], trace.endpos, velocity, random()*360,
				//%		1,1,1,1, qtrue, 30, qfalse, cg_bloodTime.integer * 1000 );
				#if 0
				BG_GetMarkDir(velocity, trace.plane.normal, projection);
				VectorSubtract(vec3_origin, projection, projection);
				projection[3] = 64;
				VectorMA(trace.endpos, -8.0f, projection, markOrigin);
				CG_ImpactMark(cgs.media.bloodDotShaders[rand() % 5], markOrigin, projection, 30.0f, random() * 360.0f, 1.0f, 1.0f, 1.0f, 1.0f, cg_bloodTime.integer * 1000);
				#else
				VectorSet(projection, 0, 0, -1);
				projection[3] = 30.0f;
				Vector4Set(color, 1.0f, 1.0f, 1.0f, 1.0f);
				trap_R_ProjectDecal(cgs.media.bloodDotShaders[rand() % 5], 1, (vec3_t *) trace.endpos, projection, color,
				                    cg_bloodTime.integer * 1000, (cg_bloodTime.integer * 1000) >> 4);
				#endif

				if (count++ > GIB_BLOOD_DOTS)
				{
					break;
				}
			}
		}
	}
Esempio n. 2
0
/*
================
G_MissileImpact
	impactDamage is how much damage the impact will do to func_explosives
================
*/
void G_MissileImpact( gentity_t *ent, trace_t *trace, int impactDamage ) {
	gentity_t       *other;
	qboolean hitClient = qfalse;
	vec3_t velocity;
	int etype;

	other = &g_entities[trace->entityNum];

	// handle func_explosives
	if ( other->classname && Q_stricmp( other->classname, "func_explosive" ) == 0 ) {
		// the damage is sufficient to "break" the ent (health == 0 is non-breakable)
		if ( other->health && impactDamage >= other->health ) {
			// check for other->takedamage needs to be inside the health check since it is
			// likely that, if successfully destroyed by the missile, in the next runmissile()
			// update takedamage would be set to '0' and the func_explosive would not be
			// removed yet, causing a bounce.
			if ( other->takedamage ) {
				BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
				G_Damage( other, ent, &g_entities[ent->r.ownerNum], velocity, ent->s.origin, impactDamage, 0, ent->methodOfDeath );
			}

			// its possible of the func_explosive not to die from this and it
			// should reflect the missile or explode it not vanish into oblivion
			if ( other->health <= 0 ) {
				return;
			}
		}
	}

	// check for bounce
	if ( !other->takedamage &&
		 ( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
		G_BounceMissile( ent, trace );
		// JPW NERVE -- spotter White Phosphorous rounds shouldn't bounce noise
		if ( !Q_stricmp( ent->classname,"WP" ) ) {
			return;
		}
		// jpw
		if ( !Q_stricmp( ent->classname, "flamebarrel" ) ) {
			G_AddEvent( ent, EV_FLAMEBARREL_BOUNCE, 0 );
		} else {
			G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
		}
		return;
	}

	if ( other->takedamage && ent->s.density == 1 ) {
		G_ExplodeMissilePoisonGas( ent );
		return;
	}

	// impact damage
	if ( other->takedamage ) {
		if ( ent->damage ) {

			if ( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
				if ( g_entities[ent->r.ownerNum].client ) {
					g_entities[ent->r.ownerNum].client->ps.persistant[PERS_ACCURACY_HITS]++;
				}
				hitClient = qtrue;
			}
			BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
			if ( VectorLength( velocity ) == 0 ) {
				velocity[2] = 1;    // stepped on a grenade
			}
			G_Damage( other, ent, &g_entities[ent->r.ownerNum], velocity,
					  ent->s.origin, ent->damage,
					  0, ent->methodOfDeath );
		} else    // if no damage value, then this is a splash damage grenade only
		{
			G_BounceMissile( ent, trace );
			return;
		}
	}

	// is it cheaper in bandwidth to just remove this ent and create a new
	// one, rather than changing the missile into the explosion?

	if ( other->takedamage && other->client ) {
		G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
		ent->s.otherEntityNum = other->s.number;
	} else {
		// Ridah, try projecting it in the direction it came from, for better decals
		vec3_t dir;
		BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, dir );
		BG_GetMarkDir( dir, trace->plane.normal, dir );
		G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( dir ) );
	}

	ent->freeAfterEvent = qtrue;

	// change over to a normal entity right at the point of impact
	etype = ent->s.eType;
	ent->s.eType = ET_GENERAL;

	SnapVectorTowards( trace->endpos, ent->s.pos.trBase );  // save net bandwidth

	G_SetOrigin( ent, trace->endpos );

	// splash damage (doesn't apply to person directly hit)
	if ( ent->splashDamage ) {
		if ( G_RadiusDamage( trace->endpos, ent->parent, ent->splashDamage, ent->splashRadius,
							 other, ent->splashMethodOfDeath ) ) {
			if ( !hitClient && g_entities[ent->r.ownerNum].client ) {
				g_entities[ent->r.ownerNum].client->ps.persistant[PERS_ACCURACY_HITS]++;
			}
		}
	}

	trap_LinkEntity( ent );
}