Fair Strides

Fair Strides' Script Shack

Recommended Posts

Back when Lucasforums was still with us, there was a thread in Holowan Labs called "Qui-Gon Glenn's Script Shack". Qui-Gon Glenn started the Shack as a central area for anyone to trouble-shoot problems with a script or get an idea of how to do something. There were some requests as well, almost always answered, and people could even post cool or useful scripts they had made for others to use and share around.

 

It's my wish that this thread serve the same purpose, though I will attempt to curate the thread itself and keep up something of a Table of Contents for this thread.

 

And with that, let the gates of Modding Hell open up and bring on the chaos... :D

 

Edit: And by the way, if you want to remove the Color-Coding that happens when you do your code snippet (which can be done with the blue in the toolbar) [Please, please, please remove the Color-Coding for the sake of my eyes if not your own!], set the Code Type to "XML".

  • Like 3

Share this post


Link to post
Share on other sites

Cool! Nice to see you opening up your own shack. 

 

 

I know a lot of people got a lot of use out of QGG's Merchant scripts, back in the day.

 

I'm personally partial to NPC spawn and "enemy" scripts, as they are quite helpful for creating dynamic conversations.

Share this post


Link to post
Share on other sites

If it's alright, I thought I'd share some of the scripts from my mod, since I got quite a few of them from the old thread, as well as various others on Lucasforums.

 

Give an item to the PC:

void main()
{
 CreateItemOnObject("(TAG_OF_ITEM", GetFirstPC());

}

Spawn an NPC:

void main() {
    //These are the X, Y and Z Co-Ordinates. To find these out, use the "whereami" cheat in KOTOR. As for TSL, I think there's an armband mod that gives it to you but I'm not sure.
    vector vPos;
    vPos.x  = 0.00;
    vPos.y  = 0.00;
    vPos.z  =   0.00;
    
    // This is the angle the NPC should be facing
    float fAngle = 0.00;

    CreateObject(OBJECT_TYPE_CREATURE, "NPC_TAG", Location(vPos, fAngle));

}

Kill an NPC through dialogue:

void main() {
    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), OBJECT_SELF);
}

Add a new Class to an NPC:

void main()
{
AddMultiClass( CLASS_TYPE_JEDIGUARDIAN, GetObjectByTag("TAG_OF_NPC"));
// Unfortunately I don't have the full list of classes on me at the moment, but that's how to make a character a Jedi Guardian at least.

}

Make an NPC walk/run to a location:

void main () {

  
  object oNPC=GetObjectByTag("TAG_OF_NPC");    

  float x=0.00;                         
  float y=0.00;                        
  float z=0.0;                        

  int bRun=FALSE;         //If set to TRUE, the NPC will run to the location.


  vector vPoint=Vector(x,y,z);
  location lPoint=Location(vPoint,0.0f);
  ActionDoCommand(SetCommandable(TRUE,oNPC));
  AssignCommand (oNPC,ActionForceMoveToLocation(lPoint,bRun));


}

Make an NPC Hostile:

void main() {
object oNPC = GetObjectByTag("Tag_Of_NPC");
int iFaction = STANDARD_FACTION_HOSTILE_1; //This works for all other factions as well, but, like the classes, I don't have them on me at the moment
      ChangeToStandardFaction(oNPC, iFaction);
}

Check to see if a global is a certain number:

int StartingConditional()
{
    int iResult = GetGlobalNumber("Your Global");
    if ((iResult == [Global Number You Want]))
    {
        return TRUE;
    }
    return FALSE;
}

//Attach this to a dialogue and it will only appear if the global is the correct number
//I think this works for Journal Entries too, just replace "GetGlobalNumber" with "GetJournalEntry"

These are all for KotOR I, so I'm not sure if these work for TSL. 

 

Please do correct me if any of these are wrong, and I'll edit the post right away.

  • Like 3
  • Light Side Points 1

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Nice.... You surpassed my skill a long time ago, FS, so it is right that you have your own shack.

 

I have to fix a mod; I did not realize J7 had borked the TSLPatcher that badly on the Sith Stalker. I will update it to install the sound file automatically, and to ensure that the appearance.2da is updated correctly. Don't be surprised if I am here later :)

Share this post


Link to post
Share on other sites

Hey FS, I've been trying to create a script that "fires" on the first converstation with an NPC

Then using that script to determine "Node availability." From what I read on holowan labs there's a default script for it using k_act_talktrue, k_con_talkedto , and k_contalked2, but I can't seem to get anything to work. 

 

What Function would you recommend I that use?

Share this post


Link to post
Share on other sites

Those are the correct scripts.

k_con_talkedto is the script you want as condition for the first time (!) dialog and not the later one even though the name might suggest as much. Then have k_act_talktrue as the script run at the end of the conversation (the end doesn't really matter as long as it's fired somewhere) and you're all set up.

  • Like 1

Share this post


Link to post
Share on other sites

Those are the correct scripts.

k_con_talkedto is the script you want as condition for the first time (!) dialog and not the later one even though the name might suggest as much. Then have k_act_talktrue as the script run at the end of the conversation (the end doesn't really matter as long as it's fired somewhere) and you're all set up.

Thank you, I will attempt that. 

 

Edit: It worked for my k1 dlg, thanks again!

Edited by jc2

Share this post


Link to post
Share on other sites

Could anyone answer why this script isn't working? I've tried to write a GetBoolean script that would be used to determine the availability of a dlg node, but it has not worked. 

 

Is this the wrong function or am missing something? 

Share this post


Link to post
Share on other sites

Hey FS, I've been trying to create a script that "fires" on the first converstation with an NPC

Then using that script to determine "Node availability." From what I read on holowan labs there's a default script for it using k_act_talktrue, k_con_talkedto , and k_contalked2, but I can't seem to get anything to work. 

 

What Function would you recommend I that use?

 

Sorry for the delay. When I'm at home, 90% of the time I don't do anything modding-related because I can't actually run the games on my laptop.

 

And I'm sorry I didn't get around to answering this, but Kexikus is correct. The only thing is that this only works the one time, unless you use the script "k_act_talkfalse" to reset the whole thing, but I think that's a K2 script (which you could remake in K1). When I originally read your post, I had thought you were asking about the concept and how to apply it to your own global variables.

 

Could anyone answer why this script isn't working? I've tried to write a GetBoolean script that would be used to determine the availability of a dlg node, but it has not worked. 

 

Is this the wrong function or am missing something? 

That would be the right function, but I've never seen that syntax (format) used before. Try modifying it to remove the " == TRUE" part.

 

The GetGlobalBoolean function itself returns a 1 or a 0 (TRUE or FALSE), so the " == TRUE" could be interfering.

  • Like 1

Share this post


Link to post
Share on other sites

Okay, I did what you suggested and it still doesn't seem to work. 

Here's the changed script in the attachment. '

 

Edit: I think I need to add a conditional like something if TRUE     then conversation availabe,  else FALSE no conversation available. Would that be right? It seems getting the boolean is not enough I need to assign it a command to it. Right?

Edited by jc2

Share this post


Link to post
Share on other sites

Looking up that global boolean, you need "kas_ChuundarDead" not "KAS_CHUUNDARDEAD". I don't know if I mentioned it or even got to it in the stream, but it is case-sensitive.

  • Like 2

Share this post


Link to post
Share on other sites

Looking up that global boolean, you need "kas_ChuundarDead" not "KAS_CHUUNDARDEAD". I don't know if I mentioned it or even got to it in the stream, but it is case-sensitive.

This was indeed the issue, thank you FS. 

Share this post


Link to post
Share on other sites

I appreciate all of the help so far from you guys!

 

If I wanted to make create a script that would "fire" allowing other dialogue options to be "available" what function should I use?

Would I try to create my own boolean, then have it fire. Therefore, I could use the boolean to check "node availability" and open up more dialogue options?  

Or is there a more simple way of doing this? 

 

Edit: if possible I would like to avoid using custom booleans to reduce incompatiblity issues, unless I have no other choice. 

Edited by jc2

Share this post


Link to post
Share on other sites

I appreciate all of the help so far from you guys!

 

If I wanted to make create a script that would "fire" allowing other dialogue options to be "available" what function should I use?

Would I try to create my own boolean, then have it fire. Therefore, I could use the boolean to check "node availability" and open up more dialogue options?  

Or is there a more simple way of doing this? 

 

Edit: if possible I would like to avoid using custom booleans to reduce incompatiblity issues, unless I have no other choice. 

Custom booleans won't affect compatibility, unless you somehow make the same global variable (remember, there are booleans and numerics) with the same case-sensitive name.

 

As to what you're asking, can you do a little doodle or something to illustrate it? Is just something as simple as "If B and C are replies to A, how can I make B appear but not C?" or something more complex?

Share this post


Link to post
Share on other sites

As to what you're asking, can you do a little doodle or something to illustrate it? Is just something as simple as "If B and C are replies to A, how can I make B appear but not C?" or something more complex?

 

I'll give you an example from my mod dialogue since that may be easier

 

If you talk to SHanilia about her Jedi Master (dialogue option A1), then the dialogue option to speak with her (Shanilia) about her mission will become available (Dialogue option B1). 

If you did not speak to her about (Dialogue option A1), then you will not be able to have (dialogue option b1). 

 

I plan to have roughly 5 of these, so that players do not access dialogue out of order. I hope this is understandable if it is not I can elaborate further. 

 

[i plan to use the alignment system to determine replies and leave reply options that are not filtered by anything.] 

 

 

Also, Custom booleans won't have trouble with the 2da? When I edited the 2da appearance, DarthParametric explained that if the added 2da files were not in order and labeled in order, then it would fail. Why would this not be the same for booleans? The variable is the row number not the name, right? So if I were to add "row 1100" boolean with a custom name, and another mod had that "row 1100" wouldn't we be incompatible? 

Or are you saying something else?

 

 

I plan to have roughly 5 of these, so that players do not access dialogue out of order. I hope this is understandable if it is not I can elaborate further. 

Share this post


Link to post
Share on other sites

That was the case for the appearance.2da, which the game's files references by the row number. Your issue with that file was that you inserted the row above the last row instead of entering some bogus info in the very bottom row and then pasting your row over that one. Yes, the KT 2DA editor is clunky that way...
 
However, the scripting functions that interact with the global values specifically take the value of the name column. The game uses that and doesn't care what order the rows are in. Also, you say that you plan on having five "tiers" of dialog that can be accessed one at a time. I take it the player can't ask about previous tiers?
 
If so, you'd be better off using a global number instead of a boolean. This way, you can increase the global number by 1 when the new tier is ready to be accessed and you're only using one global variable instead of five or however many you'd end up doing.
 
As an example:

Tier 1 DLG:

int StartingConditional()
{
    // If the variable is 0 (default), this'll be the first time.
    // You can always adjust this by change the < 1 to < 2, which
    // would allow you to set the variable to 1 after you talk to
    // Shanilla the first time.

    if(GetGlobalNumber("<name of variable, without the < > >") < 1) { return TRUE; }
    return FALSE;
}

and then at the end of that branch of dialog, you could update the global number:

void main()
{
    // Set it to 1 if you originally had it at 0, otherwise set it to 2.
    SetGlobalNumber("<name of variable, without the < > >", 1);
}

Oh, and you can disable the color-coding if you set the code type to XML when in the code window.

  • Like 1

Share this post


Link to post
Share on other sites

Just wanted to add two more things.

 

Also, Custom booleans won't have trouble with the 2da? When I edited the 2da appearance, DarthParametric explained that if the added 2da files were not in order and labeled in order, then it would fail. Why would this not be the same for booleans? The variable is the row number not the name, right? So if I were to add "row 1100" boolean with a custom name, and another mod had that "row 1100" wouldn't we be incompatible? 

Or are you saying something else?

 

You should still directly append lines to any .2da, even if the row number is not important (TSLPatcher will automatically do that anyway). As for compatibility, TSLPatcher takes care of that. It can check what the next row to add is, and then update all your files with that row number. So as long as your TSLPatcher is set up that way, your mod will work no matter what you install before it.

 

As for the global number, if your character is only in one area, or if you ever end up doing something similar for a character that's only in one module, use local numbers instead.
SetLocalNumber(GetObjectByTag("tag"), 25, *yourvalue*);
GetLocalNumber(GetObjectByTag("tag"), 25);

The 25 is an ID of the number, it can be another number, but there is a limit to them. There was a tutorial on LF that explained the ranges and which IDs are reserved for other uses, I don't if that's lost now.

Share this post


Link to post
Share on other sites

I would point out that stoffe's tutorial was for K2, and is not entirely accurate for K1. K1 has far fewer booleans, and the notes about which are available in NWScript are incorrect, and I remember having trouble with local numerics as well.

  • Like 2

Share this post


Link to post
Share on other sites

I would point out that stoffe's tutorial was for K2, and is not entirely accurate for K1. K1 has far fewer booleans, and the notes about which are available in NWScript are incorrect, and I remember having trouble with local numerics as well.

This, exactly this. This is why I tried and failed to use local numerics in the Pazaak Tournament in K1. I forget the particulars, but I think I was having issues with updating already-set ones when keeping track of info.

Share this post


Link to post
Share on other sites

Local buffoon here! How do you open a door?

 

So i'm trying to open a door on Manaan that closes itself. I don't know why it does this. It will open, then close. Not instantly but when you reload the module.

 

I wrote a script that would fire after a dialogue happened, which would open the door while you were in the module. It isn't working though. The door stays shut. I attempted to use the ActionOpenDoor function. 

Share this post


Link to post
Share on other sites

Local buffoon here! How do you open a door?

 

So i'm trying to open a door on Manaan that closes itself. I don't know why it does this. It will open, then close. Not instantly but when you reload the module.

 

I wrote a script that would fire after a dialogue happened, which would open the door while you were in the module. It isn't working though. The door stays shut. I attempted to use the ActionOpenDoor function. 

 

The important thing is that you will NEVER need to use the period and the extension in scripting. Some other things to point out without actually checking the files in question (the files in the level):

 

1. If the DoDoorAction doesn't work, then AssignCommand(GetObjectByTag(""), ActionOpenDoor(GetObjectByTag(""))); should work.

2. If there is more than one copy of that door in the level, then the script would have probably opened the very first instance of that door. I can go over that a bit more in the next stream.

  • Like 1

Share this post


Link to post
Share on other sites

The door could also be locked.

IIRC doors won't open even with scrpits while they're locked. So try and add

SetLocked("<door tag without <> >", FALSE);

But most likely your issue is the file extension in the script. This may be due to a wrong understanding, so let me try and clear this up. What you reference here is NOT the file name but the file tag set in the .ut* file. Usually it's the same (maybe it even has to be the same) but the tag obviously has no file extension which is why you don't use it.

That said, you NEVER use file extensions as FS said even when you actually reference files like in the ExecuteScript() function.

  • Like 1

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.