Fair Strides

No More Messengers After Xor Ambush -- FIXED!!!

18 posts in this topic

The bug commonly referred to as the "Juhani Quest Glitch" has officially been fixed.

 

With the help of LiliArch, Kexikus, and several other people, I've managed to fix this long-standing bug in the game, and here's the bug, how the bug is caused, how to fix it, and how we found it:

 

The Bug:

 

Whenever you follow Juhani's personal dialog far enough along, you will be approached by a Twilek named Xor. He will take an interest in Juhani, but is forced to leave disappointed and angry. Later, he ambushes you outside your ship if Juhani is present, and will be dead when all is said and done.

 

From that first moment when you get approached by Xor, you will no longer be able to be approached by any more messengers, effectively stopping the advance of others' personal quests and blocking you off from a shop later in the game.

 

Because of the loss of this store, most players have learned to hold of on delving too deep into Juhani's past until later on, after the store is open.

 

The Cause:

 

The bug is caused simply because the game checks that the value of the global number K_XOR_AMBUSH is either 0 or greater than 2 when determining whether to have any messengers approach you.

 

K_XOR_AMBUSH is set to 1 after Xor talks to you and takes an interest in Juhani. It is set to 2 after he attacks you later on.

 

But it is never set to 3 after the attack is done!

 

The Fix:

 

You guessed it: you need to set the global number K_XOR_AMBUSH to 3 after Xor dies. This will allow other messengers to approach you and allow you access to a store later on.

 

The Discovery:

 

While looking into this bug, I went searching through the game's files for how the messengers were spawned and determined. I found out that each planet had one or two scripts for this, but not all could be decompiled. By examining the ones that could be decompiled, I was able to track the code that handles everything to k_inc_utility.nss in KotOR 1's scripts.bif.

 

The relevant code from that file:

 

//::///////////////////////////////////////////////
//:: Spawn Messenger
//:: Copyright © 2002 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Determines which messenger to spawn in for a specific planet.
    Uses the waypoint K_MESSENGER_SPAWN to determine where to place an incoming messenger

    Carth: KOR_DANEL == 1. Messenger = Jordo.
    Bastila: K_SWG_HELENA == 1. Messenger = Malare.
    Mission: Mis_MissionTalk == 5  Messenger = Lena
    Canderous: G_CAND_STATE == 8, G_CAND_PLOT == 0, K_CURRENT_PLANET != 35.  Messenger = Jagi
    Juhani: G_JUHANIH_STATE == 7, G_JUHANI_PLOT == 0. Messenger = Xor
    
    Endar Spire     5
    Taris           10
    Dantooine       15
    --Kashyyk       20
    --Manaan        25
    --Korriban      30
    --Tatooine      35
    Leviathan       40
    Unknown World   45
    Star Forge      50
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Sept 26, 2002
//:://////////////////////////////////////////////

void UT_SpawnMessenger()
{
    object oPC = GetFirstPC();
    object oWay = GetWaypointByTag("K_MESSENGER_SPAWN");
    object oNPC;
    int nGlobal_1, nGlobal_2;
    location lLocal;
    int bConditional = FALSE;
    int nXor = GetGlobalNumber("K_XOR_AMBUSH");

    //Do not fire any messenger plots on Kashyyyk if Chuundar is dead
    if(GetGlobalNumber("K_CURRENT_PLANET") == 20)
    {
        bConditional = GetGlobalBoolean("kas_ChuundarDead");
    }
    if(bConditional == FALSE)
    {
        if(nXor == 0 || nXor > 2)
        {
            if(GetIsObjectValid(oWay))
            {
                lLocal = GetLocation(oWay);

                if(IsNPCPartyMember(NPC_BASTILA) &&
                   GetGlobalBoolean("K_MESS_BASTILA") == FALSE &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 25 &&
                   GetGlobalNumber("K_SWG_HELENA") == 1)
                {
                        SetGlobalBoolean("K_MESSENGER_AVAILABLE", FALSE);
                        SetGlobalBoolean("K_MESS_BASTILA", TRUE);
                        oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_malare", lLocal);
                        NoClicksFor(2.2);
                        DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                        //DelayCommand(2.0, UT_NPC_InitConversation(GetTag(oNPC)));
                        return;
                }
                if(IsNPCPartyMember(NPC_CARTH) &&
                   //MODIFIED by Preston Watamaniuk on May 13, 2003
                   //Added a check to make sure the Sith Acadamy is not closed before spawning in Jordo.
                   GetGlobalBoolean("KOR_END_HOSTILE") == FALSE &&
                   GetGlobalBoolean("K_MESS_CARTH") == FALSE &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 30 &&
                   GetGlobalNumber("KOR_DANEL") == 1)
                {
                        SetGlobalBoolean("K_MESSENGER_AVAILABLE", FALSE);
                        SetGlobalBoolean("K_MESS_CARTH", TRUE);
                        oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_jordo", lLocal);
                        NoClicksFor(2.2);
                        DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                        //DelayCommand(2.0, UT_NPC_InitConversation(GetTag(oNPC)));
                        return;
                }
                if(IsNPCPartyMember(NPC_JOLEE) &&
                   GetGlobalBoolean("K_MESS_JOLEE") == FALSE &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 25 &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 20 &&
                   GetGlobalNumber("MAN_MURDER_PLOT") == 0)
                {
                        SetGlobalBoolean("K_MESSENGER_AVAILABLE", FALSE);
                        SetGlobalBoolean("K_MESS_JOLEE", TRUE);
                        oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_davink", lLocal);
                        NoClicksFor(2.2);
                        DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                        //DelayCommand(2.0, UT_NPC_InitConversation(GetTag(oNPC)));
                        return;
                }
                if(IsNPCPartyMember(NPC_JUHANI) &&
                   GetGlobalBoolean("K_MESS_JUHANI") == FALSE &&
                   (GetGlobalNumber("G_JUHANIH_STATE") > 5 && GetGlobalNumber("G_JUHANIP_STATE")                    GetGlobalNumber("G_JUHANI_PLOT") == 0 &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 15)
                {
                        //juhanih_state > 5, and juhanip_state                         SetGlobalBoolean("K_MESSENGER_AVAILABLE", FALSE);
                        SetGlobalBoolean("K_MESS_JUHANI", TRUE);
                        oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_xor", lLocal);
                        NoClicksFor(2.2);
                        DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                        //DelayCommand(2.0, UT_NPC_InitConversation(GetTag(oNPC)));
                        return;
                }
                if(IsNPCPartyMember(NPC_CANDEROUS) &&
                   GetGlobalBoolean("K_MESS_CANDEROUS") == FALSE &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 35 &&
                   GetGlobalNumber("G_CAND_STATE") >= 6 &&
                   GetGlobalBoolean("G_CAND_THING") == TRUE &&
                   GetGlobalNumber("G_CAND_PLOT") == 0)
                {
                        SetGlobalBoolean("K_MESSENGER_AVAILABLE", FALSE);
                        SetGlobalBoolean("K_MESS_CANDEROUS", TRUE);
                        oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_jagi", lLocal);
                        NoClicksFor(2.2);
                        DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                        //DelayCommand(2.0, UT_NPC_InitConversation(GetTag(oNPC)));
                        return;
                }
                if(IsNPCPartyMember(NPC_MISSION) &&
                   GetGlobalBoolean("K_MESS_MISSION") == FALSE &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 35 &&
                   GetGlobalNumber("K_CURRENT_PLANET") != 25 &&
                   GetGlobalNumber("Mis_MissionTalk") == 5)
                {
                        SetGlobalBoolean("K_MESSENGER_AVAILABLE", FALSE);
                        SetGlobalBoolean("K_MESS_MISSION", TRUE);
                        oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_lena", lLocal);
                        NoClicksFor(2.2);
                        DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                        //DelayCommand(2.0, UT_NPC_InitConversation(GetTag(oNPC)));
                        return;
                }
                //MODIFIED by Preston Watamaniuk on April 11
                //Added the exchange crony Ziagrom to tell the PC about the special store.
                if(GetGlobalNumber("K_KOTOR_MASTER") >= 20 &&
                   GetGlobalNumber("K_Exchange_Store") == 0 &&
                   GetGlobalBoolean("K_MESS_ZIAGROM") == FALSE)
                {
                    SetGlobalBoolean("K_MESS_ZIAGROM", TRUE);
                    oNPC = CreateObject(OBJECT_TYPE_CREATURE, "g_Ziagrom", lLocal);
                    NoClicksFor(2.2);
                    DelayCommand(2.0,  AssignCommand(oNPC, ActionStartConversation(oPC,"",FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE)));
                    return;
                }
            }
        }
    }
}

 

 

Of importance is the following sample:

 

    int nXor = GetGlobalNumber("K_XOR_AMBUSH");

    //Do not fire any messenger plots on Kashyyyk if Chuundar is dead
    if(GetGlobalNumber("K_CURRENT_PLANET") == 20)
    {
        bConditional = GetGlobalBoolean("kas_ChuundarDead");
    }
    if(bConditional == FALSE)
    {
        if(nXor == 0 || nXor > 2)
        {

 

This led me to investigate the K_XOR_AMBUSH global number and how and where it was changed. I discovered that it was set to 2 just before he attacked you, but that it was never set to 3 when he is dying.

 

From there, I gathered saves from Kexikus and others and tested setting the K_XOR_AMBUSH to 3 after Xor dies. And everything works!

 

This script is used by the game to launch Xor's death scene, but I've edited it to set the K_XOR_AMBUSH to 3 at that time as well. Simply drop it into your override folder and you're good to go!

 

k_hxor_state03.7z

  • Like 10

Share this post


Link to post
Share on other sites

Bravo FS!

 

This has been a longstanding vanilla issue that many have experienced over the years. A must have!

Share this post


Link to post
Share on other sites

There was a fix for this from long ago. It was on lucasforums; I still have the file. Did it somehow evade you or did it conflict with K1R?

 

From what I understand, that fix you refer to fixes a different issue with the sidequest.

  • Like 1

Share this post


Link to post
Share on other sites

There was a fix for this from long ago. It was on lucasforums; I still have the file. Did it somehow evade you or did it conflict with K1R?

As stated in that fix's read-me:

 

"This mod will fixes the problem with the second encounter with xor (Juhani plot)

that was responsible for making Xor spawn only when using the Rapid transit system."

 

It does not fix the variable not being updated, which is necessary for the other messengers to spawn.

 

http://www.lucasforums.com/showthread.php?t=212579

http://www.lucasforums.com/showthread.php?t=154296

http://www.lucasforums.com/attachment.php?attachmentid=2451&d=1130303686

  • Like 1

Share this post


Link to post
Share on other sites

EXCELLENT WORK. I'm very thankful for that, we all are. :welcome:

 

PS: Can that file be integrated  in the newest update of  KOTOR Restoration?

  • Like 1

Share this post


Link to post
Share on other sites

As stated in that fix's read-me:

 

"This mod will fixes the problem with the second encounter with xor (Juhani plot)

that was responsible for making Xor spawn only when using the Rapid transit system."

 

It does not fix the variable not being updated, which is necessary for the other messengers to spawn.

 

http://www.lucasforums.com/showthread.php?t=212579

http://www.lucasforums.com/showthread.php?t=154296

http://www.lucasforums.com/attachment.php?attachmentid=2451&d=1130303686

ah, ok. Haven't reinstalled kotor in a while; It's been nice and stable recently. As a result I haven't read that readme in quite a long time. Just thought I'd check.

Share this post


Link to post
Share on other sites

Depending on when it's set to 2, it could be someone just using > 2 when > 1 was supposed to be there.

 

Setting it to 3 is a far easier sollution for fixing though :).

Share this post


Link to post
Share on other sites

Depending on when it's set to 2, it could be someone just using > 2 when > 1 was supposed to be there.

 

Setting it to 3 is a far easier sollution for fixing though :D.

From what I've gathered, it's set to 1 to let the game know to ambush you, and it's set to 2 when he actually does ambush you (as noted by it having to be 2 to get his death section of the dialog), so I'm operating on the idea that it has to be 3.

 

Also, compiling one script instead of trying to compile all the relevant trigger scripts that used the k_inc_utility, two of which wouldn't decompile... Hmmm, tough choice... :D

Share this post


Link to post
Share on other sites

As of 1-17-18, Snigaroo informed me that the download was broken and directing you to an error page here on DS. So he sent me the copy he'd already downloaded and I have re-attached it to the original post, as a .7z file that you will need to unpack using WinRAR, WinZip, or preferably 7zip.

  • Like 4

Share this post


Link to post
Share on other sites

Will this fix work if Xor has already approached me (but not yet ambushed me)? He simply stands outside the Ebon Hawk with his two thugs but I can't interact with him. I applied the fix but I still can't interact with him. I also tried using the Rapid Transit system to transit back to the Ebon Hawk but that didn't yield any result either. Any suggestions as to how I might solve this?

Share this post


Link to post
Share on other sites

Will this fix work if Xor has already approached me (but not yet ambushed me)? He simply stands outside the Ebon Hawk with his two thugs but I can't interact with him. I applied the fix but I still can't interact with him. I also tried using the Rapid Transit system to transit back to the Ebon Hawk but that didn't yield any result either. Any suggestions as to how I might solve this?

Try using a save from before you ever met him?

Share this post


Link to post
Share on other sites

Try using a save from before you ever met him?

I could but that would mean going back several hours in my playthrough. Can it be fixed through the save editor? I found K_XOR_AMBUSH in the global numerics but I'm not sure what value I should set it to (it's currently set to 1). I also found K_XOR_AMBUSH_FIX in the global booleans but I'm not sure what it does (also set to 1 currently).

Share this post


Link to post
Share on other sites

Try setting K_XOR_AMBUSH to 2, but make a copy of your savegame.

 

But it seems like you're having another issue. The globals seem fine for the second encounter, so I'd guess the dialog is screwed up or something like that.

Share this post


Link to post
Share on other sites

Try setting K_XOR_AMBUSH to 2, but make a copy of your savegame.

 

But it seems like you're having another issue. The globals seem fine for the second encounter, so I'd guess the dialog is screwed up or something like that.

Setting it to 2 didn't help either, however when I set it to 0 or 3 I got approached by Ziagrom so there's that. I guess I'll just have to be more careful in future playthroughs.

Share this post


Link to post
Share on other sites

Hi, guys

I'm playing KotOR1 (no Restoration, no MOD's, no Patches; 4 cd's spanish, 1.00 version) and I've found an issue that never had found before in others
playthroughs of K1. Knowing time ago about the problem completing Juhani's side quest before getting your 4th Star Map which prevents trigger the messenger
of the "Special Items Shop" at Korriban, I delayed her quest -not the talks with she- until I get the invitation of the shop (including, for my playthrough,
finishing all the others NPC's Side Quests except finding Carth's son).

After get the invitation I triggered the first encounter with Xor with no problems but now he doesn't appears again. Boarding/unboarding the Hawk, flying to
others planets several times (of course walking the "Triggering Zones") but nothing.

Reading this topic in your pages and reading about changing the value of the global number K_XOR_AMBUSH, I tried with KSE and my last save and found the
value is set to 0. I've changed it setting the value to 1 and... It has worked!!!!!!!! triggering, finally, the last encounter with Xor. Checking with KSE a
later save after Xor's death, the value was automatically set to 2.

As far as I can see at this moment (still in Korriban, before the last Star Map and before find Carth's son -my last loose end of all NPC's SQ and
"triggerings") the trick works with no further problems. Dustil encounter is not a "triggered encounter" but I was afraid that, somehow, could affect
Carth's son Quest, not closed yet. Happily, I've finished this SQ too without problems.

Maybe this can be useful for those users who hasn't applied any Patch or Fix to the game and a manner of emergence solution (like me).

Oh, by the way, if someone choose this line of action, before change nothing, make a backup of the save game. The surprises would'nt be surprises if they're
not surprises...

  • Light Side Points 1

Share this post


Link to post
Share on other sites

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