Salk

[KotOR] Help with an in game cutscene

Recommended Posts

I have edited the post above because I realized the Trigger entry was missing from the .git file but adding that too did not produce any result.

 

Yes, I have been on Tatooine before. The Xor plot comes usually pretty late into the game and Tatooine is the first planet I visit after Taris. Does it make a difference?

 

Good luck with the installer.

Share this post


Link to post
Share on other sites

Any GIT edits only take effect the first time you've ever entered the area. The game saves a "current" copy of the GIT into your saved game.

 

You can put the .git file in the Override for testing and that would work, but the area gets reset every time you enter it.

  • Like 1

Share this post


Link to post
Share on other sites

Oh I see... I did not know that.

 

Anyway what happens if I move the .git file to the Override is that I get the cutscene with the czerka officer wanting you to pay the docking fee.

 

I removed all triggers from the .git file just in case it was a matter of priority for which one should come first. I left only my own additions and nothing happens.  :no

Share this post


Link to post
Share on other sites

Then you won't be able to go that route. You'll need to delete that GIT from your override and obtain or make a save from before going to Tatooine to be able to properly test it.

 

The KotOR Saves collection's last save is just before going to the Grove.

Share this post


Link to post
Share on other sites

Well, I made some progress with this and I must say it's a lot of work to learn much stuff for very little gain but I am stubborn and I am trying to make it work.

 

The problem I am having now is with the position of the cameras in the cutscene.

 

According to what I read in the tutorial by FG, there should be two entries for Position and Orientation but in the .git file I am working on they are missing... Does it mean that there are some "default" values for them stored somewhere?

 

Curiously enough, the camera seems to be placed on the floor just under the Ebon Hawk (?) and it does look visible.

 

The script switches to camera 444 and 445 which do exist in the .git file but the position is completely borked.

Share this post


Link to post
Share on other sites

For the static cameras, there needs to be a Position field (when clicked in K-GFF it'll have three of the four entries on the left highlighted) and an Orientation field (which would have four entries visible).

 

I recommend always copying an existing Camera struct and pasting it to the Camera list itself. It will be added at the end of the list and then the only things to edit would be orientation, position, and ID (possibly Height as well).

Share this post


Link to post
Share on other sites

Hello again.

Yes, I understand we need Position and Orientation but those entries are missing from the .git file I am editing.

 

post-8946-0-39859700-1464803899_thumb.jpg

 

As you can see it has five entries: ID, Field of View, Height, MicRange and Pitch. I checked many others .git files and they are all like that. How can these cameras work without the Position and Orientation entries?

 

That's why I was wondering if the cameras' position and orientation are stored somewhere else?

Share this post


Link to post
Share on other sites

No, the cameras' Positions and Orientations should be stored in that file. Was that file opened and saved in anything before K-GFF? Did it come from a mod or from the .rim levels themselves?

Share this post


Link to post
Share on other sites

Okay.

 

It seems that my mistake was to believe that GFF Editor would show me everything that K-GFF does. Silly me.

 

I found out the hard way. Using K-GFF I can now see the Orientation and Position of the cameras. Not for the file I was working on (which I did save, yes).

Share this post


Link to post
Share on other sites

Are you just extracting them from KotOR Tool and immediately opening them up in K-GFF? Also, what version is K-GFF (lower-right corner)?

 

Edit: Oh you were using GFF Editor. If you had mentioned that when I talked about K-GFF I could have helped a lot soon (but it's okay, I'm not harping on you). GFF Editor was made for an earlier version of the GFF format, so Position and Orientation weren't around then.

Share this post


Link to post
Share on other sites

Well, I am almost ready with restoring the Xor Ambush on Tatooine.

The only thing left is for me to figure out why the party members and Xor himself face a completely wrong direction during the cutscene.

The party members direction must be set by this function in k_pkas_pcxorjp.ncs:

 

void sub2(object objectParam1, object objectParam2, object objectParam3) {
object oNPC = GetPartyMemberByIndex(0);
object object3 = GetPartyMemberByIndex(1);
object object5 = GetPartyMemberByIndex(2);
sub3();
if (GetIsObjectValid(oNPC)) {
sub4(oNPC, GetLocation(objectParam1));
AssignCommand(oNPC, SetFacing(GetFacing(objectParam1)));
}
if (GetIsObjectValid(object3)) {
sub4(object3, GetLocation(objectParam2));
DelayCommand(0.3, AssignCommand(object3, SetFacing(GetFacing(objectParam2))));
}
if (GetIsObjectValid(object5)) {
sub4(object5, GetLocation(objectParam3));
DelayCommand(0.3, AssignCommand(object5, SetFacing(GetFacing(objectParam3))));
}
}

From the little I understand, it seems to be perfectly alright. The party members should face objectParam1, objectParam2 and objectParam3 which are three waypoints I had to create and where Xor and  his minions spawn:

 

object oKas_xor_pc0_jump = GetObjectByTag("kas_xor_pc0_jump", 0);
object oKas_xor_pc1_jump = GetObjectByTag("kas_xor_pc1_jump", 0);
object oKas_xor_pc2_jump = GetObjectByTag("kas_xor_pc2_jump", 0);

But instead of looking straight at them my party members face a specific direction, as the screenshot shows. And Xor seems to be looking there too.

 

post-8946-0-23728500-1464965679_thumb.jpg

 

 

Share this post


Link to post
Share on other sites

That would probably be due to the X and Y Orientation fields of the waypoints you've warped them to. Those orientations do matter because when you use GetFacing, you're getting the directional-facing of the waypoints themselves.

 

This is made up of their orientation fields and is the equivalent of picturing the waypoint as a square with a triangle roof. The tip of the triangle points where the X and Y Orientation fields go.

 

  /\

 |_|

 

If I might suggest it, backup your tat_m17ab.mod and all file relating to it. Then download my Toolset and open the tat_m17ab.mod inside it and select the waypoints you've added. I'd be quite surprised if the arrow that shows up when you select one of them doesn't point in the direction the NPCs are facing.

Share this post


Link to post
Share on other sites

Well, this part is done.

 

The Xor ambush in Tatooine has been restored. Again, thanks a lot for your help Fair Strides. I found this post very useful with regards to X and Y Orientation (I am not sure I quite understand what the Z Orientation is used for though).

Share this post


Link to post
Share on other sites

If able, I'd really like to do that, yes. :)

 

I will move now to Manaan and see if there is anything there that needs investigation... :)

Share this post


Link to post
Share on other sites

Hoping that my guardian angel Fair Strides is still checking in here, there is another small issue I am trying to resolve.

 

In Ahto West, a republic officer is trying to convince an Echani mercenary to work for the republic. At the end of the small cutscene, once the dialogue is over and the mercenary left, the officer keeps playing the conversation animation, as the attached screenshots shows:

 

post-8946-0-20373500-1465380419_thumb.jpg

 

To stop the animation I thought a single line, added to the script that makes the mercenary leave (k_pman_reprec01), might suffice:

AssignCommand(GetNearestObjectByTag("man26_repneg"), PlayAnimation(0, 1.0, -1.0f)));

but nothing actually happens.

 

I did try other animations (like 16, DANCING) but with no result. I also changed the object but nothing.

 

Any ideas?

 

The original script is the following:

 

void main() {
SignalEvent(GetNearestObjectByTag("man26_echmerc1", OBJECT_SELF, 1), EventUserDefined(10));
}

Share this post


Link to post
Share on other sites

Looking at the man26_repneg.utc in the Ahto West module (manm_26aa), their OnSpawn script fires their OnUserDefined script, which consists only of the following:

 

void main()
{
    if (Random(5) == 0) ActionPlayAnimation(ANIMATION_LOOPING_TALK_FORCEFUL);
    else if (Random(4) == 0)ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING);
    else if (Random(3) == 0)ActionPlayAnimation(ANIMATION_LOOPING_TALK_SAD);
    else ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD);
    ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT);
    ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT);
    ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED);

    ActionDoCommand(SignalEvent(OBJECT_SELF,EventUserDefined(0)));
}

 

 

 

To re-write this for easier understanding:

 

 

 

void main()
{
    if (Random(5) == 0)
    {
        // 20% chance to talk forcefully
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_FORCEFUL);
    }
    else if (Random(4) == 0)
    {
        // 25% chance to talk while laughing
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING);
    }
    else if (Random(3) == 0)
    {
        // 33% chance to talk sadly
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_SAD);
    }
    else
    {
        // If all else fails, talk normally
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    }

    if(Random(3) == 0)
    {
        // 33% chance to scratch head before talking normally
        ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD);
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    }

    if(Random(3) == 0)
    {
        // 33% chance to look left before talking normally
        ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT);
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    }
    if(Random(3) == 0)
    {
        // 33% chance to look right before talking normally
        ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT);
        ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    }
    if(Random(3) == 0)
    {
        // 33% chance to look bored
        ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED);
    }

    // Re-fire this script to do it all again!
    ActionDoCommand(SignalEvent(OBJECT_SELF,EventUserDefined(0)));
}

 

 

 

Now, you'd basically need to get around this, but I assume you only want to do that after the mercenary's been talked to. You can check the 10th Local Boolean for the trigger ( man16a_inittrig0.utt ; tag is man26a_inittrig01 ) to make sure the conversation has fired if you want.

 

So you'd modify that above script and have this in there somewhere (probably put all of what's there into an else block):

 

if(GetLocalBoolean(GetObjectByTag("man26a_inittrig01") > 0)
{
    // Code to stop the animations or do something else
}

Share this post


Link to post
Share on other sites

Hello again and thanks for your help!

 

I didn't think of checking the OnSpawn script of the Republic Soldier and now it makes sense.

 

I tried your suggested IF condition (which I needed to change to make it even compile:

 

if(GetLocalBoolean(GetObjectByTag("man26a_inittrig01") , 1))

 

but it still did not work. What I wanted to do was to make the Republic Officer play non talking animations after the mercenary has left, just like you assumed. To do it I thought of adding an else condition to the script but I am unsure about the IF condition I need to use. I checked around and GetNearestCreature seemed promising but I don't seem to figure out how to use it in an IF condition that would return true only if the nearest creature is not a party member. Do you have a suggestion?

 

 

 

 

void main() 
{
If() <--- What should I use to make it check that the nearest creature is NOT a party member?
{
    if (Random(5) == 0) ActionPlayAnimation(ANIMATION_LOOPING_TALK_FORCEFUL);
    else if (Random(4) == 0)ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING);
    else if (Random(3) == 0)ActionPlayAnimation(ANIMATION_LOOPING_TALK_SAD);
    else ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD);
    ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT);
    ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT);
    ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED);


    ActionDoCommand(SignalEvent(OBJECT_SELF,EventUserDefined(0)));
  }
else
{
    ActionPlayAnimation(ANIMATION_LOOPING_PAUSE);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD);
    ActionPlayAnimation(ANIMATION_LOOPING_PAUSE);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT);
    ActionPlayAnimation(ANIMATION_LOOPING_PAUSE);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT);
    ActionPlayAnimation(ANIMATION_LOOPING_PAUSE);
    if(Random(3) == 0)ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED);


    ActionDoCommand(SignalEvent(OBJECT_SELF,EventUserDefined(0)));
}
}
 

 

 

 

Thanks!

Share this post


Link to post
Share on other sites

You don't need to check for the nearest creature. The fact that the local boolean "man26a_inittrig01" is 1 already specifies that the conversation is over. So what you'd need is an If statemenet that checks for this condition and then stops all animations or plays new idle animations and an else case that does what the original script does.

 

The reason why FS' if condition is not working is probably that the number of the local boolean is not working. It should be something like this:

if(GetLocalBoolean(GetObjectByTag("man26a_inittrig01"), xx) > 0)

where xx is the number of the boolean that saves whether or not the conversation is over. Not sure about the exact syntax though and I can't check right now.

Share this post


Link to post
Share on other sites

Hello Kexikus!

 

The script I would modify is k_pman_ambient05 and I believe there might be more than one NPC using it.

 

 

 

manm26aa_s.rim   man26_echmerc1.utc    ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_echmerc2.utc    ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_irimerc.utc     ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_merc1.utc       ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_repneg.utc      ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_sel3.utc        ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_selamb2.utc     ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_sithneg.utc     ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_travel.utc      ScriptUserDefine     k_pman_ambient05
manm26aa_s.rim   man26_travel001.utc   ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   m26_swoopgen01.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_casandra.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_selamb2.utc     ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_sithneg.utc     ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_sithswp1.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_sithswp2.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_sithyel001.utc  ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_sithyell.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_sithyell2.utc   ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_swoop002.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_swoop003.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_swoop004.utc    ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_swoop1.utc      ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_swoop2.utc      ScriptUserDefine     k_pman_ambient05
manm26ab_s.rim   man26_travel.utc      ScriptUserDefine     k_pman_ambient05
scripts.bif      k_pman_ambient05.ncs  (File name)          
scripts.bif      k_pman_ambient05.nss  (File name)          

 
Would it be safe doing what we are discussing?
 
Where do I find the 10th Global Boolean that Fair Strides was talking about? Has it to do with the (1010) number I read next to its name under the Trigger List?
 
Thanks for the assistance!

Share this post


Link to post
Share on other sites

Changing what I wrote to the following should work:
 

if(GetLocalBoolean(GetObjectByTag("man26a_inittrig01"), 10) > 0)

The reason why it didn't work initially was because I forget the number 10 in the GetLocalBoolean function. Each object in the game has a list of local booleans and numbers, though I forget the range for both.

 

The game uses Local Boolean 10 to determine if triggers have already been used (the activation script should set the local boolean 10 to 1/TRUE) or if you've already talked to an NPC before (the scripts k_con_talkedto.nss and k_act_talktrue.nss in K1; the first checks if Local Boolean 10 is set, the second sets to to 1/TRUE).

 

I don't see how this change would really affect the other situations, but here's the basic structure I'd use to be safe:

 

 

void main()
{
    if(GetModuleFileName() == "manm26aa") // If we're in Ahto West
    {
        if(GetLocalBoolean(GetObjectByTag("man26a_inittrig01"), 10) > 0)
        {
            // Code for not-talking animation or something
        }
        else
        {
            // Put the original code stuff here!
        }
    }
    else
    {
        // Put the original code stuff here!
    }
}

 

 

Share this post


Link to post
Share on other sites

But that would still affect all NPCs using this script in Ahto West. So all NPCs would stop their animations or do whatever you implement once the conversation is over and not just the one NPC you want to.

 

To get around that you could expand the second if statement to check if the script is run by the correct NPC.

 if(GetLocalBoolean(GetObjectByTag("man26a_inittrig01"), 10) > 0 && OBJECT_SELF = GetObjectByTag("man26_repneg"))

Share this post


Link to post
Share on other sites

Well, I tested it and it is not working. The feedback window shows me the Boolean is false both before and after I triggered the cutscene.

 

 

 

void main()
{

    object oNegotiator=(GetObjectByTag("man26_repneg")); // This one is used in the IF condition below to avoid that other creatures using the same ambient script will have their animation stop
    object  oPC=GetFirstPC();
    string cmMessage = "Boolean > 0";
    string cmMessage2 = "Boolean = 0";


if((GetLocalBoolean(GetObjectByTag("man26a_inittrig01"), 10) > 0) && (oNegotiator == OBJECT_SELF))
{


    SendMessageToPC(oPC, cmMessage);


    ActionDoCommand(SignalEvent(OBJECT_SELF,EventUserDefined(0)));
   
}


else


{


    SendMessageToPC(oPC, cmMessage2);


    ActionDoCommand(SignalEvent(OBJECT_SELF,EventUserDefined(0)));


}


}

 

 

It was possible to make it work by adding the following lines to k_pman_reprec though:

 

 

 

object oBj = GetObjectByTag("man26a_inittrig01");
SetLocalBoolean(oBj, 10, TRUE);
DelayCommand(1.0, AssignCommand(GetNearestObjectByTag("man26_repneg"), ClearAllActions())); // This one interrupts the wrong animation immediately

 

 

but I want to make sure I am not inadvertently making mistakes.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.