Jump to content

Stuck on a Force Power


Recommended Posts

What I'm trying to do is replicate the KotOR power "Stun" into JKA (to the right of "Mind Trick" in the link provided), by editing the ForceGrip code in the "wp_saber.cpp" file.

 

Like I said, I managed to put it in my Force arsenal, as well as the Datapad Menu, but that's as far as it went - Didn't even hold them in place.

Link to comment
void ForceStun( gentity_t *self )
{//FIXME: make enemy Jedi able to use this
	trace_t	tr;
	vec3_t	end, forward;
	gentity_t	*traceEnt = NULL;

	if ( self->health <= 0 )
	{
		return;
	}
	if ( !self->s.number && (cg.zoomMode || in_camera) )
	{
		return;
	}
	if ( self->client->ps.leanofs )
	{
		return;
	}

	if ( self->client->ps.forceGripEntityNum <= ENTITYNUM_WORLD )
	{
		if ( self->client->ps.forcePowerLevel[FP_STUN] > FORCE_LEVEL_1 )
		{
			self->client->ps.forcePowerDuration[FP_STUN] = level.time + 100;
			self->client->ps.weaponTime = 1000;
			if ( self->client->ps.forcePowersActive&(1<<FP_SPEED) )
			{
				self->client->ps.weaponTime = floor( self->client->ps.weaponTime * g_timescale->value );
			}
		}
		return;
	}

	if ( !WP_ForcePowerUsable( self, FP_STUN, 0 ) )
	{//can't use it right now
		return;
	}

	if ( self->client->ps.forcePower < 26 )
	{//need 20 to start, 6 to hold it for any decent amount of time...
		return;
	}

	if ( self->client->ps.weaponTime )
	{//busy
		return;
	}

	if ( self->client->ps.saberLockTime > level.time )
	{//FIXME: can this be a way to break out?
		return;
	}
	//Cause choking anim + health drain in ent in front of me
	NPC_SetAnim( self, SETANIM_TORSO, BOTH_FORCELIGHTNING_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
	self->client->ps.saberMove = self->client->ps.saberBounceMove = LS_READY;//don't finish whatever saber anim you may have been in
	self->client->ps.saberBlocked = BLOCKED_NONE;

	self->client->ps.weaponTime = 1000;
	if ( self->client->ps.forcePowersActive&(1<<FP_SPEED) )
	{
		self->client->ps.weaponTime = floor( self->client->ps.weaponTime * g_timescale->value );
	}

	AngleVectors( self->client->ps.viewangles, forward, NULL, NULL );
	VectorNormalize( forward );
	VectorMA( self->client->renderInfo.handLPoint, FORCE_GRIP_DIST, forward, end );
	
	if ( self->enemy )
	{//I have an enemy
		if ( !self->enemy->message
			&& !(self->flags&FL_NO_KNOCKBACK) )
		{//don't auto-pickup guys with keys
			if ( DistanceSquared( self->enemy->currentOrigin, self->currentOrigin ) < FORCE_GRIP_DIST_SQUARED )
			{//close enough to grab
				float minDot = 0.5f;
				if ( self->s.number < MAX_CLIENTS )
				{//player needs to be facing more directly
					minDot = 0.2f;
				}
				if ( InFront( self->enemy->currentOrigin, self->client->renderInfo.eyePoint, self->client->ps.viewangles, minDot ) ) //self->s.number || //NPCs can always lift enemy since we assume they're looking at them...?
				{//need to be facing the enemy
					if ( gi.inPVS( self->enemy->currentOrigin, self->client->renderInfo.eyePoint ) )
					{//must be in PVS
						gi.trace( &tr, self->client->renderInfo.eyePoint, vec3_origin, vec3_origin, self->enemy->currentOrigin, self->s.number, MASK_SHOT, (EG2_Collision)0, 0 );
						if ( tr.fraction == 1.0f || tr.entityNum == self->enemy->s.number )
						{//must have clear LOS
							traceEnt = self->enemy;
						}
					}
				}
			}
		}
	}
	if ( !traceEnt )
	{//okay, trace straight ahead and see what's there
		gi.trace( &tr, self->client->renderInfo.handLPoint, vec3_origin, vec3_origin, end, self->s.number, MASK_SHOT, (EG2_Collision)0, 0 );
		if ( tr.entityNum >= ENTITYNUM_WORLD || tr.fraction == 1.0 || tr.allsolid || tr.startsolid )
		{
			return;
		}

		traceEnt = &g_entities[tr.entityNum];
	}
//rww - RAGDOLL_BEGIN
#ifdef JK2_RAGDOLL_GRIPNOHEALTH
	if ( !traceEnt || traceEnt == self/*???*/ || traceEnt->bmodel || (traceEnt->NPC && traceEnt->NPC->scriptFlags & SCF_NO_FORCE) )
	{
		return;
	}
#else
//rww - RAGDOLL_END
	if ( !traceEnt || traceEnt == self/*???*/ || traceEnt->bmodel || (traceEnt->health <= 0 && traceEnt->takedamage) || (traceEnt->NPC && traceEnt->NPC->scriptFlags & SCF_NO_FORCE) )
	{
		return;
	}
//rww - RAGDOLL_BEGIN
#endif
//rww - RAGDOLL_END

	if ( traceEnt->m_pVehicle != NULL )
	{//is it a vehicle
		//grab pilot if there is one
		if ( traceEnt->m_pVehicle->m_pPilot != NULL 
			&& traceEnt->m_pVehicle->m_pPilot->client != NULL )
		{//grip the pilot
			traceEnt = traceEnt->m_pVehicle->m_pPilot;
		}
		else
		{//can't grip a vehicle
			return;
		}
	}
	if ( traceEnt->client )
	{
		if ( traceEnt->client->ps.forceJumpZStart )
		{//can't catch them in mid force jump - FIXME: maybe base it on velocity?
			return;
		}
		if ( traceEnt->client->ps.pullAttackTime > level.time )
		{//can't grip someone who is being pull-attacked or is pull-attacking
			return;
		}
		if ( !Q_stricmp("Yoda",traceEnt->NPC_type) )
		{
			Jedi_PlayDeflectSound( traceEnt );
			ForceThrow( traceEnt, qfalse );
			return;
		}

		if ( G_IsRidingVehicle( traceEnt ) 
			&& (traceEnt->s.eFlags&EF_NODRAW) )
		{//riding *inside* vehicle
			return;
		}

		switch ( traceEnt->client->NPC_class )
		{
		case CLASS_GALAKMECH://cant grip him, he's in armor
			G_AddVoiceEvent( traceEnt, Q_irand(EV_PUSHED1, EV_PUSHED3), Q_irand( 3000, 5000 ) );
			return;
			break;
		case CLASS_HAZARD_TROOPER://cant grip him, he's in armor
			return;
			break;
		case CLASS_ATST://much too big to grip!
		case CLASS_RANCOR://much too big to grip!
		case CLASS_WAMPA://much too big to grip!
		case CLASS_SAND_CREATURE://much too big to grip!
			return;
			break;
		//no droids either...?
		case CLASS_GONK:
		case CLASS_R2D2:
		case CLASS_R5D2:
		case CLASS_MARK1:
		case CLASS_MARK2:
		case CLASS_MOUSE://?
		case CLASS_PROTOCOL:
			//*sigh*... in JK3, you'll be able to grab and move *anything*...
			return;
			break;
		//not even combat droids?  (No animation for being gripped...)
		case CLASS_SABER_DROID:
		case CLASS_ASSASSIN_DROID:
			//*sigh*... in JK3, you'll be able to grab and move *anything*...
			return;
			break;
		case CLASS_PROBE:
		case CLASS_SEEKER:
		case CLASS_REMOTE:
		case CLASS_SENTRY:
		case CLASS_INTERROGATOR:
			//*sigh*... in JK3, you'll be able to grab and move *anything*...
			return;
			break;
		case CLASS_DESANN://Desann cannot be gripped, he just pushes you back instantly
		case CLASS_KYLE:
		case CLASS_TAVION:
		case CLASS_LUKE:
			Jedi_PlayDeflectSound( traceEnt );
			ForceThrow( traceEnt, qfalse );
			return;
			break;
		case CLASS_REBORN:
		case CLASS_SHADOWTROOPER:
		case CLASS_ALORA:
		case CLASS_JEDI:
			if ( traceEnt->NPC && traceEnt->NPC->rank > RANK_CIVILIAN && self->client->ps.forcePowerLevel[FP_STUN] < FORCE_LEVEL_2 )
			{
				Jedi_PlayDeflectSound( traceEnt );
				ForceThrow( traceEnt, qfalse );
				return;
			}
			break;
		}
		if ( traceEnt->s.weapon == WP_EMPLACED_GUN )
		{//FIXME: maybe can pull them out?
			return;
		}
		if ( self->enemy && traceEnt != self->enemy && traceEnt->client->playerTeam == self->client->playerTeam )
		{//can't accidently grip your teammate in combat
			return;
		}
//=CHECKABSORB===
		if ( -1 != WP_AbsorbConversion( traceEnt, traceEnt->client->ps.forcePowerLevel[FP_ABSORB], self, FP_STUN, self->client->ps.forcePowerLevel[FP_STUN], forcePowerNeeded[self->client->ps.forcePowerLevel[FP_STUN]]) )
		{
			//WP_ForcePowerStop( self, FP_STUN );
			return;
		}
//===============
	}
	else
	{//can't grip non-clients... right?
		//FIXME: Make it so objects flagged as "grabbable" are let through
		//if ( Q_stricmp( "misc_model_breakable", traceEnt->classname ) || !(traceEnt->s.eFlags&EF_BOUNCE_HALF) || !traceEnt->physicsBounce )
		{
			return;
		}
	}

	WP_ForcePowerStart( self, FP_STUN, 20 );
	//FIXME: rule out other things?
	//FIXME: Jedi resist, like the push and pull?
	self->client->ps.forceGripEntityNum = traceEnt->s.number;
	if ( traceEnt->client ) 
	{
		Vehicle_t *pVeh;
		if ( ( pVeh = G_IsRidingVehicle( traceEnt ) ) != NULL )
		{//riding vehicle? pull him off!
			//FIXME: if in an AT-ST or X-Wing, shouldn't do this... 
			//pull him off of it
			//((CVehicleNPC *)traceEnt->NPC)->Eject( traceEnt );
			pVeh->m_pVehicleInfo->Eject( pVeh, traceEnt, qtrue );
			//G_DriveVehicle( traceEnt, NULL, NULL );
		}
		G_AddVoiceEvent( traceEnt, Q_irand(EV_PUSHED1, EV_PUSHED3), 2000 );
		if ( self->client->ps.forcePowerLevel[FP_STUN] > FORCE_LEVEL_2 || traceEnt->s.weapon == WP_SABER )
		{//if we pick up & carry, drop their weap
			if ( traceEnt->s.weapon 
				&& traceEnt->client->NPC_class != CLASS_ROCKETTROOPER
				&& traceEnt->client->NPC_class != CLASS_VEHICLE
				&& traceEnt->client->NPC_class != CLASS_HAZARD_TROOPER
				&& traceEnt->client->NPC_class != CLASS_TUSKEN
				&& traceEnt->client->NPC_class != CLASS_BOBAFETT
				&& traceEnt->client->NPC_class != CLASS_ASSASSIN_DROID
				&& traceEnt->s.weapon != WP_CONCUSSION	// so rax can't drop his
				) 
			{
				if ( traceEnt->client->NPC_class == CLASS_BOBAFETT )
				{//he doesn't drop them, just puts it away
					ChangeWeapon( traceEnt, WP_MELEE );
				}
				else if ( traceEnt->s.weapon == WP_MELEE )
				{//they can't take that away from me, oh no...
				}
				else if ( traceEnt->NPC
					&& (traceEnt->NPC->scriptFlags&SCF_DONT_FLEE) )
				{//*SIGH*... if an NPC can't flee, they can't run after and pick up their weapon, do don't drop it
				}
				else if ( traceEnt->s.weapon != WP_SABER )
				{
					WP_DropWeapon( traceEnt, NULL );
				}
				else
				{
					//turn it off?
					traceEnt->client->ps.SaberDeactivate();
					G_SoundOnEnt( traceEnt, CHAN_WEAPON, "sound/weapons/saber/saberoffquick.wav" );
				}
			}
		}
		//else FIXME: need a one-armed choke if we're not on a high enough level to make them drop their gun
		VectorCopy( traceEnt->client->renderInfo.headPoint, self->client->ps.forceGripOrg );
	}
	else
	{
		VectorCopy( traceEnt->currentOrigin, self->client->ps.forceGripOrg );
	}
	self->client->ps.forceGripOrg[2] += 48;//FIXME: define?
	if ( self->client->ps.forcePowerLevel[FP_STUN] < FORCE_LEVEL_2 )
	{//just a duration
		self->client->ps.forcePowerDebounce[FP_STUN] = level.time + 250;
		self->client->ps.forcePowerDuration[FP_STUN] = level.time + 5000;
		
		if ( self->m_pVehicle && self->m_pVehicle->m_pVehicleInfo->Inhabited( self->m_pVehicle ) )
		{//empty vehicles don't make gripped noise
			traceEnt->s.loopSound = G_SoundIndex( "sound/weapons/force/stun.mp3" );
		}
	}
	else
	{
		if ( self->client->ps.forcePowerLevel[FP_STUN] == FORCE_LEVEL_2 )
		{//lifting sound?  or always?
		}
		//if ( traceEnt->s.number )
		{//picks them up for a second first
			self->client->ps.forcePowerDebounce[FP_STUN] = level.time + 1000;
		}
		/*
		else
		{//player should take damage right away
			self->client->ps.forcePowerDebounce[FP_STUN] = level.time + 250;
		}
		*/
	// force grip sound should only play when the target is alive?
	//	if (traceEnt->health>0)
	//	{
			self->s.loopSound = G_SoundIndex( "sound/weapons/force/stun.mp3" );
	//	}
	}
}

 

 

Link to comment

1.) By enums, do you mean this:

 

 

static powerEnum_t powerEnums[MAX_POWER_ENUMS] = 
{ // Light powers
"absorb", FP_ABSORB,
"heal", FP_HEAL,
"mindtrick", FP_TELEPATHY,
"protect", FP_PROTECT,
"stun", FP_STUN,
 
// Core powers
"jump", FP_LEVITATION,
"pull", FP_PULL,
"push", FP_PUSH,
"sense", FP_SEE,
"speed", FP_SPEED,
"sabdef", FP_SABER_DEFENSE,
"saboff", FP_SABER_OFFENSE,
"sabthrow", FP_SABERTHROW,
 
// Dark powers
"drain", FP_DRAIN,
"grip", FP_GRIP,
"lightning", FP_LIGHTNING,
"rage", FP_RAGE,
};
 
 
2 & 3.) : *Blew my mind*
Link to comment
This one?

 

typedef enum

{

FP_FIRST = 0,//marker

FP_HEAL = 0,//instant

FP_LEVITATION,//hold/duration

FP_SPEED,//duration

FP_PUSH,//hold/duration

FP_PULL,//hold/duration

FP_TELEPATHY,//instant

FP_GRIP,//hold/duration

FP_LIGHTNING,//hold/duration

FP_SABERTHROW,

FP_SABER_DEFENSE,

FP_SABER_OFFENSE,

//new Jedi Academy powers

FP_RAGE,//duration - speed, invincibility and extra damage for short period, drains your health and leaves you weak and slow afterwards.

FP_PROTECT,//duration - protect against physical/energy (level 1 stops blaster/energy bolts, level 2 stops projectiles, level 3 protects against explosions)

FP_ABSORB,//duration - protect against dark force powers (grip, lightning, drain - maybe push/pull, too?)

FP_DRAIN,//hold/duration - drain force power for health

FP_SEE,//duration - detect/see hidden enemies

FP_REPULSE,

FP_DESTRUCTION,

FP_DEADLYSIGHT,

FP_BLIND,

FP_STUN,

FP_BREACH,

NUM_FORCE_POWERS

} forcePowers_t;

 

 

I haven't really gotten to the other new powers in the list, just finished moving my desktop back into my house...
Link to comment

Would changing this do any good? (cg_local.h)

 

 
#define MAX_SHOWPOWERS 18
extern int showPowers[MAX_SHOWPOWERS]; 
extern char *showPowersName[MAX_SHOWPOWERS];
extern int force_icons[NUM_FORCE_POWERS];
#define MAX_DPSHOWPOWERS 22
Link to comment
#define MAX_SHOWPOWERS NUM_FORCE_POWERS-5

extern int showPowers[MAX_SHOWPOWERS]; 

extern char *showPowersName[MAX_SHOWPOWERS];

extern int force_icons[NUM_FORCE_POWERS];

#define MAX_DPSHOWPOWERS NUM_FORCE_POWERS-1

 

If you meant this, the result I got out of it was the "too many initializers" error, causing one of the files to fail.
Link to comment

This also happened with the original entry when I tried to add the power(s):

 

 

#define MAX_SHOWPOWERS 12
extern int showPowers[MAX_SHOWPOWERS]; 
extern char *showPowersName[MAX_SHOWPOWERS];
extern int force_icons[NUM_FORCE_POWERS];
#define MAX_DPSHOWPOWERS 16
 
When I changed the entries to 18-22, it didn't have any problems from there.
Link to comment
With your suggestion (underlines for errors):

 

 

int showPowers[MAX_SHOWPOWERS] = 

{

FP_ABSORB,

FP_HEAL,

FP_PROTECT,

FP_TELEPATHY,

FP_BLIND,

FP_STUN,

 

FP_SPEED,

FP_PUSH,

FP_PULL,

FP_SEE,

FP_REPULSE,

FP_BREACH,

 

FP_DRAIN,

FP_LIGHTNING,

FP_RAGE,

FP_GRIP,

FP_DESTRUCTION,

FP_DEADLYSIGHT,

};

 

char *showPowersName[MAX_SHOWPOWERS] = 

{

"SP_INGAME_ABSORB2",

"SP_INGAME_HEAL2",

"SP_INGAME_PROTECT2",

"SP_INGAME_MINDTRICK2",

"SP_INGAME_BLIND2",

"SP_INGAME_STUN2",

 

"SP_INGAME_SPEED2",

"SP_INGAME_PUSH2",

"SP_INGAME_PULL2",

"SP_INGAME_SEEING2",

"SP_INGAME_REPULSE2",

"SP_INGAME_BREACH2",

 

"SP_INGAME_DRAIN2",

"SP_INGAME_LIGHTNING2",

"SP_INGAME_DARK_RAGE2",

"SP_INGAME_GRIP2",

"SP_INGAME_DESTRUCTION2",

"SP_INGAME_DEADLYSIGHT2",

};

 

// Keep these with groups light side, core, and dark side

int showDataPadPowers[MAX_DPSHOWPOWERS] = 

{

// Light side

FP_ABSORB,

FP_HEAL,

FP_PROTECT,

FP_TELEPATHY,

FP_BLIND,

FP_STUN,

 

// Core Powers

FP_LEVITATION,

FP_SPEED,

FP_PUSH,

FP_PULL,

FP_SABERTHROW,

FP_SABER_DEFENSE,

FP_SABER_OFFENSE,

FP_SEE,

FP_REPULSE,

FP_BREACH,

 

//Dark Side

FP_DRAIN,

FP_LIGHTNING,

FP_RAGE,

FP_GRIP,

FP_DESTRUCTION,

FP_DEADLYSIGHT,

 

};

 

 

 

With my settings:

 

 


int showPowers[MAX_SHOWPOWERS] = 

{

FP_ABSORB,

FP_HEAL,

FP_PROTECT,

FP_TELEPATHY,

FP_BLIND,

FP_STUN,

 

FP_SPEED,

FP_PUSH,

FP_PULL,

FP_SEE,

FP_REPULSE,

FP_BREACH,

 

FP_DRAIN,

FP_LIGHTNING,

FP_RAGE,

FP_GRIP,

FP_DESTRUCTION,

FP_DEADLYSIGHT,

};

 

char *showPowersName[MAX_SHOWPOWERS] = 

{

"SP_INGAME_ABSORB2",

"SP_INGAME_HEAL2",

"SP_INGAME_PROTECT2",

"SP_INGAME_MINDTRICK2",

"SP_INGAME_BLIND2",

"SP_INGAME_STUN2",

 

"SP_INGAME_SPEED2",

"SP_INGAME_PUSH2",

"SP_INGAME_PULL2",

"SP_INGAME_SEEING2",

"SP_INGAME_REPULSE2",

"SP_INGAME_BREACH2",

 

"SP_INGAME_DRAIN2",

"SP_INGAME_LIGHTNING2",

"SP_INGAME_DARK_RAGE2",

"SP_INGAME_GRIP2",

"SP_INGAME_DESTRUCTION2",

"SP_INGAME_DEADLYSIGHT2",

};

 

// Keep these with groups light side, core, and dark side

int showDataPadPowers[MAX_DPSHOWPOWERS] = 

{

// Light side

FP_ABSORB,

FP_HEAL,

FP_PROTECT,

FP_TELEPATHY,

FP_BLIND,

FP_STUN,

 

// Core Powers

FP_LEVITATION,

FP_SPEED,

FP_PUSH,

FP_PULL,

FP_SABERTHROW,

FP_SABER_DEFENSE,

FP_SABER_OFFENSE,

FP_SEE,

FP_REPULSE,

FP_BREACH,

 

//Dark Side

FP_DRAIN,

FP_LIGHTNING,

FP_RAGE,

FP_GRIP,

FP_DESTRUCTION,

FP_DEADLYSIGHT,

 

};

 

Link to comment
#define MAX_SHOWPOWERS NUM_FORCE_POWERS-4

extern int showPowers[MAX_SHOWPOWERS]; 

extern char *showPowersName[MAX_SHOWPOWERS];

extern int force_icons[NUM_FORCE_POWERS];

#define MAX_DPSHOWPOWERS NUM_FORCE_POWERS-1

 

Same result: 1 succeeded, 1 failed, 1 up-to-date
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...