示例#1
0
qboolean WP_BreakSaber( gentity_t *ent, const char *surfName, saberType_t saberType )
{//Make sure there *is* one specified and not using dualSabers
	if ( ent == NULL || ent->client == NULL )
	{//invalid ent or client
		return qfalse;
	}

	if ( ent->s.number < MAX_CLIENTS )
	{//player
		//if ( g_spskill->integer < 3 )
		{//only on the hardest level?
			//FIXME: add a cvar?
			return qfalse;
		}
	}

	if ( ent->health <= 0 )
	{//not if they're dead
		return qfalse;
	}

	if ( ent->client->ps.weapon != WP_SABER )
	{//not holding saber
		return qfalse;
	}

	if ( ent->client->ps.dualSabers )
	{//FIXME: handle this?
		return qfalse;
	}

	if ( !ent->client->ps.saber[0].brokenSaber1 ) 
	{//not breakable into another type of saber
		return qfalse;
	}

	if ( PM_SaberInStart( ent->client->ps.saberMove ) //in a start
		|| PM_SaberInTransition( ent->client->ps.saberMove ) //in a transition
		|| PM_SaberInAttack( ent->client->ps.saberMove ) )//in an attack
	{//don't break when in the middle of an attack
		return qfalse;
	}

	if ( Q_stricmpn( "w_", surfName, 2 ) 
		&& Q_stricmpn( "saber_", surfName, 6 ) //hack because using mod-community made saber
		&& Q_stricmp( "cylinder01", surfName ) )//hack because using mod-community made saber
	{//didn't hit my weapon
		return qfalse;
	}

	//Sith Sword should ALWAYS do this
	if ( saberType != SABER_SITH_SWORD && Q_irand( 0, 50 ) )//&& Q_irand( 0, 10 ) )
	{//10% chance - FIXME: extern this, too?
		return qfalse;
	}

	//break it
	char	*replacementSaber1 = G_NewString( ent->client->ps.saber[0].brokenSaber1 );
	char	*replacementSaber2 = G_NewString( ent->client->ps.saber[0].brokenSaber2 );
	int		i, originalNumBlades = ent->client->ps.saber[0].numBlades;
	qboolean	broken = qfalse;
	saber_colors_t	colors[MAX_BLADES];

	//store the colors
	for ( i = 0; i < MAX_BLADES; i++ )
	{
		colors[i] = ent->client->ps.saber[0].blade[i].color;
	}

	//FIXME: chance of dropping the right-hand one?  Based on damage, or...?
	//FIXME: sound & effect when this happens, and send them into a broken parry?

	//remove saber[0], replace with replacementSaber1
	if ( replacementSaber1 )
	{
		WP_RemoveSaber( ent, 0 );
		WP_SetSaber( ent, 0, replacementSaber1 );
		for ( i = 0; i < ent->client->ps.saber[0].numBlades; i++ )
		{
			ent->client->ps.saber[0].blade[i].color = colors[i];
		}
		broken = qtrue;
		//change my saberent's model and skin to match my new right-hand saber
		WP_SetSaberEntModelSkin( ent, &g_entities[ent->client->ps.saberEntityNum] );
	}

	if ( originalNumBlades <= 1 ) 
	{//nothing to split off
		//FIXME: handle this?
	}
	else
	{
		//remove saber[1], replace with replacementSaber2
		if ( replacementSaber2 )
		{//FIXME: 25% chance that it just breaks - just spawn the second saber piece and toss it away immediately, can't be picked up.
			//shouldn't be one in this hand, but just in case, remove it
			WP_RemoveSaber( ent, 1 );
			WP_SetSaber( ent, 1, replacementSaber2 );

			//put the remainder of the original saber's blade colors onto this saber's blade(s)
			for ( i = ent->client->ps.saber[0].numBlades; i < MAX_BLADES; i++ )
			{
				ent->client->ps.saber[1].blade[i-ent->client->ps.saber[0].numBlades].color = colors[i];
			}
			broken = qtrue;
		}
	}
	return broken;
}
示例#2
0
void G_ReflectMissile( gentity_t *ent, gentity_t *missile, vec3_t forward ) 
{
	vec3_t	bounce_dir;
	int		i;
	float	speed;
	qboolean reflected = qfalse;
	gentity_t	*owner = ent;

	if ( ent->owner )
	{
		owner = ent->owner;
	}

	//save the original speed
	speed = VectorNormalize( missile->s.pos.trDelta );

	if ( ent && owner && owner->client && !owner->client->ps.saberInFlight && 
		(owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE] > FORCE_LEVEL_2 || (owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE]>FORCE_LEVEL_1&&!Q_irand( 0, 3 )) ) )
	{//if high enough defense skill and saber in-hand (100% at level 3, 25% at level 2, 0% at level 1), reflections are perfectly deflected toward an enemy
		gentity_t *enemy;
		if ( owner->enemy && Q_irand( 0, 3 ) )
		{//toward current enemy 75% of the time
			enemy = owner->enemy;
		}
		else
		{//find another enemy
			enemy = Jedi_FindEnemyInCone( owner, owner->enemy, 0.3f );
		}
		if ( enemy )
		{
			vec3_t	bullseye;
			CalcEntitySpot( enemy, SPOT_HEAD, bullseye );
			bullseye[0] += Q_irand( -4, 4 );
			bullseye[1] += Q_irand( -4, 4 );
			bullseye[2] += Q_irand( -16, 4 );
			VectorSubtract( bullseye, missile->currentOrigin, bounce_dir );
			VectorNormalize( bounce_dir );
			if ( !PM_SaberInParry( owner->client->ps.saberMove ) 
				&& !PM_SaberInReflect( owner->client->ps.saberMove ) 
				&& !PM_SaberInIdle( owner->client->ps.saberMove ) )
			{//a bit more wild
				if ( PM_SaberInAttack( owner->client->ps.saberMove )
					|| PM_SaberInTransitionAny( owner->client->ps.saberMove )
					|| PM_SaberInSpecialAttack( owner->client->ps.torsoAnim ) )
				{//moderately more wild
					for ( i = 0; i < 3; i++ )
					{
						bounce_dir[i] += Q_flrand( -0.2f, 0.2f );
					}
				}
				else
				{//mildly more wild
					for ( i = 0; i < 3; i++ )
					{
						bounce_dir[i] += Q_flrand( -0.1f, 0.1f );
					}
				}
			}
			VectorNormalize( bounce_dir );
			reflected = qtrue;
		}
	}
	if ( !reflected )
	{
		if ( missile->owner && missile->s.weapon != WP_SABER )
		{//bounce back at them if you can
			VectorSubtract( missile->owner->currentOrigin, missile->currentOrigin, bounce_dir );
			VectorNormalize( bounce_dir );
		}
		else
		{
			vec3_t missile_dir;

			VectorSubtract( ent->currentOrigin, missile->currentOrigin, missile_dir );
			VectorCopy( missile->s.pos.trDelta, bounce_dir );
			VectorScale( bounce_dir, DotProduct( forward, missile_dir ), bounce_dir );
			VectorNormalize( bounce_dir );
		}
		if ( owner->s.weapon == WP_SABER && owner->client )
		{//saber
			if ( owner->client->ps.saberInFlight )
			{//reflecting off a thrown saber is totally wild
				for ( i = 0; i < 3; i++ )
				{
					bounce_dir[i] += Q_flrand( -0.8f, 0.8f );
				}
			}
			else if ( owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE] <= FORCE_LEVEL_1 )
			{// at level 1
				for ( i = 0; i < 3; i++ )
				{
					bounce_dir[i] += Q_flrand( -0.4f, 0.4f );
				}
			}
			else
			{// at level 2
				for ( i = 0; i < 3; i++ )
				{
					bounce_dir[i] += Q_flrand( -0.2f, 0.2f );
				}
			}
			if ( !PM_SaberInParry( owner->client->ps.saberMove ) 
				&& !PM_SaberInReflect( owner->client->ps.saberMove ) 
				&& !PM_SaberInIdle( owner->client->ps.saberMove ) )
			{//a bit more wild
				if ( PM_SaberInAttack( owner->client->ps.saberMove )
					|| PM_SaberInTransitionAny( owner->client->ps.saberMove )
					|| PM_SaberInSpecialAttack( owner->client->ps.torsoAnim ) )
				{//really wild
					for ( i = 0; i < 3; i++ )
					{
						bounce_dir[i] += Q_flrand( -0.3f, 0.3f );
					}
				}
				else
				{//mildly more wild
					for ( i = 0; i < 3; i++ )
					{
						bounce_dir[i] += Q_flrand( -0.1f, 0.1f );
					}
				}
			}
		}
		else
		{//some other kind of reflection
			for ( i = 0; i < 3; i++ )
			{
				bounce_dir[i] += Q_flrand( -0.2f, 0.2f );
			}
		}
	}
	VectorNormalize( bounce_dir );
	VectorScale( bounce_dir, speed, missile->s.pos.trDelta );
#ifdef _DEBUG
		assert( !Q_isnan(missile->s.pos.trDelta[0])&&!Q_isnan(missile->s.pos.trDelta[1])&&!Q_isnan(missile->s.pos.trDelta[2]));
#endif// _DEBUG
	missile->s.pos.trTime = level.time - 10;		// move a bit on the very first frame
	VectorCopy( missile->currentOrigin, missile->s.pos.trBase );
	if ( missile->s.weapon != WP_SABER )
	{//you are mine, now!
		if ( !missile->lastEnemy )
		{//remember who originally shot this missile
			missile->lastEnemy = missile->owner;
		}
		missile->owner = owner;
	}
	if ( missile->s.weapon == WP_ROCKET_LAUNCHER )
	{//stop homing
		missile->e_ThinkFunc = thinkF_NULL;
	}
}
示例#3
0
void G_ReflectMissile(gentity_t *ent, gentity_t *missile, vec3_t forward, forcePowers_t powerToUse)
{
	vec3_t	bounce_dir;
	int		i;
	float	speed;
	qboolean perfectReflection = qfalse;
	qboolean reflected = qfalse;
	gentity_t	*owner = ent;

	if (ent->owner)
	{
		owner = ent->owner;
	}

	//save the original speed
	speed = VectorNormalize(missile->s.pos.trDelta);

	if (ent && owner && owner->client &&
		(owner->client->ps.forcePowerLevel[powerToUse] > FORCE_LEVEL_2 || (owner->client->ps.forcePowerLevel[powerToUse]>FORCE_LEVEL_1&&!Q_irand(0, 3))))
		//if high enough force skill (100% at level 3, 25% at level 2, 0% at level 1), reflections are perfectly deflected toward an enemy
	{
		perfectReflection = qtrue;
	}

	if (powerToUse == FP_SABER_DEFENSE)
	{
		if (owner->client->ps.saberInFlight)
		{//but need saber in-hand for perfect reflection
			perfectReflection = qfalse;
		}

		if (g_spskill->integer >= 2 && !g_saberAutoBlocking->integer && owner->client->ps.saberBlockingTime < level.time)
		{//but need to be blocking for perfect reflection on higher difficulties
			perfectReflection = qfalse;
		}
		/*
		if (!PM_WalkingOrIdle(owner) || !PM_SaberInParry(owner->client->ps.saberMove))
		{//but need to be blocking for perfect reflection on higher difficulties
			perfectReflection = qfalse;
		}
		*/
	}

	if (perfectReflection)
	{
		if (g_saberDeflectAutoAim->integer || owner->s.clientNum >= MAX_CLIENTS) //either by autoaim (lower difficulties)
		{
			gentity_t *enemy;
			if (owner->enemy && Q_irand(0, 3))
			{//toward current enemy 75% of the time
				enemy = owner->enemy;
			}
			else
			{//find another enemy
				enemy = Jedi_FindEnemyInCone(owner, owner->enemy, 0.3f);
			}
			if (enemy)
			{
				vec3_t	bullseye;
				CalcEntitySpot(enemy, SPOT_HEAD, bullseye);
				bullseye[0] += Q_irand(-4, 4);
				bullseye[1] += Q_irand(-4, 4);
				bullseye[2] += Q_irand(-16, 4);
				VectorSubtract(bullseye, missile->currentOrigin, bounce_dir);
				VectorNormalize(bounce_dir);
				if (!PM_SaberInParry(owner->client->ps.saberMove)
					&& !PM_SaberInReflect(owner->client->ps.saberMove)
					&& !PM_SaberInIdle(owner->client->ps.saberMove))
				{//a bit more wild
					if (PM_SaberInAttack(owner->client->ps.saberMove)
						|| PM_SaberInTransitionAny(owner->client->ps.saberMove)
						|| PM_SaberInSpecialAttack(owner->client->ps.torsoAnim))
					{//moderately more wild
						for (i = 0; i < 3; i++)
						{
							bounce_dir[i] += Q_flrand(-0.2f, 0.2f);
						}
					}
					else
					{//mildly more wild
						for (i = 0; i < 3; i++)
						{
							bounce_dir[i] += Q_flrand(-0.1f, 0.1f);
						}
					}
				}
				VectorNormalize(bounce_dir);
				reflected = qtrue;
			}
		}
		else //or by where the crosshair is (higher difficulties)
		{
			VectorSubtract(g_crosshairWorldCoord, missile->currentOrigin, bounce_dir);
			VectorNormalize(bounce_dir);
			if (!PM_SaberInParry(owner->client->ps.saberMove)
				&& !PM_SaberInReflect(owner->client->ps.saberMove)
				&& !PM_SaberInIdle(owner->client->ps.saberMove))
			{//a bit more wild
				if (PM_SaberInAttack(owner->client->ps.saberMove)
					|| PM_SaberInTransitionAny(owner->client->ps.saberMove)
					|| PM_SaberInSpecialAttack(owner->client->ps.torsoAnim))
				{//moderately more wild
					for (i = 0; i < 3; i++)
					{
						bounce_dir[i] += Q_flrand(-0.2f, 0.2f);
					}
				}
				else
				{//mildly more wild
					for (i = 0; i < 3; i++)
					{
						bounce_dir[i] += Q_flrand(-0.1f, 0.1f);
					}
				}
			}
			VectorNormalize(bounce_dir);
			reflected = qtrue;
		}
	}
	if (!reflected)
	{
		if (g_saberDeflectAutoAim->integer || owner->s.clientNum >= MAX_CLIENTS)
		{
			if (missile->owner && missile->s.weapon != WP_SABER)
			{//bounce back at them if you can
				VectorSubtract(missile->owner->currentOrigin, missile->currentOrigin, bounce_dir);
				VectorNormalize(bounce_dir);
			}
			else
			{
				vec3_t missile_dir;

				VectorSubtract(ent->currentOrigin, missile->currentOrigin, missile_dir);
				VectorCopy(missile->s.pos.trDelta, bounce_dir);
				VectorScale(bounce_dir, DotProduct(forward, missile_dir), bounce_dir);
				VectorNormalize(bounce_dir);
			}
		}
		else //deflect off at an angle.
		{
			vec3_t deflect_dir, missile_dir;
			float forceFactor;
			VectorSubtract(g_crosshairWorldCoord, missile->currentOrigin, deflect_dir);
			VectorCopy(missile->s.pos.trDelta, missile_dir);
			VectorNormalize(missile_dir);
			VectorNormalize(deflect_dir);

			//bigger forceFactors make the reflected shots go closer to the crosshair
			switch (owner->client->ps.forcePowerLevel[powerToUse])
			{
			case FORCE_LEVEL_1:
				forceFactor = 2.0f;
				break;
			case FORCE_LEVEL_2:
				forceFactor = 3.0f;
				break;
			default:
				forceFactor = 10.0f;
				break;
			}

			VectorMA(missile_dir, forceFactor, deflect_dir, bounce_dir);

			VectorNormalize(bounce_dir);
		}
		if (owner->s.weapon == WP_SABER && owner->client && powerToUse == FP_SABER_DEFENSE)
		{//saber
			if (owner->client->ps.saberInFlight)
			{//reflecting off a thrown saber is totally wild
				for (i = 0; i < 3; i++)
				{
					bounce_dir[i] += Q_flrand(-0.8f, 0.8f);
				}
			}
			else if (owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE] <= FORCE_LEVEL_1)
			{// at level 1 or below
				for (i = 0; i < 3; i++)
				{
					bounce_dir[i] += Q_flrand(-0.4f, 0.4f);
				}
			}
			else
			{// at level 2
				for (i = 0; i < 3; i++)
				{
					bounce_dir[i] += Q_flrand(-0.2f, 0.2f);
				}
			}
			if (!PM_SaberInParry(owner->client->ps.saberMove)
				&& !PM_SaberInReflect(owner->client->ps.saberMove)
				&& !PM_SaberInIdle(owner->client->ps.saberMove))
			{//a bit more wild
				if (PM_SaberInAttack(owner->client->ps.saberMove)
					|| PM_SaberInTransitionAny(owner->client->ps.saberMove)
					|| PM_SaberInSpecialAttack(owner->client->ps.torsoAnim))
				{//really wild
					for (i = 0; i < 3; i++)
					{
						bounce_dir[i] += Q_flrand(-0.3f, 0.3f);
					}
				}
				else
				{//mildly more wild
					for (i = 0; i < 3; i++)
					{
						bounce_dir[i] += Q_flrand(-0.1f, 0.1f);
					}
				}
			}
		}
		else
		{//some other kind of reflection
			for (i = 0; i < 3; i++)
			{
				bounce_dir[i] += Q_flrand(-0.2f, 0.2f);
			}
		}
	}
	VectorNormalize(bounce_dir);
	VectorScale(bounce_dir, speed, missile->s.pos.trDelta);
#ifdef _DEBUG
	assert(!Q_isnan(missile->s.pos.trDelta[0]) && !Q_isnan(missile->s.pos.trDelta[1]) && !Q_isnan(missile->s.pos.trDelta[2]));
#endif// _DEBUG
	missile->s.pos.trTime = level.time - 10;		// move a bit on the very first frame
	VectorCopy(missile->currentOrigin, missile->s.pos.trBase);
	if (missile->s.weapon != WP_SABER)
	{//you are mine, now!
		if (!missile->lastEnemy)
		{//remember who originally shot this missile
			missile->lastEnemy = missile->owner;
		}
		missile->owner = owner;
	}
	if (missile->s.weapon == WP_ROCKET_LAUNCHER)
	{//stop homing
		missile->e_ThinkFunc = thinkF_NULL;
	}
}