Ejemplo n.º 1
0
void cashspawn_think( edict_t *self )
{
	edict_t	*cash;

	if ((num_cash_items > MAX_CASH_ITEMS) || (level.modeset == MATCHSETUP) || (level.modeset == MATCHCOUNT) || (level.modeset == PREGAME))
	{
		self->nextthink = level.time + self->delay;
		return;
	}

	// spawn some money
	cash = G_Spawn();

	VectorCopy( self->s.origin, cash->s.origin );
	cash->movetype = MOVETYPE_BOUNCE;
	cash->solid = SOLID_TRIGGER;

	AngleVectors( self->s.angles, cash->velocity, NULL, NULL );
	VectorScale( cash->velocity, self->speed, cash->velocity );

	// randomize the velocity a bit
	VectorAdd( cash->velocity, tv( crandom()*self->speed*0.3, crandom()*self->speed*0.3, crandom()*self->speed*0.15 ), cash->velocity );

	cash->s.renderfx2 |= RF2_NOSHADOW;

	// FIXME: doh this doesn't work, need to spawn actual item's, so the HUD is updated automatically when picking up

	if (!strcmp(self->type, "cashroll"))
	{	// small dollar notes
		cash->s.modelindex = gi.modelindex( "models/pu_icon/cash/tris.md2" );
		cash->gravity = 0.1 + random()*0.5;

		cash->think = cashroll_animate;
		cash->nextthink = level.time + 0.1;
		cash->s.angles[PITCH] = 10;
		VectorSet( cash->avelocity, 0, 10000 * cash->gravity, 0 );

		VectorSet( cash->mins, -4, -4, -15 );
		VectorSet( cash->maxs,  4,  4, -13 );

		cash->item = FindItem("Cash");

		cash->currentcash = CASH_ROLL;
		cash->touch = cash_touch;

		cash->timestamp = level.time + 60;

		cash->think = cashroll_animate;
		cash->nextthink = level.time + 0.1;
	}
	else
	{
		cash->s.modelindex = gi.modelindex( "models/pu_icon/money/money_sm.md2" );
		cash->gravity = 1.0;

		VectorSet( cash->mins, -12, -12, -15 );
		VectorSet( cash->maxs,  12,  12,  10 );

		cash->item = FindItem("Small Cash Bag");

		cash->currentcash = CASH_BAG;
		cash->touch = cash_touch;

		cash->think = cash_kill;
		cash->nextthink = level.time + 60;
	}

	num_cash_items++;

	self->nextthink = level.time + self->delay;

}
Ejemplo n.º 2
0
/*
================
G_RunItem

================
*/
void G_RunItem( gentity_t *ent ) {
	vec3_t		origin;
	trace_t		tr;
	int			contents;
	int			mask;

	// if groundentity has been set to -1, it may have been pushed off an edge
	if ( ent->s.groundEntityNum == ENTITYNUM_NONE ) 
	{
		if ( ent->s.pos.trType != TR_GRAVITY ) 
		{
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
		}
	}

	if ( ent->s.pos.trType == TR_STATIONARY ) 
	{
		// check think function
		G_RunThink( ent );
		if ( !g_gravity->value )
		{
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
			ent->s.pos.trDelta[0] += crandom() * 40.0f; // I dunno, just do this??
			ent->s.pos.trDelta[1] += crandom() * 40.0f;
			ent->s.pos.trDelta[2] += random() * 20.0f;
		}
		return;
	}

	// get current position
	EvaluateTrajectory( &ent->s.pos, level.time, origin );

	// trace a line from the previous position to the current position
	if ( ent->clipmask ) 
	{
		mask = ent->clipmask;
	} 
	else 
	{
		mask = MASK_SOLID|CONTENTS_PLAYERCLIP;//shouldn't be able to get anywhere player can't
	}

	int ignore = ENTITYNUM_NONE;
	if ( ent->owner )
	{
		ignore = ent->owner->s.number;
	}
	else if ( ent->activator )
	{
		ignore = ent->activator->s.number;
	}
	gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, ignore, mask, G2_NOCOLLIDE, 0 );

	VectorCopy( tr.endpos, ent->currentOrigin );

	if ( tr.startsolid ) 
	{
		tr.fraction = 0;
	}

	gi.linkentity( ent );	// FIXME: avoid this for stationary?

	// check think function
	G_RunThink( ent );

	if ( tr.fraction == 1 ) 
	{
		if ( g_gravity->value <= 0 )
		{
			if ( ent->s.apos.trType != TR_LINEAR )
			{
				VectorCopy( ent->currentAngles, ent->s.apos.trBase );
				ent->s.apos.trType = TR_LINEAR;
				ent->s.apos.trDelta[1] = Q_flrand( -300, 300 );
				ent->s.apos.trDelta[0] = Q_flrand( -10, 10 );
				ent->s.apos.trDelta[2] = Q_flrand( -10, 10 );
				ent->s.apos.trTime = level.time;
			}
		}
		//friction in zero-G
		if ( !g_gravity->value )
		{
			float friction = 0.975f;
			/*friction -= ent->mass/1000.0f;
			if ( friction < 0.1 )
			{
				friction = 0.1f;
			}
			*/
			VectorScale( ent->s.pos.trDelta, friction, ent->s.pos.trDelta );
			VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
			ent->s.pos.trTime = level.time;
		}
		return;
	}

	// if it is in a nodrop volume, remove it
	contents = gi.pointcontents( ent->currentOrigin, -1 );
	if ( contents & CONTENTS_NODROP ) 
	{
		G_FreeEntity( ent );
		return;
	}

	if ( !tr.startsolid )
	{
		G_BounceItem( ent, &tr );
	}
}
Ejemplo n.º 3
0
/*
==============
CG_DamageFeedback
==============
*/
void CG_DamageFeedback(int yawByte, int pitchByte, int damage)
{
	float        left, front, up;
	float        kick;
	int          health;
	float        scale;
	vec3_t       dir;
	vec3_t       angles;
	float        dist;
	float        yaw, pitch;
	int          slot;
	viewDamage_t *vd;

	// show the attacking player's head and name in corner
	cg.attackerTime = cg.time;

	// the lower on health you are, the greater the view kick will be
	health = cg.snap->ps.stats[STAT_HEALTH];
	if (health < 40)
	{
		scale = 1;
	}
	else
	{
		scale = 40.0 / health;
	}
	kick = damage * scale;

	if (kick < 5)
	{
		kick = 5;
	}
	if (kick > 10)
	{
		kick = 10;
	}

	// find a free slot
	for (slot = 0; slot < MAX_VIEWDAMAGE; slot++)
	{
		if (cg.viewDamage[slot].damageTime + cg.viewDamage[slot].damageDuration < cg.time)
		{
			break;
		}
	}

	if (slot == MAX_VIEWDAMAGE)
	{
		return;     // no free slots, never override or splats will suddenly disappear

	}
	vd = &cg.viewDamage[slot];

	// if yaw and pitch are both 255, make the damage always centered (falling, etc)
	if (yawByte == 255 && pitchByte == 255)
	{
		vd->damageX    = 0;
		vd->damageY    = 0;
		cg.v_dmg_roll  = 0;
		cg.v_dmg_pitch = -kick;
	}
	else
	{
		// positional
		pitch = pitchByte / 255.0 * 360;
		yaw   = yawByte / 255.0 * 360;

		angles[PITCH] = pitch;
		angles[YAW]   = yaw;
		angles[ROLL]  = 0;

		AngleVectors(angles, dir, NULL, NULL);
		VectorSubtract(vec3_origin, dir, dir);

		front = DotProduct(dir, cg.refdef.viewaxis[0]);
		left  = DotProduct(dir, cg.refdef.viewaxis[1]);
		up    = DotProduct(dir, cg.refdef.viewaxis[2]);

		dir[0] = front;
		dir[1] = left;
		dir[2] = 0;
		dist   = VectorLength(dir);
		if (dist < 0.1)
		{
			dist = 0.1;
		}

		cg.v_dmg_roll = kick * left;

		cg.v_dmg_pitch = -kick * front;

		if (front <= 0.1)
		{
			front = 0.1;
		}
		vd->damageX = crandom() * 0.3 + -left / front;
		vd->damageY = crandom() * 0.3 + up / dist;
	}

	// clamp the position
	if (vd->damageX > 1.0)
	{
		vd->damageX = 1.0;
	}
	if (vd->damageX < -1.0)
	{
		vd->damageX = -1.0;
	}

	if (vd->damageY > 1.0)
	{
		vd->damageY = 1.0;
	}
	if (vd->damageY < -1.0)
	{
		vd->damageY = -1.0;
	}

	// don't let the screen flashes vary as much
	if (kick > 10)
	{
		kick = 10;
	}
	vd->damageValue    = kick;
	cg.v_dmg_time      = cg.time + DAMAGE_TIME;
	vd->damageTime     = cg.snap->serverTime;
	vd->damageDuration = kick * 50 * (1 + 2 * (!vd->damageX && !vd->damageY));
	cg.damageTime      = cg.snap->serverTime;
	cg.damageIndex     = slot;
}
Ejemplo n.º 4
0
//------------------------------------
void Seeker_Strafe( void )
{
    int		side;
    vec3_t	end, right, dir;
    trace_t	tr;

    if ( random() > 0.7f || !NPC->enemy || !NPC->enemy->client )
    {
        // Do a regular style strafe
        AngleVectors( NPC->client->renderInfo.eyeAngles, NULL, right, NULL );

        // Pick a random strafe direction, then check to see if doing a strafe would be
        //	reasonably valid
        side = ( rand() & 1 ) ? -1 : 1;
        VectorMA( NPC->currentOrigin, SEEKER_STRAFE_DIS * side, right, end );

        gi.trace( &tr, NPC->currentOrigin, NULL, NULL, end, NPC->s.number, MASK_SOLID, (EG2_Collision)0, 0 );

        // Close enough
        if ( tr.fraction > 0.9f )
        {
            float vel = SEEKER_STRAFE_VEL;
            float upPush = SEEKER_UPWARD_PUSH;
            if ( NPC->client->NPC_class != CLASS_BOBAFETT )
            {
                G_Sound( NPC, G_SoundIndex( "sound/chars/seeker/misc/hiss" ));
            }
            else
            {
                vel *= 3.0f;
                upPush *= 4.0f;
            }
            VectorMA( NPC->client->ps.velocity, vel*side, right, NPC->client->ps.velocity );
            // Add a slight upward push
            NPC->client->ps.velocity[2] += upPush;

            NPCInfo->standTime = level.time + 1000 + random() * 500;
        }
    }
    else
    {
        // Do a strafe to try and keep on the side of their enemy
        AngleVectors( NPC->enemy->client->renderInfo.eyeAngles, dir, right, NULL );

        // Pick a random side
        side = ( rand() & 1 ) ? -1 : 1;
        float	stDis = SEEKER_STRAFE_DIS;
        if ( NPC->client->NPC_class == CLASS_BOBAFETT )
        {
            stDis *= 2.0f;
        }
        VectorMA( NPC->enemy->currentOrigin, stDis * side, right, end );

        // then add a very small bit of random in front of/behind the player action
        VectorMA( end, crandom() * 25, dir, end );

        gi.trace( &tr, NPC->currentOrigin, NULL, NULL, end, NPC->s.number, MASK_SOLID, (EG2_Collision)0, 0 );

        // Close enough
        if ( tr.fraction > 0.9f )
        {
            VectorSubtract( tr.endpos, NPC->currentOrigin, dir );
            dir[2] *= 0.25; // do less upward change
            float dis = VectorNormalize( dir );

            // Try to move the desired enemy side
            VectorMA( NPC->client->ps.velocity, dis, dir, NPC->client->ps.velocity );

            float upPush = SEEKER_UPWARD_PUSH;
            if ( NPC->client->NPC_class != CLASS_BOBAFETT )
            {
                G_Sound( NPC, G_SoundIndex( "sound/chars/seeker/misc/hiss" ));
            }
            else
            {
                upPush *= 4.0f;
            }

            // Add a slight upward push
            NPC->client->ps.velocity[2] += upPush;

            NPCInfo->standTime = level.time + 2500 + random() * 500;
        }
    }
}
Ejemplo n.º 5
0
void pendulum_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
    // Mostly copied from func_explosive_explode. We can't use that function because
    // the origin is a bit different.

    vec3_t origin;
    vec3_t forward, left, up;
    vec3_t chunkorigin;
    vec3_t size;
    int    count;
    int    mass;

    // Particles originate from business end of pendulum
    AngleVectors(self->s.angles, forward, left, up);
    VectorScale(forward, self->move_origin[0], forward);
    VectorScale(left, -self->move_origin[1], left);
    VectorScale(up, self->move_origin[2], up);
    VectorAdd(self->s.origin, forward, origin);
    VectorAdd(origin, left, origin);
    VectorAdd(origin, up, origin);

    self->mass      *= 2;
    self->takedamage = DAMAGE_NO;

    VectorSubtract(origin, self->enemy->s.origin, self->velocity);
    VectorNormalize(self->velocity);
    VectorScale(self->velocity, 150, self->velocity);

    // start chunks towards the center
    VectorScale(size, 0.5, size);

    mass = self->mass;
    if (!mass)
    {
        mass = 75;
    }

    // big chunks
    if (mass >= 100)
    {
        count = mass / 100;
        if (count > 8)
        {
            count = 8;
        }
        while (count--)
        {
            chunkorigin[0] = origin[0] + crandom() * size[0];
            chunkorigin[1] = origin[1] + crandom() * size[1];
            chunkorigin[2] = origin[2] + crandom() * size[2];
            ThrowDebris(self, "models/objects/debris1/tris.md2", 1, chunkorigin, 0, 0);
        }
    }

    // small chunks
    count = mass / 25;
    if (count > 16)
    {
        count = 16;
    }
    while (count--)
    {
        chunkorigin[0] = origin[0] + crandom() * size[0];
        chunkorigin[1] = origin[1] + crandom() * size[1];
        chunkorigin[2] = origin[2] + crandom() * size[2];
        ThrowDebris(self, "models/objects/debris2/tris.md2", 2, chunkorigin, 0, 0);
    }
    G_FreeEdict(self);
}
Ejemplo n.º 6
0
/*
======================
CG_AddParticles
======================
*/
void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent)
{
	cparticle_t	*p;
	qboolean turb = qtrue;

	if (!pshader)
		CG_Printf ("CG_ParticleSnowFlurry pshader == ZERO!\n");

	if (!free_particles)
		return;
	p = free_particles;
	free_particles = p->next;
	p->next = active_particles;
	active_particles = p;
	p->time = cg.time;
	p->color = 0;
	p->alpha = 0.90f;
	p->alphavel = 0;

	p->start = cent->currentState.origin2[0];
	p->end = cent->currentState.origin2[1];
	
	p->endtime = cg.time + cent->currentState.time;
	p->startfade = cg.time + cent->currentState.time2;
	
	p->pshader = pshader;
	
	if (rand()%100 > 90)
	{
		p->height = 32;
		p->width = 32;
		p->alpha = 0.10f;
	}
	else
	{
		p->height = 1;
		p->width = 1;
	}

	p->vel[2] = -20;

	p->type = P_WEATHER_FLURRY;
	
	if (turb)
		p->vel[2] = -10;
	
	VectorCopy(cent->currentState.origin, p->org);

	p->org[0] = p->org[0];
	p->org[1] = p->org[1];
	p->org[2] = p->org[2];

	p->vel[0] = p->vel[1] = 0;
	
	p->accel[0] = p->accel[1] = p->accel[2] = 0;

	p->vel[0] += cent->currentState.angles[0] * 32 + (crandom() * 16);
	p->vel[1] += cent->currentState.angles[1] * 32 + (crandom() * 16);
	p->vel[2] += cent->currentState.angles[2];

	if (turb)
	{
		p->accel[0] = crandom () * 16;
		p->accel[1] = crandom () * 16;
	}

}
Ejemplo n.º 7
0
/*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON
This should be renamed trigger_timer...
Repeatedly fires its targets.
Can be turned on or off by using.

"wait"			base time between triggering all targets, default is 1
"random"		wait variance, default is 0
so, the basic time between firing is a random time between
(wait - random) and (wait + random)

*/
void func_timer_think( gentity_t *self ) {
	G_UseTargets (self, self->activator);
	// set time before next firing
	self->nextthink = level.time + 1000 * ( self->wait + crandom() * self->random );
}
Ejemplo n.º 8
0
//---------------------------------------------------------
void rocketThink( gentity_t *ent )
//---------------------------------------------------------
{
	vec3_t newdir, targetdir, 
			up={0,0,1}, right; 
	vec3_t	org;
	float dot, dot2;

	if ( ent->disconnectDebounceTime && ent->disconnectDebounceTime < level.time )
	{//time's up, we're done, remove us
		if ( ent->lockCount )
		{//explode when die
			WP_ExplosiveDie( ent, ent->owner, ent->owner, 0, MOD_UNKNOWN, 0, HL_NONE );
		}
		else
		{//just remove when die
			G_FreeEntity( ent );
		}
		return;
	}
	if ( ent->enemy && ent->enemy->inuse )
	{
		float vel = (ent->spawnflags&1)?ent->speed:ROCKET_VELOCITY;
		float newDirMult = ent->angle?ent->angle*2.0f:1.0f;
		float oldDirMult = ent->angle?(1.0f-ent->angle)*2.0f:1.0f;

		if ( (ent->spawnflags&1) )
		{//vehicle rocket
			if ( ent->enemy->client && ent->enemy->client->NPC_class == CLASS_VEHICLE )
			{//tracking another vehicle
				if ( ent->enemy->client->ps.speed+ent->speed > vel )
				{
					vel = ent->enemy->client->ps.speed+ent->speed;
				}
			}
		}

		VectorCopy( ent->enemy->currentOrigin, org );
		org[2] += (ent->enemy->mins[2] + ent->enemy->maxs[2]) * 0.5f;

		if ( ent->enemy->client )
		{
			switch( ent->enemy->client->NPC_class )
			{
			case CLASS_ATST:
				org[2] += 80;
				break;
			case CLASS_MARK1:
				org[2] += 40;
				break;
			case CLASS_PROBE:
				org[2] += 60;
				break;
			default:
				break;
			}
			if ( !TIMER_Done( ent->enemy, "flee" ) )
			{
				TIMER_Set( ent->enemy, "rocketChasing", 500 );
			}
		}

		VectorSubtract( org, ent->currentOrigin, targetdir );
		VectorNormalize( targetdir );

		// Now the rocket can't do a 180 in space, so we'll limit the turn to about 45 degrees.
		dot = DotProduct( targetdir, ent->movedir );

		// a dot of 1.0 means right-on-target.
		if ( dot < 0.0f )
		{	
			// Go in the direction opposite, start a 180.
			CrossProduct( ent->movedir, up, right );
			dot2 = DotProduct( targetdir, right );

			if ( dot2 > 0 )
			{	
				// Turn 45 degrees right.
				VectorMA( ent->movedir, 0.3f*newDirMult, right, newdir );
			}
			else
			{	
				// Turn 45 degrees left.
				VectorMA(ent->movedir, -0.3f*newDirMult, right, newdir);
			}

			// Yeah we've adjusted horizontally, but let's split the difference vertically, so we kinda try to move towards it.
			newdir[2] = ( (targetdir[2]*newDirMult) + (ent->movedir[2]*oldDirMult) ) * 0.5;

			// slowing down coupled with fairly tight turns can lead us to orbit an enemy..looks bad so don't do it!
//			vel *= 0.5f;
		}
		else if ( dot < 0.70f )
		{	
			// Still a bit off, so we turn a bit softer
			VectorMA( ent->movedir, 0.5f*newDirMult, targetdir, newdir );
		}
		else
		{	
			// getting close, so turn a bit harder
			VectorMA( ent->movedir, 0.9f*newDirMult, targetdir, newdir );
		}

		// add crazy drunkenness
		for ( int i = 0; i < 3; i++ )
		{
			newdir[i] += crandom() * ent->random * 0.25f;
		}

		// decay the randomness
		ent->random *= 0.9f;

		if ( ent->enemy->client
			&& ent->enemy->client->ps.groundEntityNum != ENTITYNUM_NONE )
		{//tracking a client who's on the ground, aim at the floor...?
			// Try to crash into the ground if we get close enough to do splash damage
			float dis = Distance( ent->currentOrigin, org );

			if ( dis < 128 )
			{
				// the closer we get, the more we push the rocket down, heh heh.
				newdir[2] -= (1.0f - (dis / 128.0f)) * 0.6f;
			}
		}

		VectorNormalize( newdir );

		VectorScale( newdir, vel * 0.5f, ent->s.pos.trDelta );
		VectorCopy( newdir, ent->movedir );
		SnapVector( ent->s.pos.trDelta );			// save net bandwidth
		VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
		ent->s.pos.trTime = level.time;
	}

	ent->nextthink = level.time + ROCKET_ALT_THINK_TIME;	// Nothing at all spectacular happened, continue.
	return;
}
Ejemplo n.º 9
0
/*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST
Any brush that you want to explode or break apart.  If you want an
ex0plosion, set dmg and it will do a radius explosion of that amount
at the center of the bursh.

If targeted it will not be shootable.

health defaults to 100.

mass defaults to 75.  This determines how much debris is emitted when
it explodes.  You get one large chunk per 100 of mass (up to 8) and
one small chunk per 25 of mass (up to 16).  So 800 gives the most.
*/
void func_explosive_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
	vec3_t	origin;
	vec3_t	chunkorigin;
	vec3_t	size;
	int		count;
	int		mass;

	// bmodel origins are (0 0 0), we need to adjust that here
	VectorScale (self->size, 0.5, size);
	VectorAdd (self->absmin, size, origin);
	VectorCopy (origin, self->s.origin);

	self->takedamage = DAMAGE_NO;

	if (self->dmg)
		T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE);

	VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity);
	VectorNormalize (self->velocity);
	VectorScale (self->velocity, 150, self->velocity);

	// start chunks towards the center
	VectorScale (size, 0.5, size);

	mass = self->mass;
	if (!mass)
		mass = 75;

	// big chunks
	if (mass >= 100)
	{
		count = mass / 100;
		if (count > 8)
			count = 8;
		while(count--)
		{
			chunkorigin[0] = origin[0] + crandom() * size[0];
			chunkorigin[1] = origin[1] + crandom() * size[1];
			chunkorigin[2] = origin[2] + crandom() * size[2];
			ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin);
		}
	}

	// small chunks
	count = mass / 25;
	if (count > 16)
		count = 16;
	while(count--)
	{
		chunkorigin[0] = origin[0] + crandom() * size[0];
		chunkorigin[1] = origin[1] + crandom() * size[1];
		chunkorigin[2] = origin[2] + crandom() * size[2];
		ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin);
	}

	G_UseTargets (self, attacker);

	if (self->dmg)
		BecomeExplosion1 (self);
	else
		G_FreeEdict (self);
}
Ejemplo n.º 10
0
void soldier_fire (edict_t *self, int flash_number)
{
	vec3_t	start;
	vec3_t	forward, right, up;
	vec3_t	aim;
	vec3_t	dir;
	vec3_t	end;
	float	r, u;
	int		flash_index;

	if ((self->s.skinnum % 6) < 2)
		flash_index = blaster_flash[flash_number];
	else if ((self->s.skinnum % 6) < 4)
		flash_index = shotgun_flash[flash_number];
	else
		flash_index = machinegun_flash[flash_number];

	AngleVectors (self->s.angles, forward, right, NULL);
	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);

	if (flash_number == 5 || flash_number == 6)
	{
		VectorCopy (forward, aim);
	}
	else
	{
		VectorCopy (self->enemy->s.origin, end);
		end[2] += self->enemy->viewheight;

		// Lazarus fog reduction of accuracy
		if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
		{
			end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
			end[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
		}
		
		VectorSubtract (end, start, aim);
		// Lazarus: Accuracy is skill level dependent
		if(skill->value < 3)
		{
			vectoangles (aim, dir);
			AngleVectors (dir, forward, right, up);

			r = crandom()*(1000 - 333*skill->value);
			u = crandom()*(500 - 167*skill->value);
			VectorMA (start, 8192, forward, end);
			VectorMA (end, r, right, end);
			VectorMA (end, u, up, end);

			VectorSubtract (end, start, aim);
		}
		VectorNormalize (aim);
	}

	if ((self->s.skinnum % 6) <= 1)
	{
		// Lazarus: make bolt speed skill level dependent
		monster_fire_blaster (self, start, aim, 5, 600 + 100*skill->value, flash_index, EF_BLASTER, BLASTER_ORANGE);
	}
	else if ((self->s.skinnum % 6) <= 3)
	{
		monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
	}
	else
	{
		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;

		monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);

		if (level.time >= self->monsterinfo.pausetime)
			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
		else
			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
	}
}
Ejemplo n.º 11
0
static qboolean CG_RainParticleGenerate( cg_atmosphericParticle_t *particle, vec3_t currvec, float currweight )
{
	// Attempt to 'spot' a raindrop somewhere below a sky texture.

	float angle, distance;
	float groundHeight, skyHeight;
//	int msec = trap_Milliseconds();

//	n_generatetime++;
	
	angle = random() * 2*M_PI;
	distance = 20 + MAX_ATMOSPHERIC_DISTANCE * random();

	particle->pos[0] = cg.refdef_current->vieworg[0] + sin(angle) * distance;
	particle->pos[1] = cg.refdef_current->vieworg[1] + cos(angle) * distance;
	
	// ydnar: choose a spawn point randomly between sky and ground
	skyHeight = BG_GetSkyHeightAtPoint( particle->pos );
	if( skyHeight == MAX_ATMOSPHERIC_HEIGHT )
		return qfalse;
	groundHeight = BG_GetSkyGroundHeightAtPoint( particle->pos );
	if( groundHeight >= skyHeight )
		return qfalse;
	particle->pos[2] = groundHeight + random() * (skyHeight - groundHeight);

	// make sure it doesn't fall from too far cause it then will go over our heads ('lower the ceiling')
	if( cg_atmFx.baseHeightOffset > 0 ) {
		if( particle->pos[2] - cg.refdef_current->vieworg[2] > cg_atmFx.baseHeightOffset ) {
			particle->pos[2] = cg.refdef_current->vieworg[2] + cg_atmFx.baseHeightOffset;

			if( particle->pos[2] < groundHeight ) {
				return qfalse;
			}
		}
	}
	
	// ydnar: rain goes in bursts
	{
		float		maxActiveDrops;
		
		// every 10 seconds allow max raindrops
		maxActiveDrops = 0.50 * cg_atmFx.numDrops + 0.001 * cg_atmFx.numDrops * (10000 - (cg.time % 10000));
		if( cg_atmFx.oldDropsActive > maxActiveDrops )
			return qfalse;
	}
	
	CG_SetParticleActive( particle, ACT_FALLING );
	particle->colour[0] = 0.6 + 0.2 * random() * 0xFF;
	particle->colour[1] = 0.6 + 0.2 * random() * 0xFF;
	particle->colour[2] = 0.6 + 0.2 * random() * 0xFF;
	VectorCopy( currvec, particle->delta );
	particle->delta[2] += crandom() * 100;
	VectorCopy( particle->delta, particle->deltaNormalized );
	VectorNormalizeFast( particle->deltaNormalized );
	particle->height = ATMOSPHERIC_RAIN_HEIGHT + crandom() * 100;
	particle->weight = currweight;
	particle->effectshader = &cg_atmFx.effectshaders[0];
//	particle->effectshader = &cg_atmFx.effectshaders[ (int) (random() * ( cg_atmFx.numEffectShaders - 1 )) ];

//	generatetime += trap_Milliseconds() - msec;
	return( qtrue );
}
Ejemplo n.º 12
0
void FireTotem_think(edict_t *self, edict_t *caster)
{
	int talentLevel;
	float chance;
	edict_t *target = NULL;

	//Totem should not work underwater (gee I wonder why).
	if(!self->waterlevel)
	{
		//Talent: Volcanic
		talentLevel = getTalentLevel(caster, TALENT_VOLCANIC);
		chance = 0.02 * talentLevel;

		//Find players in radius and attack them.
		while ((target = findclosestradius(target, self->s.origin, TOTEM_MAX_RANGE)) != NULL)
		{
			if (G_ValidTarget(self, target, true) && (self->s.origin[2]+64>target->s.origin[2]))
			{
				vec3_t forward, end;
				int damage = FIRETOTEM_DAMAGE_BASE + self->monsterinfo.level * FIRETOTEM_DAMAGE_MULT;
				int count = 10 + self->monsterinfo.level;
				int speed = 600;
				float	val, dist;
				qboolean fireball=false;

				// copy target location
				G_EntMidPoint(target, end);

				// calculate distance to target
				dist = distance(end, self->s.origin);

				// move our target point based on projectile and enemy velocity
				VectorMA(end, (float)dist/speed, target->velocity, end);

				//Talent: Volcanic - chance to shoot a fireball
				if (talentLevel > 0 && chance > random())
					fireball = true;

				// aim up
				if (fireball)
					val = ((dist/2048)*(dist/2048)*2048) + (end[2]-self->s.origin[2]);//4.4
				else
					val = ((dist/512)*(dist/512)*512) + (end[2]-self->s.origin[2]);
				if (val < 0)
					val = 0;
				end[2] += val;

				// calculate direction vector to target
				VectorSubtract(end, self->s.origin, forward);
				VectorNormalize(forward);
				
				// don't fire in a perfectly straight line
				forward[1] += 0.05*crandom(); 

				// spawn flames
				if (fireball)
					fire_fireball(self, self->s.origin, forward, 200, 125, 600, 5, 20);//4.4
				else
					ThrowFlame(self, self->s.origin, forward, distance(self->s.origin, target->s.origin), speed, damage, GetRandom(2, 4));
				
				self->lastsound = level.framenum;

				// refire delay
				self->delay = level.time + FRAMETIME;
			}
		}
	}

}
Ejemplo n.º 13
0
void NPC_BSGM_Attack( void )
{
	//Don't do anything if we're hurt
	if ( NPC->painDebounceTime > level.time )
	{
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

#if 0
	//FIXME: if killed enemy, use victory anim
	if ( NPC->enemy && NPC->enemy->health <= 0 
		&& !NPC->enemy->s.number )
	{//my enemy is dead
		if ( NPC->client->ps.torsoAnim == BOTH_STAND2TO1 )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				G_AddVoiceEvent( NPC, Q_irand( EV_VICTORY1, EV_VICTORY3 ), 3000 );
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_TRIUMPHANT1START, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer += 500;
				NPC->client->ps.torsoTimer += 500;
			}
		}
		else if ( NPC->client->ps.torsoAnim == BOTH_TRIUMPHANT1START )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_TRIUMPHANT1STARTGESTURE, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer += 500;
				NPC->client->ps.torsoTimer += 500;
			}
		}
		else if ( NPC->client->ps.torsoAnim == BOTH_TRIUMPHANT1STARTGESTURE )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_TRIUMPHANT1STOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer += 500;
				NPC->client->ps.torsoTimer += 500;
			}
		}
		else if ( NPC->client->ps.torsoAnim == BOTH_TRIUMPHANT1STOP )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_STAND1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer = -1;
				NPC->client->ps.torsoTimer = -1;
			}
		}
		else if ( NPC->wait )
		{
			if ( TIMER_Done( NPC, "gloatTime" ) )
			{
				GM_StartGloat();
			}
			else if ( DistanceHorizontalSquared( NPC->client->renderInfo.eyePoint, NPC->enemy->r.currentOrigin ) > 4096 && (NPCInfo->scriptFlags&SCF_CHASE_ENEMIES) )//64 squared
			{
				NPCInfo->goalEntity = NPC->enemy;
				GM_Move();
			}
			else
			{//got there
				GM_StartGloat();
			}
		}
		NPC_FaceEnemy( qtrue );
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}
#endif

	//If we don't have an enemy, just idle
	if ( NPC_CheckEnemyExt(qfalse) == qfalse || !NPC->enemy )
	{
		NPC->enemy = NULL;
		NPC_BSGM_Patrol();
		return;
	}

	enemyLOS4 = enemyCS4 = qfalse;
	move4 = qtrue;
	faceEnemy4 = qfalse;
	shoot4 = qfalse;
	hitAlly4 = qfalse;
	VectorClear( impactPos4 );
	enemyDist4 = DistanceSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );

	//if ( NPC->client->ps.torsoAnim == BOTH_ATTACK4 ||
	//	NPC->client->ps.torsoAnim == BOTH_ATTACK5 )
	if (0)
	{
		shoot4 = qfalse;
		if ( TIMER_Done( NPC, "smackTime" ) && !NPCInfo->blockedDebounceTime )
		{//time to smack
			//recheck enemyDist4 and InFront
			if ( enemyDist4 < MELEE_DIST_SQUARED && InFront( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, 0.3f ) )
			{
				vec3_t	smackDir;
				VectorSubtract( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, smackDir );
				smackDir[2] += 30;
				VectorNormalize( smackDir );
				//hurt them
				G_Sound( NPC->enemy, CHAN_AUTO, G_SoundIndex( "sound/weapons/galak/skewerhit.wav" ) );
				G_Damage( NPC->enemy, NPC, NPC, smackDir, NPC->r.currentOrigin, (g_spskill.integer+1)*Q_irand( 5, 10), DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK, MOD_CRUSH ); 
				if ( NPC->client->ps.torsoAnim == BOTH_ATTACK4 )
				{//smackdown
					int knockAnim = BOTH_KNOCKDOWN1;
					if ( BG_CrouchAnim( NPC->enemy->client->ps.legsAnim ) )
					{//knockdown from crouch
						knockAnim = BOTH_KNOCKDOWN4;
					}
					//throw them
					smackDir[2] = 1;
					VectorNormalize( smackDir );
					G_Throw( NPC->enemy, smackDir, 50 );
					NPC_SetAnim( NPC->enemy, SETANIM_BOTH, knockAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				}
				else
				{//uppercut
					//throw them
					G_Throw( NPC->enemy, smackDir, 100 );
					//make them backflip
					NPC_SetAnim( NPC->enemy, SETANIM_BOTH, BOTH_KNOCKDOWN5, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				}
				//done with the damage
				NPCInfo->blockedDebounceTime = 1;
			}
		}
	}
	else if ( NPC->lockCount ) //already shooting laser
	{//sometimes use the laser beam attack, but only after he's taken down our generator
		shoot4 = qfalse;
		if ( NPC->lockCount == 1 )
		{//charging up
			if ( TIMER_Done( NPC, "beamDelay" ) )
			{//time to start the beam
				int laserAnim;
				//if ( Q_irand( 0, 1 ) )
				if (1)
				{
					laserAnim = BOTH_ATTACK2;
				}
				/*
				else
				{
					laserAnim = BOTH_ATTACK7;
				}
				*/
				NPC_SetAnim( NPC, SETANIM_BOTH, laserAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoTimer + Q_irand( 1000, 3000 ) );
				//turn on beam effect
				NPC->lockCount = 2;
				G_PlayEffectID( G_EffectIndex("galak/trace_beam"), NPC->r.currentOrigin, vec3_origin );
				NPC->s.loopSound = G_SoundIndex( "sound/weapons/galak/lasercutting.wav" );
				if ( !NPCInfo->coverTarg )
				{//for moving looping sound at end of trace
					NPCInfo->coverTarg = G_Spawn();
					if ( NPCInfo->coverTarg )
					{
						G_SetOrigin( NPCInfo->coverTarg, NPC->client->renderInfo.muzzlePoint );
						NPCInfo->coverTarg->r.svFlags |= SVF_BROADCAST;
						NPCInfo->coverTarg->s.loopSound = G_SoundIndex( "sound/weapons/galak/lasercutting.wav" );
					}
				}
			}
		}
		else
		{//in the actual attack now
			if ( NPC->client->ps.torsoTimer <= 0 )
			{//attack done!
				NPC->lockCount = 0;
				G_FreeEntity( NPCInfo->coverTarg );
				NPC->s.loopSound = 0;
#if 0
				NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_DROPWEAP2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
#endif
				TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoTimer );
			}
			else
			{//attack still going
				//do the trace and damage
				trace_t	trace;
				vec3_t	end, mins={-3,-3,-3}, maxs={3,3,3};
				VectorMA( NPC->client->renderInfo.muzzlePoint, 1024, NPC->client->renderInfo.muzzleDir, end );
				trap_Trace( &trace, NPC->client->renderInfo.muzzlePoint, mins, maxs, end, NPC->s.number, MASK_SHOT );
				if ( trace.allsolid || trace.startsolid )
				{//oops, in a wall
					if ( NPCInfo->coverTarg )
					{
						G_SetOrigin( NPCInfo->coverTarg, NPC->client->renderInfo.muzzlePoint );
					}
				}
				else
				{//clear
					if ( trace.fraction < 1.0f )
					{//hit something
						gentity_t *traceEnt = &g_entities[trace.entityNum];
						if ( traceEnt && traceEnt->takedamage )
						{//damage it
							G_SoundAtLoc( trace.endpos, CHAN_AUTO, G_SoundIndex( "sound/weapons/galak/laserdamage.wav" ) );
							G_Damage( traceEnt, NPC, NPC, NPC->client->renderInfo.muzzleDir, trace.endpos, 10, 0, MOD_UNKNOWN );
						}
					}
					if ( NPCInfo->coverTarg )
					{
						G_SetOrigin( NPCInfo->coverTarg, trace.endpos );
					}
					if ( !Q_irand( 0, 5 ) )
					{
						G_SoundAtLoc( trace.endpos, CHAN_AUTO, G_SoundIndex( "sound/weapons/galak/laserdamage.wav" ) );
					}
				}
			}
		}
	}
	else 
	{//Okay, we're not in a special attack, see if we should switch weapons or start a special attack
		/*
		if ( NPC->s.weapon == WP_REPEATER 
			&& !(NPCInfo->scriptFlags & SCF_ALT_FIRE)//using rapid-fire
			&& NPC->enemy->s.weapon == WP_SABER //enemy using saber
			&& NPC->client && (NPC->client->ps.saberEventFlags&SEF_DEFLECTED)
			&& !Q_irand( 0, 50 ) )
		{//he's deflecting my shots, switch to the laser or the lob fire for a while
			TIMER_Set( NPC, "noRapid", Q_irand( 2000, 6000 ) );
			NPCInfo->scriptFlags |= SCF_ALT_FIRE;
			NPC->alt_fire = qtrue;
			if ( NPC->locationDamage[HL_GENERIC1] > GENERATOR_HEALTH && (Q_irand( 0, 1 )||enemyDist4 < MAX_LOB_DIST_SQUARED) )
			{//shield down, use laser
				NPC_GM_StartLaser();
			}
		}
		else*/
		if (// !NPC->client->ps.powerups[PW_GALAK_SHIELD] 
			1 //rwwFIXMEFIXME: just act like the shield is down til the effects and stuff are done
			&& enemyDist4 < MELEE_DIST_SQUARED 
			&& InFront( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, 0.3f ) 
			&& NPC->enemy->localAnimIndex <= 1 )//within 80 and in front
		{//our shield is down, and enemy within 80, if very close, use melee attack to slap away
			if ( TIMER_Done( NPC, "attackDelay" ) )
			{
				//animate me
				int swingAnim = BOTH_ATTACK1;
#if 0
				if ( NPC->locationDamage[HL_GENERIC1] > GENERATOR_HEALTH )
				{//generator down, use random melee
					swingAnim = Q_irand( BOTH_ATTACK4, BOTH_ATTACK5 );//smackdown or uppercut
				}
				else
				{//always knock-away
					swingAnim = BOTH_ATTACK5;//uppercut
				}
#endif
				//FIXME: swing sound
				NPC_SetAnim( NPC, SETANIM_BOTH, swingAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoTimer + Q_irand( 1000, 3000 ) );
				//delay the hurt until the proper point in the anim
				TIMER_Set( NPC, "smackTime", 600 );
				NPCInfo->blockedDebounceTime = 0;
				//FIXME: say something?
			}
		}
		else if ( !NPC->lockCount && NPC->locationDamage[HL_GENERIC1] > GENERATOR_HEALTH
			&& TIMER_Done( NPC, "attackDelay" )
			&& InFront( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, 0.3f )
			&& ((!Q_irand( 0, 10*(2-g_spskill.integer))&& enemyDist4 > MIN_LOB_DIST_SQUARED&& enemyDist4 < MAX_LOB_DIST_SQUARED)
				||(!TIMER_Done( NPC, "noLob" )&&!TIMER_Done( NPC, "noRapid" ))) 
			&& NPC->enemy->s.weapon != WP_TURRET )
		{//sometimes use the laser beam attack, but only after he's taken down our generator
			shoot4 = qfalse;
			NPC_GM_StartLaser();
		}
		else if ( enemyDist4 < MIN_LOB_DIST_SQUARED 
			&& (NPC->enemy->s.weapon != WP_TURRET || Q_stricmp( "PAS", NPC->enemy->classname ))
			&& TIMER_Done( NPC, "noRapid" ) )//256
		{//enemy within 256
			if ( (NPC->client->ps.weapon == WP_REPEATER) && (NPCInfo->scriptFlags & SCF_ALT_FIRE) )
			{//shooting an explosive, but enemy too close, switch to primary fire
				NPCInfo->scriptFlags &= ~SCF_ALT_FIRE;
				NPC->alt_fire = qfalse;
				//FIXME: use weap raise & lower anims
				NPC_ChangeWeapon( WP_REPEATER );
			}
		}
		else if ( (enemyDist4 > MAX_LOB_DIST_SQUARED || (NPC->enemy->s.weapon == WP_TURRET && !Q_stricmp( "PAS", NPC->enemy->classname )))
			&& TIMER_Done( NPC, "noLob" ) )//448
		{//enemy more than 448 away and we are ready to try lob fire again
			if ( (NPC->client->ps.weapon == WP_REPEATER) && !(NPCInfo->scriptFlags & SCF_ALT_FIRE) )
			{//enemy far enough away to use lobby explosives
				NPCInfo->scriptFlags |= SCF_ALT_FIRE;
				NPC->alt_fire = qtrue;
				//FIXME: use weap raise & lower anims
				NPC_ChangeWeapon( WP_REPEATER );
			}
		}
	}

	//can we see our target?
	if ( NPC_ClearLOS4( NPC->enemy ) )
	{
		NPCInfo->enemyLastSeenTime = level.time;//used here for aim debouncing, not always a clear LOS
		enemyLOS4 = qtrue;

		if ( NPC->client->ps.weapon == WP_NONE )
		{
			enemyCS4 = qfalse;//not true, but should stop us from firing
			NPC_AimAdjust( -1 );//adjust aim worse longer we have no weapon
		}
		else
		{//can we shoot our target?
			if ( ((NPC->client->ps.weapon == WP_REPEATER && (NPCInfo->scriptFlags&SCF_ALT_FIRE))) && enemyDist4 < MIN_LOB_DIST_SQUARED )//256
			{
				enemyCS4 = qfalse;//not true, but should stop us from firing
				hitAlly4 = qtrue;//us!
				//FIXME: if too close, run away!
			}
			else
			{
				int hit = NPC_ShotEntity( NPC->enemy, impactPos4 );
				gentity_t *hitEnt = &g_entities[hit];
				if ( hit == NPC->enemy->s.number 
					|| ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPC->client->enemyTeam )
					|| ( hitEnt && hitEnt->takedamage ) )
				{//can hit enemy or will hit glass or other breakable, so shoot anyway
					enemyCS4 = qtrue;
					NPC_AimAdjust( 2 );//adjust aim better longer we have clear shot at enemy
					VectorCopy( NPC->enemy->r.currentOrigin, NPCInfo->enemyLastSeenLocation );
				}
				else
				{//Hmm, have to get around this bastard
					NPC_AimAdjust( 1 );//adjust aim better longer we can see enemy
					if ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPC->client->playerTeam )
					{//would hit an ally, don't fire!!!
						hitAlly4 = qtrue;
					}
					else
					{//Check and see where our shot *would* hit... if it's not close to the enemy (within 256?), then don't fire
					}
				}
			}
		}
	}
	else if ( trap_InPVS( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) )
	{
		int hit;
		gentity_t *hitEnt;

		if ( TIMER_Done( NPC, "talkDebounce" ) && !Q_irand( 0, 10 ) )
		{
			if ( NPCInfo->enemyCheckDebounceTime < 8 )
			{
				int speech = -1;
				switch( NPCInfo->enemyCheckDebounceTime )
				{
				case 0:
				case 1:
				case 2:
					speech = EV_CHASE1 + NPCInfo->enemyCheckDebounceTime;
					break;
				case 3:
				case 4:
				case 5:
					speech = EV_COVER1 + NPCInfo->enemyCheckDebounceTime-3;
					break;
				case 6:
				case 7:
					speech = EV_ESCAPING1 + NPCInfo->enemyCheckDebounceTime-6;
					break;
				}
				NPCInfo->enemyCheckDebounceTime++;
				if ( speech != -1 )
				{
					G_AddVoiceEvent( NPC, speech, Q_irand( 3000, 5000 ) );
					TIMER_Set( NPC, "talkDebounce", Q_irand( 5000, 7000 ) );
				}
			}
		}

		NPCInfo->enemyLastSeenTime = level.time;

		hit = NPC_ShotEntity( NPC->enemy, impactPos4 );
		hitEnt = &g_entities[hit];
		if ( hit == NPC->enemy->s.number 
			|| ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPC->client->enemyTeam )
			|| ( hitEnt && hitEnt->takedamage ) )
		{//can hit enemy or will hit glass or other breakable, so shoot anyway
			enemyCS4 = qtrue;
		}
		else
		{
			faceEnemy4 = qtrue;
			NPC_AimAdjust( -1 );//adjust aim worse longer we cannot see enemy
		}
	}

	if ( enemyLOS4 )
	{
		faceEnemy4 = qtrue;
	}
	else
	{
		if ( !NPCInfo->goalEntity )
		{
			NPCInfo->goalEntity = NPC->enemy;
		}
		if ( NPCInfo->goalEntity == NPC->enemy )
		{//for now, always chase the enemy
			move4 = qtrue;
		}
	}
	if ( enemyCS4 )
	{
		shoot4 = qtrue;
		//NPCInfo->enemyCheckDebounceTime = level.time;//actually used here as a last actual LOS
	}
	else
	{
		if ( !NPCInfo->goalEntity )
		{
			NPCInfo->goalEntity = NPC->enemy;
		}
		if ( NPCInfo->goalEntity == NPC->enemy )
		{//for now, always chase the enemy
			move4 = qtrue;
		}
	}

	//Check for movement to take care of
	GM_CheckMoveState();

	//See if we should override shooting decision with any special considerations
	GM_CheckFireState();

	if ( NPC->client->ps.weapon == WP_REPEATER && (NPCInfo->scriptFlags&SCF_ALT_FIRE) && shoot4 && TIMER_Done( NPC, "attackDelay" ) )
	{
		vec3_t	muzzle;
		vec3_t	angles;
		vec3_t	target;
		vec3_t velocity = {0,0,0};
		vec3_t mins = {-REPEATER_ALT_SIZE,-REPEATER_ALT_SIZE,-REPEATER_ALT_SIZE}, maxs = {REPEATER_ALT_SIZE,REPEATER_ALT_SIZE,REPEATER_ALT_SIZE};
		qboolean clearshot;

		CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
		
		VectorCopy( NPC->enemy->r.currentOrigin, target );

		target[0] += flrand( -5, 5 )+(crandom()*(6-NPCInfo->currentAim)*2);
		target[1] += flrand( -5, 5 )+(crandom()*(6-NPCInfo->currentAim)*2);
		target[2] += flrand( -5, 5 )+(crandom()*(6-NPCInfo->currentAim)*2);

		//Find the desired angles
		clearshot = WP_LobFire( NPC, muzzle, target, mins, maxs, MASK_SHOT|CONTENTS_LIGHTSABER, 
			velocity, qtrue, NPC->s.number, NPC->enemy->s.number,
			300, 1100, 1500, qtrue );
		if ( VectorCompare( vec3_origin, velocity ) || (!clearshot&&enemyLOS4&&enemyCS4)  )
		{//no clear lob shot and no lob shot that will hit something breakable
			if ( enemyLOS4 && enemyCS4 && TIMER_Done( NPC, "noRapid" ) )
			{//have a clear straight shot, so switch to primary
				NPCInfo->scriptFlags &= ~SCF_ALT_FIRE;
				NPC->alt_fire = qfalse;
				NPC_ChangeWeapon( WP_REPEATER );
				//keep this weap for a bit
				TIMER_Set( NPC, "noLob", Q_irand( 500, 1000 ) );
			}
			else
			{
				shoot4 = qfalse;
			}
		}
		else
		{
			vectoangles( velocity, angles );

			NPCInfo->desiredYaw		= AngleNormalize360( angles[YAW] );
			NPCInfo->desiredPitch	= AngleNormalize360( angles[PITCH] );

			VectorCopy( velocity, NPC->client->hiddenDir );
			NPC->client->hiddenDist = VectorNormalize ( NPC->client->hiddenDir );
		}
	}
	else if ( faceEnemy4 )
	{//face the enemy
		NPC_FaceEnemy( qtrue );
	}

	if ( !TIMER_Done( NPC, "standTime" ) )
	{
		move4 = qfalse;
	}
	if ( !(NPCInfo->scriptFlags&SCF_CHASE_ENEMIES) )
	{//not supposed to chase my enemies
		if ( NPCInfo->goalEntity == NPC->enemy )
		{//goal is my entity, so don't move
			move4 = qfalse;
		}
	}

	if ( move4 && !NPC->lockCount )
	{//move toward goal
		if ( NPCInfo->goalEntity 
			/*&& NPC->client->ps.legsAnim != BOTH_ALERT1
			&& NPC->client->ps.legsAnim != BOTH_ATTACK2 
			&& NPC->client->ps.legsAnim != BOTH_ATTACK4
			&& NPC->client->ps.legsAnim != BOTH_ATTACK5 
			&& NPC->client->ps.legsAnim != BOTH_ATTACK7*/ )
		{
			move4 = GM_Move();
		}
		else
		{
			move4 = qfalse;
		}
	}

	if ( !TIMER_Done( NPC, "flee" ) )
	{//running away
		faceEnemy4 = qfalse;
	}

	//FIXME: check scf_face_move_dir here?

	if ( !faceEnemy4 )
	{//we want to face in the dir we're running
		if ( !move4 )
		{//if we haven't moved, we should look in the direction we last looked?
			VectorCopy( NPC->client->ps.viewangles, NPCInfo->lastPathAngles );
		}
		if ( move4 )
		{//don't run away and shoot
			NPCInfo->desiredYaw = NPCInfo->lastPathAngles[YAW];
			NPCInfo->desiredPitch = 0;
			shoot4 = qfalse;
		}
	}
	NPC_UpdateAngles( qtrue, qtrue );

	if ( NPCInfo->scriptFlags & SCF_DONT_FIRE )
	{
		shoot4 = qfalse;
	}

	if ( NPC->enemy && NPC->enemy->enemy )
	{
		if ( NPC->enemy->s.weapon == WP_SABER && NPC->enemy->enemy->s.weapon == WP_SABER )
		{//don't shoot at an enemy jedi who is fighting another jedi, for fear of injuring one or causing rogue blaster deflections (a la Obi Wan/Vader duel at end of ANH)
			shoot4 = qfalse;
		}
	}
	//FIXME: don't shoot right away!
	if ( shoot4 )
	{//try to shoot if it's time
		if ( TIMER_Done( NPC, "attackDelay" ) )
		{
			if( !(NPCInfo->scriptFlags & SCF_FIRE_WEAPON) ) // we've already fired, no need to do it again here
			{
				WeaponThink( qtrue );
			}
		}
	}

	//also:
	if ( NPC->enemy->s.weapon == WP_TURRET && !Q_stricmp( "PAS", NPC->enemy->classname ) )
	{//crush turrets
		if ( G_BoundsOverlap( NPC->r.absmin, NPC->r.absmax, NPC->enemy->r.absmin, NPC->enemy->r.absmax ) )
		{//have to do this test because placed turrets are not solid to NPCs (so they don't obstruct navigation)
			//if ( NPC->client->ps.powerups[PW_GALAK_SHIELD] > 0 )
			if (0)
			{
				NPC->client->ps.powerups[PW_BATTLESUIT] = level.time + ARMOR_EFFECT_TIME;
				G_Damage( NPC->enemy, NPC, NPC, NULL, NPC->r.currentOrigin, 100, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN ); 
			}
			else
			{
				G_Damage( NPC->enemy, NPC, NPC, NULL, NPC->r.currentOrigin, 100, DAMAGE_NO_KNOCKBACK, MOD_CRUSH ); 
			}
		}
	}
	else if ( NPCInfo->touchedByPlayer != NULL && NPCInfo->touchedByPlayer == NPC->enemy )
	{//touched enemy
		//if ( NPC->client->ps.powerups[PW_GALAK_SHIELD] > 0 )
		if (0)
		{//zap him!
			vec3_t	smackDir;

			//animate me
#if 0
			NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK6, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
#endif
			TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoTimer );
			TIMER_Set( NPC, "standTime", NPC->client->ps.legsTimer );
			//FIXME: debounce this?
			NPCInfo->touchedByPlayer = NULL;
			//FIXME: some shield effect?
			NPC->client->ps.powerups[PW_BATTLESUIT] = level.time + ARMOR_EFFECT_TIME;

			VectorSubtract( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, smackDir );
			smackDir[2] += 30;
			VectorNormalize( smackDir );
			G_Damage( NPC->enemy, NPC, NPC, smackDir, NPC->r.currentOrigin, (g_spskill.integer+1)*Q_irand( 5, 10), DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN ); 
			//throw them
			G_Throw( NPC->enemy, smackDir, 100 );
			//NPC->enemy->s.powerups |= ( 1 << PW_SHOCKED );
			if ( NPC->enemy->client )
			{
			//	NPC->enemy->client->ps.powerups[PW_SHOCKED] = level.time + 1000;
				NPC->enemy->client->ps.electrifyTime = level.time + 1000;
			}
			//stop any attacks
			ucmd.buttons = 0;
		}
	}

	if ( NPCInfo->movementSpeech < 3 && NPCInfo->blockedSpeechDebounceTime <= level.time )
	{
		if ( NPC->enemy && NPC->enemy->health > 0 && NPC->enemy->painDebounceTime > level.time )
		{
			if ( NPC->enemy->health < 50 && NPCInfo->movementSpeech == 2 )
			{
				G_AddVoiceEvent( NPC, EV_ANGER2, Q_irand( 2000, 4000 ) );
				NPCInfo->movementSpeech = 3;
			}
			else if ( NPC->enemy->health < 75 && NPCInfo->movementSpeech == 1 )
			{
				G_AddVoiceEvent( NPC, EV_ANGER1, Q_irand( 2000, 4000 ) );
				NPCInfo->movementSpeech = 2;
			}
			else if ( NPC->enemy->health < 100 && NPCInfo->movementSpeech == 0 )
			{
				G_AddVoiceEvent( NPC, EV_ANGER3, Q_irand( 2000, 4000 ) );
				NPCInfo->movementSpeech = 1;
			}
		}
	}
}
Ejemplo n.º 14
0
void CG_Chunks( int owner, vec3_t origin, const vec3_t normal, const vec3_t mins, const vec3_t maxs, 
						float speed, int numChunks, material_t chunkType, int customChunk, float baseScale, int customSound = 0 )
{
	localEntity_t	*le;
	refEntity_t		*re;
	vec3_t			dir;
	int				i, j, k;
	int				chunkModel = 0;
	leBounceSound_t	bounce = LEBS_NONE;
	float			r, speedMod = 1.0f;
	qboolean		chunk = qfalse;

	if ( chunkType == MAT_NONE )
	{
		// Well, we should do nothing
		return;
	}

	if ( customSound )
	{
		if ( cgs.sound_precache[customSound] ) 
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.sound_precache[customSound] );
		}
	}
	// Set up our chunk sound info...breaking sounds are done here so they are done once on breaking..some return instantly because the chunks are done with effects instead of models
	switch( chunkType )
	{
	case MAT_GLASS:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.glassChunkSound );
		}
		return;
		break;
	case MAT_GRATE1:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.grateSound );
		}
		return;
		break;
	case MAT_ELECTRICAL:// (sparks)
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgi_S_RegisterSound (va("sound/ambience/spark%d.wav", Q_irand(1, 6))) );
		}
		return;
		break;
	case MAT_DRK_STONE:
	case MAT_LT_STONE:
	case MAT_GREY_STONE:
	case MAT_WHITE_METAL:  // not quite sure what this stuff is supposed to be...it's for Stu
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.rockBreakSound );
			bounce = LEBS_ROCK;
		}
		speedMod = 0.5f; // rock blows up less
		break;
	case MAT_GLASS_METAL:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.glassChunkSound ); // FIXME: should probably have a custom sound
			bounce = LEBS_METAL;
		}
		break;
	case MAT_CRATE1:
	case MAT_CRATE2:
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.crateBreakSound[Q_irand(0,1)] );
		}
		break;
	case MAT_METAL:
	case MAT_METAL2:
	case MAT_METAL3:
	case MAT_ELEC_METAL:// FIXME: maybe have its own sound?
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgs.media.chunkSound );
			bounce = LEBS_METAL;
		}
		speedMod = 0.8f; // metal blows up a bit more
		break;
	case MAT_ROPE:
		/*
		if ( !customSound )
		{
			cgi_S_StartSound( NULL, owner, CHAN_BODY, cgi_S_RegisterSound( "" ));  FIXME:  needs a sound
		}
		*/
		return;
		break;
	}

	if ( baseScale <= 0.0f )
	{
		baseScale = 1.0f;
	}

	// Chunks
	for( i = 0; i < numChunks; i++ )
	{
		if ( customChunk > 0 )
		{
			// Try to use a custom chunk.
			if ( cgs.model_draw[customChunk] )
			{
				chunk = qtrue;
				chunkModel = cgs.model_draw[customChunk];
			}
		}

		if ( !chunk )
		{
			// No custom chunk.  Pick a random chunk type at run-time so we don't get the same chunks
			switch( chunkType )
			{
			case MAT_METAL2: //bluegrey
				chunkModel = cgs.media.chunkModels[CHUNK_METAL2][Q_irand(0, 3)];
				break;
			case MAT_GREY_STONE://gray
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK1][Q_irand(0, 3)];
				break;
			case MAT_LT_STONE: //tan
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK2][Q_irand(0, 3)];
				break;
			case MAT_DRK_STONE://brown
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK3][Q_irand(0, 3)];
				break;
			case MAT_WHITE_METAL:
				chunkModel = cgs.media.chunkModels[CHUNK_WHITE_METAL][Q_irand(0, 3)];
				break;
			case MAT_CRATE1://yellow multi-colored crate chunks
				chunkModel = cgs.media.chunkModels[CHUNK_CRATE1][Q_irand(0, 3)];
				break;
			case MAT_CRATE2://red multi-colored crate chunks
				chunkModel = cgs.media.chunkModels[CHUNK_CRATE2][Q_irand(0, 3)];
				break;
			case MAT_ELEC_METAL:
			case MAT_GLASS_METAL:
			case MAT_METAL://grey
				chunkModel = cgs.media.chunkModels[CHUNK_METAL1][Q_irand(0, 3)];
				break;
			case MAT_METAL3:
				if ( rand() & 1 )
				{
					chunkModel = cgs.media.chunkModels[CHUNK_METAL1][Q_irand(0, 3)];
				}
				else
				{
					chunkModel = cgs.media.chunkModels[CHUNK_METAL2][Q_irand(0, 3)];
				}
				break;
			}
		}

		// It wouldn't look good to throw a bunch of RGB axis models...so make sure we have something to work with.
		if ( chunkModel )
		{
			le = CG_AllocLocalEntity();
			re = &le->refEntity;

			re->hModel = chunkModel;
			le->leType = LE_FRAGMENT;
			le->endTime = cg.time + 1300 + random() * 900;

			// spawn chunk roughly in the bbox of the thing...bias towards center in case thing blowing up doesn't complete fill its bbox.
			for( j = 0; j < 3; j++ )
			{
				r = random() * 0.8f + 0.1f;
				re->origin[j] = ( r * mins[j] + ( 1 - r ) * maxs[j] );
			}
			VectorCopy( re->origin, le->pos.trBase );

			// Move out from center of thing, otherwise you can end up things moving across the brush in an undesirable direction.  Visually looks wrong
			VectorSubtract( re->origin, origin, dir );
			VectorNormalize( dir );
			VectorScale( dir, Q_flrand( speed * 0.5f, speed * 1.25f ) * speedMod, le->pos.trDelta );

			// Angular Velocity
			VectorSet( le->angles.trBase, random() * 360, random() * 360, random() * 360 );

			le->angles.trDelta[0] = crandom();
			le->angles.trDelta[1] = crandom();
			le->angles.trDelta[2] = 0; // don't do roll

			VectorScale( le->angles.trDelta, random() * 600.0f + 200.0f, le->angles.trDelta );

			le->pos.trType = TR_GRAVITY;
			le->angles.trType = TR_LINEAR;
			le->pos.trTime = le->angles.trTime = cg.time;
			le->bounceFactor = 0.2f + random() * 0.2f;
			le->leFlags |= LEF_TUMBLE;
			le->ownerGentNum = owner;
			le->leBounceSoundType = bounce; 

			// Make sure that we have the desired start size set
			le->radius = Q_flrand( baseScale * 0.75f, baseScale * 1.25f );
			re->nonNormalizedAxes = qtrue;
			AxisCopy( axisDefault, re->axis ); // could do an angles to axis, but this is cheaper and works ok
			for( k = 0; k < 3; k++ )
			{
				VectorScale( re->axis[k], le->radius, re->axis[k] );
			}
		}
	}
}
Ejemplo n.º 15
0
void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir)
{
	float	length;
	float	dist;
	float	crittersize;
	vec3_t	angles, forward;
	vec3_t	point;
	cparticle_t	*p;
	int		i;
	
	dist = 0;

	VectorNegate (dir, dir);
	length = VectorLength (dir);
	vectoangles (dir, angles);
	AngleVectors (angles, forward, NULL, NULL);

	crittersize = LARGESIZE;

	if (length)
		dist = length / crittersize;

	if (dist < 1)
		dist = 1;

	VectorCopy (origin, point);

	for (i=0; i<dist; i++)
	{
		VectorMA (point, crittersize, forward, point);	
				
		if (!free_particles)
			return;

		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cg.time;
		p->alpha = 5.0;
		p->alphavel = 0;
		p->roll = 0;

		p->pshader = cgs.media.smokePuffShader;

		// RF, stay around for long enough to expand and dissipate naturally
		if (length)
			p->endtime = cg.time + 4500 + (crandom() * 3500);
		else
			p->endtime = cg.time + 750 + (crandom() * 500);
		
		p->startfade = cg.time;
		
		p->width = LARGESIZE;
		p->height = LARGESIZE;

		// RF, expand while falling
		p->endheight = LARGESIZE*3.0;
		p->endwidth = LARGESIZE*3.0;

		if (!length)
		{
			p->width *= 0.2f;
			p->height *= 0.2f;

			p->endheight = NORMALSIZE;
			p->endwidth = NORMALSIZE;
		}

		p->type = P_SMOKE;

		VectorCopy( point, p->org );
		
		p->vel[0] = crandom()*6;
		p->vel[1] = crandom()*6;
		p->vel[2] = random()*20;

		// RF, add some gravity/randomness
		p->accel[0] = crandom()*3;
		p->accel[1] = crandom()*3;
		p->accel[2] = -PARTICLE_GRAVITY*0.4;

		VectorClear( p->accel );

		p->rotate = qfalse;

		p->roll = rand()%179;
		
		p->alpha = 0.75;
		
	}

	
}
Ejemplo n.º 16
0
void barrel_explode (edict_t *self)
{
	vec3_t	org;
	float	spd;
	vec3_t	save;

	T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_BARREL);

	VectorCopy (self->s.origin, save);
	VectorMA (self->absmin, 0.5, self->size, self->s.origin);

	// a few big chunks
	spd = 1.5 * (float)self->dmg / 200.0;
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris1/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris1/tris.md2", spd, org);

	// bottom corners
	spd = 1.75 * (float)self->dmg / 200.0;
	VectorCopy (self->absmin, org);
	ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
	VectorCopy (self->absmin, org);
	org[0] += self->size[0];
	ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
	VectorCopy (self->absmin, org);
	org[1] += self->size[1];
	ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);
	VectorCopy (self->absmin, org);
	org[0] += self->size[0];
	org[1] += self->size[1];
	ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org);

	// a bunch of little chunks
	spd = 2 * self->dmg / 200;
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);
	org[0] = self->s.origin[0] + crandom() * self->size[0];
	org[1] = self->s.origin[1] + crandom() * self->size[1];
	org[2] = self->s.origin[2] + crandom() * self->size[2];
	ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org);

	VectorCopy (save, self->s.origin);
	if (self->groundentity)
		BecomeExplosion2 (self);
	else
		BecomeExplosion1 (self);
}
Ejemplo n.º 17
0
/*
=====================
CG_AddParticleToScene
=====================
*/
void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha)
{

	vec3_t		point;
	polyVert_t	verts[4];
	float		width;
	float		height;
	float		time, time2;
	float		ratio;
	float		invratio;
	vec3_t		color;
	polyVert_t	TRIverts[3];
	vec3_t		rright2, rup2;

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY
		|| p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
	{// create a front facing polygon
			
		if (p->type != P_WEATHER_FLURRY)
		{
			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
			{
				if (org[2] > p->end)			
				{	
					p->time = cg.time;	
					VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground
									
					p->org[2] = ( p->start + crandom () * 4 );
					
					
					if (p->type == P_BUBBLE_TURBULENT)
					{
						p->vel[0] = crandom() * 4;
						p->vel[1] = crandom() * 4;
					}
				
				}
			}
			else
			{
				if (org[2] < p->end)			
				{	
					p->time = cg.time;	
					VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground
									
					while (p->org[2] < p->end) 
					{
						p->org[2] += (p->start - p->end); 
					}
					
					
					if (p->type == P_WEATHER_TURBULENT)
					{
						p->vel[0] = crandom() * 16;
						p->vel[1] = crandom() * 16;
					}
				
				}
			}
			

			// Rafael snow pvs check
			if (!p->link)
				return;

			p->alpha = 1;
		}
		
		// Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp
		if (Distance( cg.snap->ps.origin, org ) > 1024) {
			return;
		}
		// done.
	
		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
		{
			VectorMA (org, -p->height, vup, point);	
			VectorMA (point, -p->width, vright, point);	
			VectorCopy (point, verts[0].xyz);	
			verts[0].st[0] = 0;	
			verts[0].st[1] = 0;	
			verts[0].modulate[0] = 255;	
			verts[0].modulate[1] = 255;	
			verts[0].modulate[2] = 255;	
			verts[0].modulate[3] = 255 * p->alpha;	

			VectorMA (org, -p->height, vup, point);	
			VectorMA (point, p->width, vright, point);	
			VectorCopy (point, verts[1].xyz);	
			verts[1].st[0] = 0;	
			verts[1].st[1] = 1;	
			verts[1].modulate[0] = 255;	
			verts[1].modulate[1] = 255;	
			verts[1].modulate[2] = 255;	
			verts[1].modulate[3] = 255 * p->alpha;	

			VectorMA (org, p->height, vup, point);	
			VectorMA (point, p->width, vright, point);	
			VectorCopy (point, verts[2].xyz);	
			verts[2].st[0] = 1;	
			verts[2].st[1] = 1;	
			verts[2].modulate[0] = 255;	
			verts[2].modulate[1] = 255;	
			verts[2].modulate[2] = 255;	
			verts[2].modulate[3] = 255 * p->alpha;	

			VectorMA (org, p->height, vup, point);	
			VectorMA (point, -p->width, vright, point);	
			VectorCopy (point, verts[3].xyz);	
			verts[3].st[0] = 1;	
			verts[3].st[1] = 0;	
			verts[3].modulate[0] = 255;	
			verts[3].modulate[1] = 255;	
			verts[3].modulate[2] = 255;	
			verts[3].modulate[3] = 255 * p->alpha;	
		}
		else
		{
			VectorMA (org, -p->height, vup, point);	
			VectorMA (point, -p->width, vright, point);	
			VectorCopy( point, TRIverts[0].xyz );
			TRIverts[0].st[0] = 1;
			TRIverts[0].st[1] = 0;
			TRIverts[0].modulate[0] = 255;
			TRIverts[0].modulate[1] = 255;
			TRIverts[0].modulate[2] = 255;
			TRIverts[0].modulate[3] = 255 * p->alpha;	

			VectorMA (org, p->height, vup, point);	
			VectorMA (point, -p->width, vright, point);	
			VectorCopy (point, TRIverts[1].xyz);	
			TRIverts[1].st[0] = 0;
			TRIverts[1].st[1] = 0;
			TRIverts[1].modulate[0] = 255;
			TRIverts[1].modulate[1] = 255;
			TRIverts[1].modulate[2] = 255;
			TRIverts[1].modulate[3] = 255 * p->alpha;	

			VectorMA (org, p->height, vup, point);	
			VectorMA (point, p->width, vright, point);	
			VectorCopy (point, TRIverts[2].xyz);	
			TRIverts[2].st[0] = 0;
			TRIverts[2].st[1] = 1;
			TRIverts[2].modulate[0] = 255;
			TRIverts[2].modulate[1] = 255;
			TRIverts[2].modulate[2] = 255;
			TRIverts[2].modulate[3] = 255 * p->alpha;	
		}
	
	}
	else if (p->type == P_SPRITE)
	{
		vec3_t	rr, ru;
		vec3_t	rotate_ang;

#ifdef WOLF_PARTICLES
		VectorSet (color, 1.0, 1.0, 1.0);
#else
		VectorSet (color, 1.0, 1.0, 0.5);
#endif
		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		if (p->roll) {
			vectoangles( cg.refdef.viewaxis[0], rotate_ang );
			rotate_ang[ROLL] += p->roll;
			AngleVectors ( rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA (org, -height, ru, point);	
			VectorMA (point, -width, rr, point);	
		} else {
			VectorMA (org, -height, vup, point);	
			VectorMA (point, -width, vright, point);	
		}
		VectorCopy (point, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255;	
		verts[0].modulate[1] = 255;	
		verts[0].modulate[2] = 255;	
		verts[0].modulate[3] = 255;

		if (p->roll) {
			VectorMA (point, 2*height, ru, point);	
		} else {
			VectorMA (point, 2*height, vup, point);	
		}
		VectorCopy (point, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255;	
		verts[1].modulate[1] = 255;	
		verts[1].modulate[2] = 255;	
		verts[1].modulate[3] = 255;	

		if (p->roll) {
			VectorMA (point, 2*width, rr, point);	
		} else {
			VectorMA (point, 2*width, vright, point);	
		}
		VectorCopy (point, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255;	
		verts[2].modulate[1] = 255;	
		verts[2].modulate[2] = 255;	
		verts[2].modulate[3] = 255;	

		if (p->roll) {
			VectorMA (point, -2*height, ru, point);	
		} else {
			VectorMA (point, -2*height, vup, point);	
		}
		VectorCopy (point, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255;	
		verts[3].modulate[1] = 255;	
		verts[3].modulate[2] = 255;	
		verts[3].modulate[3] = 255;	
	}
	else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT)
	{// create a front rotating facing polygon

		if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) {
			return;
		}

		if (p->color == BLOODRED)
			VectorSet (color, 0.22f, 0.0f, 0.0f);
		else if (p->color == GREY75)
		{
			float	len;
			float	greyit;
			float	val;
			len = Distance (cg.snap->ps.origin, org);
			if (!len)
				len = 1;

			val = 4096/len;
			greyit = 0.25 * val;
			if (greyit > 0.5)
				greyit = 0.5;

			VectorSet (color, greyit, greyit, greyit);
		}
		else
			VectorSet (color, 1.0, 1.0, 1.0);

		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;
		
		if (cg.time > p->startfade)
		{
			invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) );

			if (p->color == EMISIVEFADE)
			{
				float fval;
				fval = (invratio * invratio);
				if (fval < 0)
					fval = 0;
				VectorSet (color, fval , fval , fval );
			}
			invratio *= p->alpha;
		}
		else 
			invratio = 1 * p->alpha;

		if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO )
			invratio = 1;

		if (invratio > 1)
			invratio = 1;
	
		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		if (p->type != P_SMOKE_IMPACT)
		{
			vec3_t temp;

			vectoangles (rforward, temp);
			p->accumroll += p->roll;
			temp[ROLL] += p->accumroll * 0.1;
			AngleVectors ( temp, NULL, rright2, rup2);
		}
		else
		{
			VectorCopy (rright, rright2);
			VectorCopy (rup, rup2);
		}
		
		if (p->rotate)
		{
			VectorMA (org, -height, rup2, point);	
			VectorMA (point, -width, rright2, point);	
		}
		else
		{
			VectorMA (org, -p->height, vup, point);	
			VectorMA (point, -p->width, vright, point);	
		}
		VectorCopy (point, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255 * color[0];	
		verts[0].modulate[1] = 255 * color[1];	
		verts[0].modulate[2] = 255 * color[2];	
		verts[0].modulate[3] = 255 * invratio;	

		if (p->rotate)
		{
			VectorMA (org, -height, rup2, point);	
			VectorMA (point, width, rright2, point);	
		}
		else
		{
			VectorMA (org, -p->height, vup, point);	
			VectorMA (point, p->width, vright, point);	
		}
		VectorCopy (point, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255 * color[0];	
		verts[1].modulate[1] = 255 * color[1];	
		verts[1].modulate[2] = 255 * color[2];	
		verts[1].modulate[3] = 255 * invratio;	

		if (p->rotate)
		{
			VectorMA (org, height, rup2, point);	
			VectorMA (point, width, rright2, point);	
		}
		else
		{
			VectorMA (org, p->height, vup, point);	
			VectorMA (point, p->width, vright, point);	
		}
		VectorCopy (point, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255 * color[0];	
		verts[2].modulate[1] = 255 * color[1];	
		verts[2].modulate[2] = 255 * color[2];	
		verts[2].modulate[3] = 255 * invratio;	

		if (p->rotate)
		{
			VectorMA (org, height, rup2, point);	
			VectorMA (point, -width, rright2, point);	
		}
		else
		{
			VectorMA (org, p->height, vup, point);	
			VectorMA (point, -p->width, vright, point);	
		}
		VectorCopy (point, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255 * color[0];	
		verts[3].modulate[1] = 255 * color[1];	
		verts[3].modulate[2] = 255 * color[2];	
		verts[3].modulate[3] = 255  * invratio;	
		
	}
	else if (p->type == P_BLEED)
	{
		vec3_t	rr, ru;
		vec3_t	rotate_ang;
		float	alpha;

		alpha = p->alpha;
		
		if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO )
			alpha = 1;

		if (p->roll) 
		{
			vectoangles( cg.refdef.viewaxis[0], rotate_ang );
			rotate_ang[ROLL] += p->roll;
			AngleVectors ( rotate_ang, NULL, rr, ru);
		}
		else
		{
			VectorCopy (vup, ru);
			VectorCopy (vright, rr);
		}

		VectorMA (org, -p->height, ru, point);	
		VectorMA (point, -p->width, rr, point);	
		VectorCopy (point, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 111;	
		verts[0].modulate[1] = 19;	
		verts[0].modulate[2] = 9;	
		verts[0].modulate[3] = 255 * alpha;	

		VectorMA (org, -p->height, ru, point);	
		VectorMA (point, p->width, rr, point);	
		VectorCopy (point, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 111;	
		verts[1].modulate[1] = 19;	
		verts[1].modulate[2] = 9;	
		verts[1].modulate[3] = 255 * alpha;	

		VectorMA (org, p->height, ru, point);	
		VectorMA (point, p->width, rr, point);	
		VectorCopy (point, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 111;	
		verts[2].modulate[1] = 19;	
		verts[2].modulate[2] = 9;	
		verts[2].modulate[3] = 255 * alpha;	

		VectorMA (org, p->height, ru, point);	
		VectorMA (point, -p->width, rr, point);	
		VectorCopy (point, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 111;	
		verts[3].modulate[1] = 19;	
		verts[3].modulate[2] = 9;	
		verts[3].modulate[3] = 255 * alpha;	

	}
	else if (p->type == P_FLAT_SCALEUP)
	{
		float width, height;
		float sinR, cosR;

		if (p->color == BLOODRED)
			VectorSet (color, 1, 1, 1);
		else
			VectorSet (color, 0.5, 0.5, 0.5);
		
		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		if (width > p->endwidth)
			width = p->endwidth;

		if (height > p->endheight)
			height = p->endheight;

		sinR = height * sin(DEG2RAD(p->roll)) * sqrt(2);
		cosR = width * cos(DEG2RAD(p->roll)) * sqrt(2);

		VectorCopy (org, verts[0].xyz);	
		verts[0].xyz[0] -= sinR;
		verts[0].xyz[1] -= cosR;
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255 * color[0];	
		verts[0].modulate[1] = 255 * color[1];	
		verts[0].modulate[2] = 255 * color[2];	
		verts[0].modulate[3] = 255;	

		VectorCopy (org, verts[1].xyz);	
		verts[1].xyz[0] -= cosR;	
		verts[1].xyz[1] += sinR;	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255 * color[0];	
		verts[1].modulate[1] = 255 * color[1];	
		verts[1].modulate[2] = 255 * color[2];	
		verts[1].modulate[3] = 255;	

		VectorCopy (org, verts[2].xyz);	
		verts[2].xyz[0] += sinR;	
		verts[2].xyz[1] += cosR;	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255 * color[0];	
		verts[2].modulate[1] = 255 * color[1];	
		verts[2].modulate[2] = 255 * color[2];	
		verts[2].modulate[3] = 255;	

		VectorCopy (org, verts[3].xyz);	
		verts[3].xyz[0] += cosR;	
		verts[3].xyz[1] -= sinR;	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255 * color[0];	
		verts[3].modulate[1] = 255 * color[1];	
		verts[3].modulate[2] = 255 * color[2];	
		verts[3].modulate[3] = 255;		
	}
	else if (p->type == P_FLAT)
	{

		VectorCopy (org, verts[0].xyz);	
		verts[0].xyz[0] -= p->height;	
		verts[0].xyz[1] -= p->width;	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255;	
		verts[0].modulate[1] = 255;	
		verts[0].modulate[2] = 255;	
		verts[0].modulate[3] = 255;	

		VectorCopy (org, verts[1].xyz);	
		verts[1].xyz[0] -= p->height;	
		verts[1].xyz[1] += p->width;	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255;	
		verts[1].modulate[1] = 255;	
		verts[1].modulate[2] = 255;	
		verts[1].modulate[3] = 255;	

		VectorCopy (org, verts[2].xyz);	
		verts[2].xyz[0] += p->height;	
		verts[2].xyz[1] += p->width;	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255;	
		verts[2].modulate[1] = 255;	
		verts[2].modulate[2] = 255;	
		verts[2].modulate[3] = 255;	

		VectorCopy (org, verts[3].xyz);	
		verts[3].xyz[0] += p->height;	
		verts[3].xyz[1] -= p->width;	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255;	
		verts[3].modulate[1] = 255;	
		verts[3].modulate[2] = 255;	
		verts[3].modulate[3] = 255;	

	}
	// Ridah
	else if (p->type == P_ANIM) {
		vec3_t	rr, ru;
		vec3_t	rotate_ang;
		int i, j;

		time = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;
		if (ratio >= 1.0f) {
			ratio = 0.9999f;
		}

		width = p->width + ( ratio * ( p->endwidth - p->width) );
		height = p->height + ( ratio * ( p->endheight - p->height) );

		// if we are "inside" this sprite, don't draw
		if (Distance( cg.snap->ps.origin, org ) < width/1.5) {
			return;
		}

		i = p->shaderAnim;
		j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]);
		p->pshader = shaderAnims[i][j];

		if (p->roll) {
			vectoangles( cg.refdef.viewaxis[0], rotate_ang );
			rotate_ang[ROLL] += p->roll;
			AngleVectors ( rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA (org, -height, ru, point);	
			VectorMA (point, -width, rr, point);	
		} else {
			VectorMA (org, -height, vup, point);	
			VectorMA (point, -width, vright, point);	
		}
		VectorCopy (point, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255;	
		verts[0].modulate[1] = 255;	
		verts[0].modulate[2] = 255;	
		verts[0].modulate[3] = 255;

		if (p->roll) {
			VectorMA (point, 2*height, ru, point);	
		} else {
			VectorMA (point, 2*height, vup, point);	
		}
		VectorCopy (point, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255;	
		verts[1].modulate[1] = 255;	
		verts[1].modulate[2] = 255;	
		verts[1].modulate[3] = 255;	

		if (p->roll) {
			VectorMA (point, 2*width, rr, point);	
		} else {
			VectorMA (point, 2*width, vright, point);	
		}
		VectorCopy (point, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255;	
		verts[2].modulate[1] = 255;	
		verts[2].modulate[2] = 255;	
		verts[2].modulate[3] = 255;	

		if (p->roll) {
			VectorMA (point, -2*height, ru, point);	
		} else {
			VectorMA (point, -2*height, vup, point);	
		}
		VectorCopy (point, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255;	
		verts[3].modulate[1] = 255;	
		verts[3].modulate[2] = 255;	
		verts[3].modulate[3] = 255;	
	}
	// done.
	
	if (!p->pshader) {
// (SA) temp commented out for DM
//		CG_Printf ("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type);
		return;
	}

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY)
		trap_R_AddPolyToScene( p->pshader, 3, TRIverts );
	else
		trap_R_AddPolyToScene( p->pshader, 4, verts );

}
Ejemplo n.º 18
0
void UI_DoSaber( vec3_t origin, vec3_t dir, float length, float lengthMax, float radius, saber_colors_t color )
{
	vec3_t		mid, rgb={1,1,1};
	qhandle_t	blade = 0, glow = 0;
	refEntity_t saber;
	float radiusmult;
	float radiusRange;
	float radiusStart;

	if ( length < 0.5f )
	{
		// if the thing is so short, just forget even adding me.
		return;
	}

	// Find the midpoint of the saber for lighting purposes
	VectorMA( origin, length * 0.5f, dir, mid );

	switch( color )
	{
		case SABER_RED:
			glow = redSaberGlowShader;
			blade = redSaberCoreShader;
			VectorSet( rgb, 1.0f, 0.2f, 0.2f );
			break;
		case SABER_ORANGE:
			glow = orangeSaberGlowShader;
			blade = orangeSaberCoreShader;
			VectorSet( rgb, 1.0f, 0.5f, 0.1f );
			break;
		case SABER_YELLOW:
			glow = yellowSaberGlowShader;
			blade = yellowSaberCoreShader;
			VectorSet( rgb, 1.0f, 1.0f, 0.2f );
			break;
		case SABER_GREEN:
			glow = greenSaberGlowShader;
			blade = greenSaberCoreShader;
			VectorSet( rgb, 0.2f, 1.0f, 0.2f );
			break;
		case SABER_BLUE:
			glow = blueSaberGlowShader;
			blade = blueSaberCoreShader;
			VectorSet( rgb, 0.2f, 0.4f, 1.0f );
			break;
		case SABER_PURPLE:
			glow = purpleSaberGlowShader;
			blade = purpleSaberCoreShader;
			VectorSet( rgb, 0.9f, 0.2f, 1.0f );
			break;
		default:
			break;
	}

	memset( &saber, 0, sizeof( refEntity_t ));

	// Saber glow is it's own ref type because it uses a ton of sprites, otherwise it would eat up too many
	//	refEnts to do each glow blob individually
	saber.saberLength = length;

	// Jeff, I did this because I foolishly wished to have a bright halo as the saber is unleashed.
	// It's not quite what I'd hoped tho.  If you have any ideas, go for it!  --Pat
	if (length < lengthMax )
	{
		radiusmult = 1.0 + (2.0 / length);		// Note this creates a curve, and length cannot be < 0.5.
	}
	else
	{
		radiusmult = 1.0;
	}

	radiusRange = radius * 0.075f;
	radiusStart = radius-radiusRange;

	saber.radius = (radiusStart + crandom() * radiusRange)*radiusmult;
	//saber.radius = (2.8f + crandom() * 0.2f)*radiusmult;

	VectorCopy( origin, saber.origin );
	VectorCopy( dir, saber.axis[0] );
	saber.reType = RT_SABER_GLOW;
	saber.customShader = glow;
	saber.shaderRGBA[0] = saber.shaderRGBA[1] = saber.shaderRGBA[2] = saber.shaderRGBA[3] = 0xff;
	//saber.renderfx = rfx;

	trap->R_AddRefEntityToScene( &saber );

	// Do the hot core
	VectorMA( origin, length, dir, saber.origin );
	VectorMA( origin, -1, dir, saber.oldorigin );
	saber.customShader = blade;
	saber.reType = RT_LINE;
	radiusStart = radius/3.0f;
	saber.radius = (radiusStart + crandom() * radiusRange)*radiusmult;
//	saber.radius = (1.0 + crandom() * 0.2f)*radiusmult;

	trap->R_AddRefEntityToScene( &saber );
}
Ejemplo n.º 19
0
// the trigger was just activated
// ent->activator should be set to the activator so it can be held through a delay
// so wait for the delay time before firing
void multi_trigger( gentity_t *ent, gentity_t *activator ) {
	gentity_t *rofftarget = NULL, *testent = NULL;
	gentity_t *te;
	int i = MAX_CLIENTS;

	if (ent->teamnodmg &&
		activator && activator->client &&
		ent->teamnodmg == activator->client->sess.sessionTeam &&
		!g_ff_objectives.integer)
	{
		return;
	}

	if (ent->spawnflags & 1)
	{
		if (!activator->client)
		{
			return;
		}

		if (!(activator->client->pers.cmd.buttons & BUTTON_USE))
		{
			return;
		}
	}

	ent->activator = activator;
	if ( ent->nextthink ) {
		return;		// can't retrigger until the wait is over
	}

	if ( activator->client ) {
		if ( ( ent->spawnflags & 2 ) &&
			activator->client->sess.sessionTeam != TEAM_RED ) {
			return;
		}
		if ( ( ent->spawnflags & 4 ) &&
			activator->client->sess.sessionTeam != TEAM_BLUE ) {
			return;
		}
	}

	G_UseTargets (ent, ent->activator);

	if (ent->roffname && ent->roffid != -1)
	{
		if (ent->rofftarget)
		{
			while (i < MAX_GENTITIES)
			{
				testent = &g_entities[i];

				if (testent && testent->targetname && strcmp(testent->targetname, ent->rofftarget) == 0)
				{
					rofftarget = testent;
					break;
				}
				i++;
			}
		}
		else
		{
			rofftarget = activator;
		}

		if (rofftarget)
		{
			trap_ROFF_Play(rofftarget->s.number, ent->roffid, qfalse);

			//Play it at the same time on the client, so that we can catch client-side notetrack events and not have to send
			//them over from the server (this wouldn't work for things like effects due to lack of ability to precache them
			//on the server)

			//remember the entity's original position in case of a server-side "loop" notetrack
			VectorCopy(rofftarget->s.pos.trBase, rofftarget->s.origin2);
			VectorCopy(rofftarget->s.apos.trBase, rofftarget->s.angles2);

			te = G_TempEntity( rofftarget->s.pos.trBase, EV_PLAY_ROFF );
			te->s.eventParm = ent->roffid;
			te->s.weapon = rofftarget->s.number;
			te->s.trickedentindex = 0;

			//But.. this may not produce desired results for clients who connect while a ROFF is playing.

			rofftarget->roffid = ent->roffid; //let this entity know the most recent ROFF played on him
		}
	}

	if ( ent->wait > 0 ) {
		ent->think = multi_wait;
		ent->nextthink = level.time + ( ent->wait + ent->random * crandom() ) * 1000;
	} else {
		// we can't just remove (self) here, because this is a touch function
		// called while looping through area links...
		ent->touch = 0;
		ent->nextthink = level.time + FRAMETIME;
		ent->think = G_FreeEntity;
	}
}
Ejemplo n.º 20
0
/*
=================
fire_lead

This is an internal support routine used for bullet/pellet based weapons.
=================
*/
static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod)
{
	trace_t		tr;
	vec3_t		dir;
	vec3_t		forward, right, up;
	vec3_t		end;
	float		r;
	float		u;
	vec3_t		water_start;
	qboolean	water = false;
	int			content_mask = MASK_SHOT | MASK_WATER;

	tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
	if (!(tr.fraction < 1.0))
	{
		vectoangles (aimdir, dir);
		AngleVectors (dir, forward, right, up);

		r = crandom()*hspread;
		u = crandom()*vspread;
		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		if (gi.pointcontents (start) & MASK_WATER)
		{
			water = true;
			VectorCopy (start, water_start);
			content_mask &= ~MASK_WATER;
		}

		tr = gi.trace (start, NULL, NULL, end, self, content_mask);

		// see if we hit water
		if (tr.contents & MASK_WATER)
		{
			int		color;

			water = true;
			VectorCopy (tr.endpos, water_start);

			if (!VectorCompare (start, tr.endpos))
			{
				if (tr.contents & CONTENTS_WATER)
				{
					if (strcmp(tr.surface->name, "*brwater") == 0)
						color = SPLASH_BROWN_WATER;
					else
						color = SPLASH_BLUE_WATER;
				}
				else if (tr.contents & CONTENTS_SLIME)
					color = SPLASH_SLIME;
				else if (tr.contents & CONTENTS_LAVA)
					color = SPLASH_LAVA;
				else
					color = SPLASH_UNKNOWN;

				if (color != SPLASH_UNKNOWN)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (TE_SPLASH);
					gi.WriteByte (8);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.WriteByte (color);
					gi.multicast (tr.endpos, MULTICAST_PVS);
				}

				// change bullet's course when it enters water
				VectorSubtract (end, start, dir);
				vectoangles (dir, dir);
				AngleVectors (dir, forward, right, up);
				r = crandom()*hspread*2;
				u = crandom()*vspread*2;
				VectorMA (water_start, 8192, forward, end);
				VectorMA (end, r, right, end);
				VectorMA (end, u, up, end);
			}

			// re-trace ignoring water this time
			tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
		}
	}

	// send gun puff / flash
	if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
	{
		if (tr.fraction < 1.0)
		{
			if (tr.ent->takedamage)
			{
				T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod);
			}
			else
			{
				if (strncmp (tr.surface->name, "sky", 3) != 0)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (te_impact);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.multicast (tr.endpos, MULTICAST_PVS);

					if (self->client)
						PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
				}
			}
		}
	}

	// if went through water, determine where the end and make a bubble trail
	if (water)
	{
		vec3_t	pos;

		VectorSubtract (tr.endpos, water_start, dir);
		VectorNormalize (dir);
		VectorMA (tr.endpos, -2, dir, pos);
		if (gi.pointcontents (pos) & MASK_WATER)
			VectorCopy (pos, tr.endpos);
		else
			tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);

		VectorAdd (water_start, tr.endpos, pos);
		VectorScale (pos, 0.5, pos);

		gi.WriteByte (svc_temp_entity);
		gi.WriteByte (TE_BUBBLETRAIL);
		gi.WritePosition (water_start);
		gi.WritePosition (tr.endpos);
		gi.multicast (pos, MULTICAST_PVS);
	}
}
Ejemplo n.º 21
0
/*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON
"wait"			base time between triggering all targets, default is 1
"random"		wait variance, default is 0

so, the basic time between firing is a random time between
(wait - random) and (wait + random)

"delay"			delay before first firing when turned on, default is 0

"pausetime"		additional delay used only the very first time
				and only if spawned with START_ON

These can used but not touched.
*/
void func_timer_think (edict_t *self)
{
	G_UseTargets (self, self->activator);
	self->nextthink = level.time + self->wait + crandom() * self->random;
}
Ejemplo n.º 22
0
void Machinegun_Fire(edict_t * ent)
{
	int i;
	vec3_t start;
	vec3_t forward, right;
	vec3_t angles;
	int damage = 8;
	int kick = 2;
	vec3_t offset;

	if (!(ent->client->buttons & BUTTON_ATTACK)) {
		ent->client->machinegun_shots = 0;
		ent->client->ps.gunframe++;
		return;
	}

	if (ent->client->ps.gunframe == 5)
		ent->client->ps.gunframe = 4;
	else
		ent->client->ps.gunframe = 5;

	if (ent->client->pers.inventory[ent->client->ammo_index] < 1) {
		ent->client->ps.gunframe = 6;
		if (level.time >= ent->pain_debounce_time) {
			gi.sound(ent, CHAN_VOICE,
				 gi.soundindex("weapons/noammo.wav"), 1,
				 ATTN_NORM, 0);
			ent->pain_debounce_time = level.time + 1;
		}
		NoAmmoWeaponChange(ent);
		return;
	}

	if (is_quad) {
		damage *= 4;
		kick *= 4;
	}

	for (i = 1; i < 3; i++) {
		ent->client->kick_origin[i] = crandom() * 0.35;
		ent->client->kick_angles[i] = crandom() * 0.7;
	}
	ent->client->kick_origin[0] = crandom() * 0.35;
	ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;

	// raise the gun as it is firing
	if (!deathmatch->value) {
		ent->client->machinegun_shots++;
		if (ent->client->machinegun_shots > 9)
			ent->client->machinegun_shots = 9;
	}
	// get start / end positions
	VectorAdd(ent->client->v_angle, ent->client->kick_angles, angles);
	AngleVectors(angles, forward, right, NULL);
	VectorSet(offset, 0, 8, ent->viewheight - 8);
	P_ProjectSource(ent->client, ent->s.origin, offset, forward, right,
			start);
	fire_bullet(ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD,
		    DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);

	gi.WriteByte(svc_muzzleflash);
	gi.WriteShort(ent - g_edicts);
	gi.WriteByte(MZ_MACHINEGUN | is_silenced);
	gi.multicast(ent->s.origin, MULTICAST_PVS);

	PlayerNoise(ent, start, PNOISE_WEAPON);

	if (!((int)dmflags->value & DF_INFINITE_AMMO))
		ent->client->pers.inventory[ent->client->ammo_index]--;

	ent->client->anim_priority = ANIM_ATTACK;
	if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
		ent->s.frame = FRAME_crattak1 - (int)(random() + 0.25);
		ent->client->anim_end = FRAME_crattak9;
	} else {
		ent->s.frame = FRAME_attack1 - (int)(random() + 0.25);
		ent->client->anim_end = FRAME_attack8;
	}
}
Ejemplo n.º 23
0
void Use_Target_Delay(gentity_t *ent, gentity_t *other, gentity_t *activator)
{
	ent->nextthink = level.time + (ent->wait + ent->random * crandom()) * 1000;
	ent->think     = Think_Target_Delay;
	ent->activator = activator;
}
Ejemplo n.º 24
0
void Chaingun_Fire(edict_t * ent)
{
	int i;
	int shots;
	vec3_t start;
	vec3_t forward, right, up;
	float r, u;
	vec3_t offset;
	int damage;
	int kick = 2;

	if (deathmatch->value)
		damage = 6;
	else
		damage = 8;

	if (ent->client->ps.gunframe == 5)
		gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"),
			 1, ATTN_IDLE, 0);

	if ((ent->client->ps.gunframe == 14)
	    && !(ent->client->buttons & BUTTON_ATTACK)) {
		ent->client->ps.gunframe = 32;
		ent->client->weapon_sound = 0;
		return;
	} else if ((ent->client->ps.gunframe == 21)
		   && (ent->client->buttons & BUTTON_ATTACK)
		   && ent->client->pers.inventory[ent->client->ammo_index]) {
		ent->client->ps.gunframe = 15;
	} else {
		ent->client->ps.gunframe++;
	}

	if (ent->client->ps.gunframe == 22) {
		ent->client->weapon_sound = 0;
		gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"),
			 1, ATTN_IDLE, 0);
	} else {
		ent->client->weapon_sound =
		    gi.soundindex("weapons/chngnl1a.wav");
	}

	ent->client->anim_priority = ANIM_ATTACK;
	if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
		ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
		ent->client->anim_end = FRAME_crattak9;
	} else {
		ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
		ent->client->anim_end = FRAME_attack8;
	}

	if (ent->client->ps.gunframe <= 9)
		shots = 1;
	else if (ent->client->ps.gunframe <= 14) {
		if (ent->client->buttons & BUTTON_ATTACK)
			shots = 2;
		else
			shots = 1;
	} else
		shots = 3;

	if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
		shots = ent->client->pers.inventory[ent->client->ammo_index];

	if (!shots) {
		if (level.time >= ent->pain_debounce_time) {
			gi.sound(ent, CHAN_VOICE,
				 gi.soundindex("weapons/noammo.wav"), 1,
				 ATTN_NORM, 0);
			ent->pain_debounce_time = level.time + 1;
		}
		NoAmmoWeaponChange(ent);
		return;
	}

	if (is_quad) {
		damage *= 4;
		kick *= 4;
	}

	for (i = 0; i < 3; i++) {
		ent->client->kick_origin[i] = crandom() * 0.35;
		ent->client->kick_angles[i] = crandom() * 0.7;
	}

	for (i = 0; i < shots; i++) {
		// get start / end positions
		AngleVectors(ent->client->v_angle, forward, right, up);
		r = 7 + crandom() * 4;
		u = crandom() * 4;
		VectorSet(offset, 0, r, u + ent->viewheight - 8);
		P_ProjectSource(ent->client, ent->s.origin, offset, forward,
				right, start);

		fire_bullet(ent, start, forward, damage, kick,
			    DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD,
			    MOD_CHAINGUN);
	}

	// send muzzle flash
	gi.WriteByte(svc_muzzleflash);
	gi.WriteShort(ent - g_edicts);
	gi.WriteByte((MZ_CHAINGUN1 + shots - 1) | is_silenced);
	gi.multicast(ent->s.origin, MULTICAST_PVS);

	PlayerNoise(ent, start, PNOISE_WEAPON);

	if (!((int)dmflags->value & DF_INFINITE_AMMO))
		ent->client->pers.inventory[ent->client->ammo_index] -= shots;
}
Ejemplo n.º 25
0
void RT_Flying_Strafe( void )
{
	int		side;
	vec3_t	end, right, dir;
	trace_t	tr;

	if ( random() > 0.7f 
		|| !NPC->enemy 
		|| !NPC->enemy->client )
	{
		// Do a regular style strafe
		AngleVectors( NPC->client->renderInfo.eyeAngles, NULL, right, NULL );

		// Pick a random strafe direction, then check to see if doing a strafe would be
		//	reasonably valid
		side = ( rand() & 1 ) ? -1 : 1;
		VectorMA( NPC->currentOrigin, RT_FLYING_STRAFE_DIS * side, right, end );

		gi.trace( &tr, NPC->currentOrigin, NULL, NULL, end, NPC->s.number, MASK_SOLID );

		// Close enough
		if ( tr.fraction > 0.9f )
		{
			float vel = RT_FLYING_STRAFE_VEL+Q_flrand(-20,20);
			VectorMA( NPC->client->ps.velocity, vel*side, right, NPC->client->ps.velocity );
			if ( !Q_irand( 0, 3 ) )
			{
				// Add a slight upward push
				float upPush = RT_FLYING_UPWARD_PUSH;
				if ( NPC->client->ps.velocity[2] < 300 )
				{
					if ( NPC->client->ps.velocity[2] < 300+upPush )
					{
						NPC->client->ps.velocity[2] += upPush;
					}
					else
					{
						NPC->client->ps.velocity[2] = 300;
					}
				}
			}

//			NPCInfo->standTime = level.time + 1000 + random() * 500;	// Original
//			NPCInfo->standTime = level.time + 2000 + random() * 500;	// Revision 1
			NPCInfo->standTime = level.time + 1500 + random() * 500;	// Revision 2
		}
	}
	else
	{
		// Do a strafe to try and keep on the side of their enemy
		AngleVectors( NPC->enemy->client->renderInfo.eyeAngles, dir, right, NULL );

		// Pick a random side
		side = ( rand() & 1 ) ? -1 : 1;
		float	stDis = RT_FLYING_STRAFE_DIS*2.0f;
		VectorMA( NPC->enemy->currentOrigin, stDis * side, right, end );

		// then add a very small bit of random in front of/behind the player action
		VectorMA( end, crandom() * 25, dir, end );

		gi.trace( &tr, NPC->currentOrigin, NULL, NULL, end, NPC->s.number, MASK_SOLID );

		// Close enough
		if ( tr.fraction > 0.9f )
		{
			float vel = (RT_FLYING_STRAFE_VEL*4)+Q_flrand(-20,20);
			VectorSubtract( tr.endpos, NPC->currentOrigin, dir );
			dir[2] *= 0.25; // do less upward change
			float dis = VectorNormalize( dir );
			if ( dis > vel )
			{
				dis = vel;
			}
			// Try to move the desired enemy side
			VectorMA( NPC->client->ps.velocity, dis, dir, NPC->client->ps.velocity );

			if ( !Q_irand( 0, 3 ) )
			{
				float upPush = RT_FLYING_UPWARD_PUSH;
				// Add a slight upward push
				if ( NPC->client->ps.velocity[2] < 300 )
				{
					if ( NPC->client->ps.velocity[2] < 300+upPush )
					{
						NPC->client->ps.velocity[2] += upPush;
					}
					else
					{
						NPC->client->ps.velocity[2] = 300;
					}
				}
				else if ( NPC->client->ps.velocity[2] > 300 )
				{
					NPC->client->ps.velocity[2] = 300;
				}
			}

//			NPCInfo->standTime = level.time + 2500 + random() * 500;	// Original
//			NPCInfo->standTime = level.time + 5000 + random() * 500;	// Revision 1
			NPCInfo->standTime = level.time + 3500 + random() * 500;	// Revision 2
		}
	}
}
Ejemplo n.º 26
0
void CG_Particle_OilSlick (qhandle_t pshader, centity_t *cent)
{
	cparticle_t	*p;
	
	if (!pshader)
		CG_Printf ("CG_Particle_OilSlick == ZERO!\n");

	if (!free_particles)
		return;
	p = free_particles;
	free_particles = p->next;
	p->next = active_particles;
	active_particles = p;
	p->time = cg.time;
	
	if (cent->currentState.angles2[2])
		p->endtime = cg.time + cent->currentState.angles2[2];
	else
		p->endtime = cg.time + 60000;

	p->startfade = p->endtime;

	p->alpha = 1.0;
	p->alphavel = 0;
	p->roll = 0;

	p->pshader = pshader;

	if (cent->currentState.angles2[0] || cent->currentState.angles2[1])
	{
		p->width = cent->currentState.angles2[0];
		p->height = cent->currentState.angles2[0];

		p->endheight = cent->currentState.angles2[1];
		p->endwidth = cent->currentState.angles2[1];
	}
	else
	{
		p->width = 8;
		p->height = 8;

		p->endheight = 16;
		p->endwidth = 16;
	}

	p->type = P_FLAT_SCALEUP;

	p->snum = 1.0;

	VectorCopy(cent->currentState.origin, p->org );
	
	p->org[2]+= 0.55 + (crandom() * 0.5);

	p->vel[0] = 0;
	p->vel[1] = 0;
	p->vel[2] = 0;
	VectorClear( p->accel );

	p->rotate = qfalse;

	p->roll = rand()%179;
	
	p->alpha = 0.75;

}
Ejemplo n.º 27
0
/*
================
LaunchItem

Spawns an item and tosses it forward
================
*/
gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity, char *target ) {
	gentity_t	*dropped;

	dropped = G_Spawn();

	dropped->s.eType = ET_ITEM;
	dropped->s.modelindex = item - bg_itemlist;	// store item number in modelindex
	dropped->s.modelindex2 = 1; // This is non-zero is it's a dropped item

	dropped->classname = item->classname;
	dropped->item = item;

	// try using the "correct" mins/maxs first
	VectorSet( dropped->mins, item->mins[0], item->mins[1], item->mins[2] );
	VectorSet( dropped->maxs, item->maxs[0], item->maxs[1], item->maxs[2] );

	if ((!dropped->mins[0] && !dropped->mins[1] && !dropped->mins[2]) && 
		(!dropped->maxs[0] && !dropped->maxs[1] && !dropped->maxs[2]))
	{
		VectorSet( dropped->maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS );
		VectorScale( dropped->maxs, -1, dropped->mins );
	}

	dropped->contents = CONTENTS_TRIGGER|CONTENTS_ITEM;//CONTENTS_TRIGGER;//not CONTENTS_BODY for dropped items, don't need to ID them

	if ( target && target[0] )
	{
		dropped->target = G_NewString( target );
	}
	else
	{
		// if not targeting something, auto-remove after 30 seconds
		// only if it's NOT a security or goodie key
		if (dropped->item->giTag != INV_SECURITY_KEY )
		{
			dropped->e_ThinkFunc = thinkF_G_FreeEntity;
			dropped->nextthink = level.time + 30000;
		}

		if ( dropped->item->giType == IT_AMMO && dropped->item->giTag == AMMO_FORCE )
		{
			dropped->nextthink = -1;
			dropped->e_ThinkFunc = thinkF_NULL;
		}
	}

	dropped->e_TouchFunc = touchF_Touch_Item;

	if ( item->giType == IT_WEAPON )
	{
		// give weapon items zero pitch, a random yaw, and rolled onto their sides...but would be bad to do this for a bowcaster
		if ( item->giTag != WP_BOWCASTER
			&& item->giTag != WP_THERMAL
			&& item->giTag != WP_TRIP_MINE
			&& item->giTag != WP_DET_PACK )
		{
			VectorSet( dropped->s.angles, 0, crandom() * 180, 90.0f );
			G_SetAngles( dropped, dropped->s.angles );
		}
	}

	G_SetOrigin( dropped, origin );
	dropped->s.pos.trType = TR_GRAVITY;
	dropped->s.pos.trTime = level.time;
	VectorCopy( velocity, dropped->s.pos.trDelta );

	dropped->s.eFlags |= EF_BOUNCE_HALF;

	dropped->flags = FL_DROPPED_ITEM;

	gi.linkentity (dropped);

	return dropped;
}
Ejemplo n.º 28
0
void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir)
{
	float	length;
	float	dist;
	float	crittersize;
	vec3_t	angles, forward;
	vec3_t	point;
	cparticle_t	*p;
	int		i;
	
	dist = 0;

	length = VectorLength (dir);
	vectoangles (dir, angles);
	AngleVectors (angles, forward, NULL, NULL);

	crittersize = LARGESIZE;

	if (length)
		dist = length / crittersize;

	if (dist < 1)
		dist = 1;

	VectorCopy (origin, point);

	for (i=0; i<dist; i++)
	{
		VectorMA (point, crittersize, forward, point);	
		
		if (!free_particles)
			return;

		p = free_particles;
		free_particles = p->next;
		p->next = active_particles;
		active_particles = p;

		p->time = cg.time;
		p->alpha = 1.0;
		p->alphavel = 0;
		p->roll = 0;

		p->pshader = cgs.media.smokePuffShader;

		p->endtime = cg.time + 350 + (crandom() * 100);
		
		p->startfade = cg.time;
		
		p->width = LARGESIZE;
		p->height = LARGESIZE;
		p->endheight = LARGESIZE;
		p->endwidth = LARGESIZE;

		p->type = P_SMOKE;

		VectorCopy( origin, p->org );
		
		p->vel[0] = 0;
		p->vel[1] = 0;
		p->vel[2] = -1;
		
		VectorClear( p->accel );

		p->rotate = qfalse;

		p->roll = rand()%179;
		
		p->color = BLOODRED;
		
		p->alpha = 0.75;
		
	}

	
}
Ejemplo n.º 29
0
void CG_GibPlayer( vec3_t playerOrigin ) {
	vec3_t	origin, velocity;

	if ( !cg_blood.integer ) {
		return;
	}

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	if ( rand() & 1 ) {
		CG_LaunchGib( origin, velocity, cgs.media.gibSkull );
	} else {
		CG_LaunchGib( origin, velocity, cgs.media.gibBrain );
	}

	// allow gibs to be turned off for speed
	if ( !cg_gibs.integer ) {
		return;
	}

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibAbdomen );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibArm );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibChest );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibFist );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibFoot );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibForearm );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibIntestine );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibLeg );

	VectorCopy( playerOrigin, origin );
	velocity[0] = crandom()*GIB_VELOCITY;
	velocity[1] = crandom()*GIB_VELOCITY;
	velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
	CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
}
Ejemplo n.º 30
0
void ThrowGib (edict_t *self, char *gibname, int damage, int type)
{
	edict_t *gib;
	vec3_t	vd;
	vec3_t	origin;
	vec3_t	size;
	float	vscale;

	if (!self || !gibname)
	{
		return;
	}

	if (level.framenum > lastgibframe)
	{
		gibsthisframe = 0;
		lastgibframe = level.framenum;
	}

	gibsthisframe++;
	
	if (gibsthisframe > 20)
	{
		return;
	}

	gib = G_Spawn();

	VectorScale (self->size, 0.5, size);
	VectorAdd (self->absmin, size, origin);
	gib->s.origin[0] = origin[0] + crandom() * size[0];
	gib->s.origin[1] = origin[1] + crandom() * size[1];
	gib->s.origin[2] = origin[2] + crandom() * size[2];

	gi.setmodel (gib, gibname);
	gib->solid = SOLID_NOT;
	gib->s.effects |= EF_GIB;
	gib->flags |= FL_NO_KNOCKBACK;
	gib->takedamage = DAMAGE_YES;
	gib->die = gib_die;

	if (type == GIB_ORGANIC)
	{
		gib->movetype = MOVETYPE_TOSS;
		gib->touch = gib_touch;
		vscale = 0.5;
	}
	else
	{
		gib->movetype = MOVETYPE_BOUNCE;
		vscale = 1.0;
	}

	VelocityForDamage (damage, vd);
	VectorMA (self->velocity, vscale, vd, gib->velocity);
	ClipGibVelocity (gib);
	gib->avelocity[0] = random()*600;
	gib->avelocity[1] = random()*600;
	gib->avelocity[2] = random()*600;

	gib->think = G_FreeEdict;
	gib->nextthink = level.time + 10 + random()*10;

	gi.linkentity (gib);
}