Jump to content

Ask me anything about the Jedi source code


Recommended Posts

Guest Redemption
Posted

@@Asgarath83 - Hi pal, I thought you might be able to help :) WP_SaberParry is in the same file but lower down in it. 

qboolean WP_SaberParry( gentity_t *victim, gentity_t *attacker )
{
	if ( !victim || !victim->client || !attacker )
	{
		return qfalse;
	}

	if ( victim->s.number || g_saberAutoBlocking->integer || victim->client->ps.saberBlockingTime > level.time )
	{//either an NPC or a player who is blocking
		if ( !PM_SaberInTransitionAny( victim->client->ps.saberMove )
			&& !PM_SaberInBounce( victim->client->ps.saberMove )
			&& !PM_SaberInKnockaway( victim->client->ps.saberMove ) )
		{//I'm not attacking, in transition or in a bounce or knockaway, so play a parry
			WP_SaberBlockNonRandom( victim, saberHitLocation, qfalse );
		}
		victim->client->ps.saberEventFlags |= SEF_PARRIED;

		//since it was parried, take away any damage done
		//FIXME: what if the damage was done before the parry?
		WP_SaberClearDamageForEntNum( victim->s.number );

		//tell the victim to get mad at me
		if ( victim->enemy != attacker && victim->client->playerTeam != attacker->client->playerTeam )
		{//they're not mad at me and they're not on my team
			G_ClearEnemy( victim );
			G_SetEnemy( victim, attacker );
		}
		return qtrue;
	}
	return qfalse;
}
Posted

mmm... first off, are you pretty sure is a good gameplay choice make Galak mech and shadowtrooper immune to saber damage with a suit that can parry the swings or saber throws? because shadowtrooper can push explosive weapons and deflect blaster with saber, so with this feature is pratically an invincible adversary. if you wanna add a simple saber resistance to shadow trooper, like hazard trooper class, you need just to go into G_combat.cpp and add this low 

if ( client && client->NPC_class == CLASS_SHADOWTROOPER )
    {
        if ( mod == MOD_SABER
            && damage>0
            && !(dflags&DAMAGE_NO_PROTECTION) )
        {
            damage /= 9;
        }
    }

under the same condition related hazardtrooper.

Edit, wait a moment. i am checking now...

 

you are editing a function that is previous in file of function you are calling. so when compiler build the solution and read the file, not found the function, because the void is after your add.

mmm i tryed to cut and paste the saberparry function upper the file, but i get error about other functions. is not easy to do that, because require to re-order all the functions of wp_saber.cpp for allows to the compiler of read all the definition in the new right sequence. should be a long task and i cannot help you in that. :\

 

however, if i remember fine, boba fett armor can parry and deflect the saber throws. maybe you can do a workaround about this feature.

 

mmmm yep i got that

 

if ( attacker && attacker->client && attacker->client->ps.saberInFlight )
        {//thrown saber hit something
            if ( ( hitEnt && hitEnt->client && hitEnt->health > 0 && ( hitEnt->client->NPC_class == CLASS_DESANN || !Q_stricmp("Yoda",hitEnt->NPC_type) || hitEnt->client->NPC_class == CLASS_LUKE || hitEnt->client->NPC_class == CLASS_BOBAFETT || (hitEnt->client->ps.powerups[PW_GALAK_SHIELD] > 0) ) ) ||
                 ( owner && owner->client && owner->health > 0 && ( owner->client->NPC_class == CLASS_DESANN || !Q_stricmp("Yoda",owner->NPC_type) || owner->client->NPC_class == CLASS_LUKE || (owner->client->ps.powerups[PW_GALAK_SHIELD] > 0) ) ) )
            {//Luke and Desann slap thrown sabers aside
                //FIXME: control the direction of the thrown saber... if hit Galak's shield, bounce directly away from his origin?
                WP_SaberKnockaway( attacker, &tr );
add shadowtrooper class in this if field and shadowtrooper become invincible to saber throw. after you can add a resistance to saber damage in g_combat of 90% and that should be okay.
Guest Redemption
Posted

Hi , I've edited g_combat and made it so that Galak and Shadows don't take damage from lightsabers and such already, I just need to see the lightsaber bounce back as in parry to let people know that the saber is ineffective... I think its a good gameplay mechanic instead of reduced damage by the saber. 

 

Thinking goes, when you finally meet these characters you are already starting to feel pretty tough, so how about making you have to use other methods i.e' force powers and heavy weapons... Just differentiates the enemies a bit more :) It does say that, that armour seems to resist my lightsaber in the game.

 

How are you anyways @@Asgarath83?

Asgarath83 likes this
Posted

Hi , I've edited g_combat and made it so that Galak and Shadows don't take damage from lightsabers and such already, I just need to see the lightsaber bounce back as in parry to let people know that the saber is ineffective... I think its a good gameplay mechanic instead of reduced damage by the saber. 

 

Thinking goes, when you finally meet these characters you are already starting to feel pretty tough, so how about making you have to use other methods i.e' force powers and heavy weapons... Just differentiates the enemies a bit more :) It does say that, that armour seems to resist my lightsaber in the game.

 

How are you anyways @@Asgarath83?

 

lol in that moment i am little stressed and tired. there a problem into my code that become me little crazy.

about your problem: you can do that working on MOD_SABER too. if damage of MOD_SABER is *= 0, like demp2 code for assassin droid for these class, they become invincible to saber. about saber parry... i am cannot know how can i help you about a super parry code, but as you can see, there is a workaround about the boba fett deflecting saber throw code that you can use for prevent to hit these classes with saber throws.

Guest Redemption
Posted

Yeah, its a tricky one... but I'll keep at it. Thank you for you're help. You seem to be making loads of progress with you're coding mods.

 

Impressive... Most impressive

 

Take care pal

Cerez and Asgarath83 like this
Posted

Yeah, its a tricky one... but I'll keep at it. Thank you for you're help. You seem to be making loads of progress with you're coding mods.

 

Impressive... Most impressive

 

Take care pal

Thanks, but there are coder more good of me ^_^ good luck with your mod and have fun. :)

Posted

@@MGummelt

 

sorry if i ask but maybe you can give me a little incipit also about my trouble.
i am doing with dusty help a special AI that allow to npc to:
- switch weapons and use altfire randomly in
fight. they can also use force power when they shoot player! it's pretty fun because player
can be force gripped when is shooted by a cultist armored with WP_FLECHETTE, for
example.

so, enemies use all arsenal inside the NPCfile of the NPC for fight the player. this AI is based on cultist commando's dusty
and bobafett AI code. it's work fine, but i have a serious probem concerned sabers. basically, i have a NPC with two weapons: a
variant of WP_FLECHETTE (WP_CANNON) and WP_SABER with saber dual_2. npc should randomly switch and alternate the
flechette \ cannon fight mode with saberist mode, switching by flechette and saber. and yes, it does that. but there is a little

problem: when NPC switch weapon to saber, saber model is basically invisible and also not make any kind of damage (because saber have not a damagetrace, because model of saber is not respawned) , so NPC AI workaround that acting like a reborn cultist, using simply force powers and "hands" as weapon. he not do saber swings, but i see he does the saber taunts...
and sometimes i ears in game the sound of saberon , so the sabere there is... but the moel is not displayed in game.
i am trying to fixing the thing working on NPC_combat about a new version of NPC_changeweapon code related to dusty's patch. 

but i have not much success.

how i need to do for allow to NPCs to switch correctly by a shooting weapon to a saber weapon?

this is the npc switch weapon function code, it's all morning i am trying to fix that and i am little tired.

 

 

void NPC_ChangeWeapon( int newWeapon )
{

    qboolean    changing = qfalse;
    if ( newWeapon != NPC->client->ps.weapon )
    {
        changing = qtrue;
    }
    if ( changing )
    {
        G_RemoveWeaponModels( NPC );
    }
    ChangeWeapon( NPC, newWeapon );
    if ( changing && NPC->client->ps.weapon != WP_NONE )
    {
        if ( NPC->client->ps.weapon == WP_SABER )
        {
            WP_SaberAddG2SaberModels( NPC );
        }
        else
        {
            G_CreateG2AttachedWeaponModel( NPC, weaponData[NPC->client->ps.weapon].weaponMdl, NPC->handRBolt, 0 );
        }
    }
}

sorry if i ask it, but i am in that empasse by some days.

Guest Redemption
Posted

Hey, just to let people know that maybe interested, I think I've got it to work :)

Here's where @@MGummelt pointed me to and put this piece of code:

if (victim->client && (victim->client->NPC_class == CLASS_GALAKMECH || victim->client->NPC_class == CLASS_SHADOWTROOPER))
				{
					WP_SaberParry(victim, attacker);
					return didDamage;
				}

By pointing to play an animation seems to have done the trick!!!

if (victim->client && (victim->client->NPC_class == CLASS_GALAKMECH || victim->client->NPC_class == CLASS_SHADOWTROOPER))
				{
					PM_SetSaberMove(LS_PARRY_LL);
					return didDamage;
				}

It's not finished because I'd prefer it to bounce off where I hit, instead of looking off. The idea is here I just would like to hear from the community on how to proceed... I'm thinking that hit location will play an appropriate animation. 

Also, putting the finishing touches to lightning block

Cerez and Asgarath83 like this
Posted

Hey, just to let people know that maybe interested, I think I've got it to work :)

Here's where @@MGummelt pointed me to and put this piece of code:

if (victim->client && (victim->client->NPC_class == CLASS_GALAKMECH || victim->client->NPC_class == CLASS_SHADOWTROOPER))
				{
					WP_SaberParry(victim, attacker);
					return didDamage;
				}

By pointing to play an animation seems to have done the trick!!!

if (victim->client && (victim->client->NPC_class == CLASS_GALAKMECH || victim->client->NPC_class == CLASS_SHADOWTROOPER))
				{
					PM_SetSaberMove(LS_PARRY_LL);
					return didDamage;
				}

It's not finished because I'd prefer it to bounce off where I hit, instead of looking off. The idea is here I just would like to hear from the community on how to proceed... I'm thinking that hit location will play an appropriate animation. 

Also, putting the finishing touches to lightning block

remember me when Vader lock with hand blasters of Han Solo on empire strikes back. nice idea! :D

Posted

The random number generator has no effect on saber blocking or damages VS humans in normal MP codebase.

 

What do you mean? w_saber.c:CheckSaberDamage() is full of Q_irand() calls.

Posted

What do you mean? w_saber.c:CheckSaberDamage() is full of Q_irand() calls.

Ah yes, but not susceptible to being problematic like the ones that are inconsistent using the RandFloat function atop that file which is for deflecting and pushing projectiles away.

Posted

Ideally, if you could replicate the normal behavior in a debug build of the original games etc and get the outputs with saber interactions and compare them to a current build that might be helpful but I'm not sure a debug build of the older VS would produce the same results, either.  Mostly you'd just want to see what the assembly output looks like and the floats in real time and where they seem to drop off.  Has anyone ever actually tested SP saber stuff compared to base?  Because I'm thinking it might be tri_col_test related.

Posted

Hi everybody

 

Hi sir

 

 

Let me tell you something. You have coded two of the best games I ever played. Jedi Academy and Outcast did my childhood, my teenage years and my young adult life on videogames.

 

I don't know how much I can thank you, and what can I do, but you have made gold. Still playing and modding for this JA, 14 years after the release. 

 

 

I think I know every single cheat code, every single g_something of SP game, every single trick of the "playermodel" function and now coding, I understand what I have played. And I think I will play this game until the end of computers.

 

 

I am creating mods for SP, with 45, 55 maps, it requiers me years. But the biggest project of all time we all want here is Jedi Knight III. We want Kyle Katarn to come back. And If I had enough time and energy, I would have contacted the best mappers, modelers, coders and would have launched the project, because I am the kind of modders who finish what they start. 

 

Seeing you here Sir, is like having the announcement of JKIII. It show us that, 14 years later, peoples who made the dream still care about Jedi Knight, and I think that means a lot to all of us.

 

 

Thank you for all.

Smoo, MGummelt and Asgarath83 like this
Posted

Ah yes, but not susceptible to being problematic like the ones that are inconsistent using the RandFloat function atop that file which is for deflecting and pushing projectiles away.

 

The idea was that internal PRNG implementation was very weak and consecutive call could produce recognizable sequences regardless of current seed value, but now I see that it was fixed in Jedi Academy code, so this kind of falls. At least for JA. Still going to collect some data on JK2 and check this hypothesis.

 

Mostly you'd just want to see what the assembly output looks like and the floats in real time and where they seem to drop off

 

Maybe this is what you'd want to do for JA, but as I explained in JK2 it's not the issue and there are perceived mod discrepancies too. I'm personally interested in JK2 case, just hoping the core reason may be the same in both games.

Posted

Let me explain this more in depth (concerns only JK2)

Current JK2 QVM rand() implementation uses a linear congruential generator algorithm and returns LOWEST bits of calculated value:

int rand( void ) {
    randSeed = (69069 * randSeed + 1);
    return randSeed & 0x7fff;
}

Unfortunately lowest bits have very short periods - at most 2^n for nth bit. For example subsequent (rand() & 1) calls yield (1, 0, 1, 0, 1, 0…) sequence. Now consider this simplified code example:

if (rand() & 1) {
    SaberBlock();
    if (rand() & 1) {
        SaberParry();
    }
}

Of course SaberParry() never actually happens, despite the developer's intent. This is simplified and over-dramatized, but this type of unintended correlations surely exist in JK2 code due to this rand() implementation. Also consider that players who've never seen the code are aware that parry never happens right after block. One could say that they "recognize pattern" (although here it's just a dead code, you can imagine more complex and not 0/1 correlations).

 

Now examine same code segment in a mod:

if (rand() & 1) {
    SaberBlock();
    saberColor = rand();
    if (rand() & 1) {
        SaberParry();
    }
}

The situation changes diametrically even though a mod developer thought he wasn't altering block/parry behaviour.

Posted

Even if that were true (I'm not saying it's not, it sounds very plausible!), people still complain about altered saber blocks when simply recompiling the sdk code with no changes. Or made changes in completely unrelated areas of code.

Smoo likes this
Posted

JKA uses a different rand (based on MSVC) implementation in many places. I'm not sure if we changed it further or not as far as sabers are concerned. Q_irand / Q_flrand.

 

Also mind you, Rand_Init is only ever called in the engine and not for mod code. (JKA)

Posted

@@MGummelt - Hello again. I've tried my hand at coding it in but get this error:

Error 4 error C3861: 'WP_SaberParry': identifier not found

You may need to declare the WP_SaberParry() function above your function if the actual definition of the function is lower in the .cpp file.  You can see some other examples of that at the top of the wp_saber.cpp file:

void WP_SaberDrop( gentity_t *self, gentity_t *saber );
qboolean WP_SaberLose( gentity_t *self, vec3_t throwDir );
void WP_SaberReturn( gentity_t *self, gentity_t *saber );
void WP_SaberBlock( gentity_t *saber, vec3_t hitloc, qboolean missleBlock );
void WP_SaberBlockNonRandom( gentity_t *self, vec3_t hitloc, qboolean missileBlock );

Just add this there, too:

qboolean WP_SaberParry( gentity_t *victim, gentity_t *attacker );

Note: if your function is in a different file altogether, you need to extern it like so:

extern qboolean WP_SaberParry( gentity_t *victim, gentity_t *attacker );
Posted

problem: when NPC switch weapon to saber, saber model is basically invisible and also not make any kind of damage (because saber have not a damagetrace, because model of saber is not respawned) 

 

What model are you using for the saber they use?  Can you post your .npc file and the .saber file for the saber you're using?  Are you sure that saber model is working properly and included in your assets?

Posted

Hey, just to let people know that maybe interested, I think I've got it to work :)

Here's where @@MGummelt pointed me to and put this piece of code:

if (victim->client && (victim->client->NPC_class == CLASS_GALAKMECH || victim->client->NPC_class == CLASS_SHADOWTROOPER))
				{
					WP_SaberParry(victim, attacker);
					return didDamage;
				}

By pointing to play an animation seems to have done the trick!!!

if (victim->client && (victim->client->NPC_class == CLASS_GALAKMECH || victim->client->NPC_class == CLASS_SHADOWTROOPER))
				{
					PM_SetSaberMove(LS_PARRY_LL);
					return didDamage;
				}

It's not finished because I'd prefer it to bounce off where I hit, instead of looking off. The idea is here I just would like to hear from the community on how to proceed... I'm thinking that hit location will play an appropriate animation. 

Also, putting the finishing touches to lightning block

 

Yeah, that's basically short-cutting all the parry logic that picks the right parry animation for you based on what's happening.  You should be able to call WP_SaberParry() itself if you just declare it at the top of the file like I showed above.

Posted

problem: when NPC switch weapon to saber, saber model is basically invisible

 

So I'm guessing your problem is that your NPC's .npc def doesn't have a saber declared as his weapon?  If not, he will never create a saber in his ent->client->ps.saber, never initialize any of that data, never create the G2 models or anything.  You probably need to give him a saber as a weapon in his .npc.  This this bit of code in NPC_SetMiscDefaultData() in NPC_spawn.cpp will initialize it all:

	if ( ent->client->ps.saber[0].type != SABER_NONE 
		&& (!(ent->NPC->aiFlags&NPCAI_MATCHPLAYERWEAPON)||!ent->weaponModel[0]) )
	{//if I'm equipped with a saber, initialize it (them)
		ent->client->ps.SaberDeactivate();
		ent->client->ps.SetSaberLength( 0 );
		WP_SaberInitBladeData( ent );
		if ( ent->client->ps.weapon == WP_SABER )
		{//this is our current weapon, add the models now
			WP_SaberAddG2SaberModels( ent );
		}
		Jedi_ClearTimers( ent );
	}

Alternatively, you could try calling WP_SetSaber() in WP_SaberLoad.cpp before calling NPC_ChangeWeapon().  That's what's called when you use the saber console command or ICARUS command to give someone a saber.  That might work, too.

Posted

Yes, total conversion. Thanks :D

@@Penekowski

is also possible to add a different kind of damage to a specific saber you create on SAB files:

<snip> 

doing something like that on wp_saber.cpp, you can create a specific saber (later you add this on ext_data/sabers folder. that inflict special damage and damage effect to enemies with custom MOD. so you can do same saber that is deadly against droid because inflicting damage with MOD_DEMP2 . otherwise you can add new Mods and set on g_combat for be deadly against jedi, sith or force users, and so you can get sabers inbued with Light side of force and other with dark side.

you can see into the example tree a black hole \ dark sabers, an electric saber that electrocuted enemy hitted, and a disgregator saber. enemy killed by MOD_SNIPER die with body disintegration, like disruptor rifle. :)

 

Yeah, I mean - if you don't like how you're doing it now, I suppose you could add another field to the .sab file and parse it in WP_SaberParseParms(), then store it on the saberInfo_t struct in q_shared.h (keep in mind that changing this struct will invalidate old save data).

 

So you could add a methodOfDamage field to saberInfo_t and then check that instead of fullName.  

Posted

Another source code (and scripting) related question comes to mind:

 

Is it possible to set and retrieve values from CVARs in ICARUS?

 

The following code snippet crashes the game when retrieving the value from cvar_sex (the player is female to start with):

 

declare( STRING, "playergen" );

if ( get(STRING, "cvar_sex") = "m" )
{
	set( "cvar_sex", get(STRING, "playergen") );
	free( "playergen" );
}
else
{
	set( "playergen", get(STRING, "cvar_sex") );
	set( "cvar_sex", "m" );
}

 

No, if I recall we didn't want to give designers the ability to access any cvar they wanted - that would just be chaos.  It would open up a bunch of features to them that we didn't intend, they didn't need and which they wouldn't entirely know the effects of.  And some would work in development (like cheats) but not release.  Instead if they needed a specific command to do something a cvar or console command could do, we wrote an ICARUS command for it.

 

However, I imagine something like this could fairly easily be written.  At least, someone could probably write a function to stuff a command to the console (like "\set g_sex f") or call Cvar_Set and Cvar_Get...

Cerez likes this

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...