PDA

View Full Version : Creating an NPC


Pavlos
10-19-2005, 05:08 PM
I'm sorry if this has been brought up before but I can't find it and I probably sound like a total n00b, which I am, but how on earth do you create an NPC?

Simbacca
10-19-2005, 05:55 PM
this thread may help. it assists with creating new merchant NPCs:
http://www.lucasforums.com/showthread.php?t=147231

or this thread for recruiting NPCs:
http://www.lucasforums.com/showthread.php?t=131944

hopefully these help. i found them both under the General Tools + Tutorials forum.

also, welcome to the forum :)

Pavlos
10-20-2005, 12:28 PM
Thanks very much! I am actually creating a merchant at the moment. But my problem is how can I get an NPC to appear somewhere and then how do I attatch a dialogue file to him?

Darth333
10-20-2005, 01:53 PM
There's a conversation field in the .utc file: just type the name of your dlg file. Check the recruit tutorial for more details at the section "editing the .utc file": http://www.lucasforums.com/showthread.php?t=131944


as fro spawning npcs in the game, check this tutorial: http://www.lucasforums.com/showthread.php?t=143536

Pavlos
10-20-2005, 04:59 PM
Ok, so I've looked at the script for spawning an NPC as you enter an area, for the whereami armband which order do I put the information for the Location (Is it just the same order x y z?)

void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
if (!GetIsObjectValid(GetObjectByTag("o")))
{
CreateObject(OBJECT_TYPE_CREATURE, "c_drdith1_templateresref", Location(Vector(-78.45780,14.12259,0.0), 0.0));
}

ExecuteScript("Old_k_204tel_enter", OBJECT_SELF());
}

}

Is this right? When I try to compile it says k_204tel_enter.nss<12>: Error Syntax error at, "<" (I'm not sure it could be, "(") I can't think of what I've done wrong but if someone could have a look over it it would be excellent.
I'm sorry but I don't know how to put the above script into your simply stylish blue boxes.

Darth333
10-20-2005, 07:00 PM
Ok, so I've looked at the script for spawning an NPC as you enter an area, for the whereami armband which order do I put the information for the Location (Is it just the same order x y z?)
yes, the first coordinate is x, the second y and the third one z.

as For the script, there was an extra ()after OBJECT_SELF (it's because I modified the script at the last minute and forgot to remove it. I'll fix the template.)
This should work (well almost, see my comment below):


void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
if (!GetIsObjectValid(GetObjectByTag("o")))
{
CreateObject(OBJECT_TYPE_CREATURE, "c_drdith1_templateresref", Location(Vector(-78.45780,14.12259,0.0), 0.0));
}

ExecuteScript("Old_k_204tel_enter", OBJECT_SELF);
}
}


While the script will compile, your npc won't spawn: the template must not have more than 16 characters and c_drdith1_templateresref is way to long :)

kdsphantom
10-20-2005, 07:22 PM
Hiya Pavlos
they (boblion)taught me how to do that you use
[code] "script stuff blahblahblah "[/cod e] NOTE the space in the word code is there as to show you what you need to use, leave out the space to get the blue background.

Im pretty green on scripts too buddy heh like that script has things I wish I knew what did what. I take it "ExecuteScript" is a command to fire a script from inside a script? and what is "Old_k_204tel_enter" if you dont mind my asking?

I loaded your script up and took out that line and the script compiled, perhaps there is another way to fire that script ? after this script fires? but like I say im very green at this as well, but I just learned of ExecuteScript just now from you.
well hope this is of some help, the [code] at least and good luck
kdsphantom

EDIT
heh Darth angel ya I didnt refresh my screen before i posted and didnt even see your post before i did mine, or I wouldnt have even posted :) cause I even learned more from yours. and sadly heh it might not show but I do use the Lexicon but hey I still hope I helped Pavlos with the code thingy )

Darth333
10-20-2005, 08:25 PM
Im pretty green on scripts too buddy heh like that script has things I wish I knew what did what. I take it "ExecuteScript" is a command to fire a script from inside a script? and what is "Old_k_204tel_enter" if you dont mind my asking?

That will execute the old area on enter script without having to decompile the .nss file. Old_k_204tel_enter is just k_204tel_enter.ncs renamed to Old_k_204tel_enter.ncs :) You'll find more details on the how to inject a script here: http://lucasforums.com/showthread.php?t=137370

here: http://www.nwnlexicon.com/

and here: http://lucasforums.com/showthread.php?t=143536

The fact that the script wasn't compiling has nothing to see with the ExecuteScript function. As I explained above, it had to see with an extra pair of () after OBJECT_SELF

Fred Tetra
10-20-2005, 08:45 PM
That will execute the old area on enter script without having to decompile the .nss file. Old_k_204tel_enter is just k_204tel_enter.ncs renamed to Old_k_204tel_enter.ncs :) You'll find more details on the how to inject a script here: http://lucasforums.com/showthread.php?t=137370

here: http://www.nwnlexicon.com/

and here: http://lucasforums.com/showthread.php?t=143536

The fact that the script wasn't compiling has nothing to see with the ExecuteScript function. As I explained above, it had to see with an extra pair of () after OBJECT_SELF

Doesn't the 16 character limit apply to script names, too? "Old_k_204tel_enter" is 18 characters long... :)

Darth333
10-20-2005, 08:46 PM
yes it does :)

Pavlos
10-21-2005, 11:38 AM
DAMN! Time to rename stuff then! Thannks for the help, guys!

void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
if (!GetIsObjectValid(GetObjectByTag("o")))
{
CreateObject(OBJECT_TYPE_CREATURE, "m_templateresref", Location(Vector(-78.45780,14.12259,0.0), 0.0));
}

ExecuteScript("1k_204tel_enter", OBJECT_SELF);
}
}


Is that any better for the naming? (Again I cannot seem to get the blue box thing to work. Oh well)

Edit: Yay! I got the box to work!

Pavlos
10-21-2005, 12:02 PM
Ok, I must be doing something wrong as the NPC doesn't spawn, I changed the names etc. I don't understand what is wrong

Darkkender
10-21-2005, 12:28 PM
DAMN! Time to rename stuff then! Thannks for the help, guys!

void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
if (!GetIsObjectValid(GetObjectByTag("o")))
{
CreateObject(OBJECT_TYPE_CREATURE, "m_templateresref", Location(Vector(-78.45780,14.12259,0.0), 0.0));
}

ExecuteScript("1k_204tel_enter", OBJECT_SELF);
}
}


Is that any better for the naming? (Again I cannot seem to get the blue box thing to work. Oh well)

Edit: Yay! I got the box to work!

What is the name of the utc file for your npc you are trying to spawn? If it is something other than m_templateresref then you need to change the "m_templateresref" reference to the name of the utc file minus the ".utc" of course. Also you need to include a copy of the utc file in the folder where your script is compiled or it will not link properly and will not spawn the NPC.

Fred Tetra
10-21-2005, 01:02 PM
I would instead say that you need to have the creature (.utc) and the compiled script (.ncs) files in the same place for the game to use them, be that the override folder for testing, or in a .mod file when it is ready for release.

Saying that you need to have the file in the same folder where the script is compiled might mislead some novice people into thinking that there is some connection between the two outside of the game, which there isn't. If they're compiling them right in the override folder (ick!), your advice would be valid, but that's an unusual case.

Darkkender
10-21-2005, 01:18 PM
I would instead say that you need to have the creature (.utc) and the compiled script (.ncs) files in the same place for the game to use them, be that the override folder for testing, or in a .mod file when it is ready for release.

Saying that you need to have the file in the same folder where the script is compiled might mislead some novice people into thinking that there is some connection between the two outside of the game, which there isn't. If they're compiling them right in the override folder (ick!), your advice would be valid, but that's an unusual case.

The reason I stated it that way was because you need to have the gff file in the folder you are compiling it at when using the resref. Otherwise the the script will not link properly at compilation so it will not spawn the creature object in game. This has always confused me as to the need of this but this is what was recomended to me from one of our scripting guru's long time ago. When you compile the script without the utc file or the other related gff files for the other object scripts your script will be half the compiled size as compared to a script compiled with the utc or other gff file in the same folder.

*unless our tool master has previously addressed this situation with his updated versions of nwnsscomp program.*

Pavlos
10-21-2005, 01:41 PM
Ok so should I compile the script with the .utc file that I made for the NPC or without it? If without I have no idea why it isn't working as I have changed all the relevant data in the .utc to fit the new name.

Fred Tetra
10-21-2005, 01:53 PM
Here's a simple script I used to test your assertion:

void main()
{
CreateObject(1, "203_merc005", GetLocation(GetObjectByTag("wp_mercbg1_01", 0)), 0);
}

Any combination of the files (203_merc005.utc and wp_mercbg1_01.utw) being present or absent yields a compiled .ncs of 94 bytes in size. Nowhere in the nwnnsscomp code do I remember anything that copies the .ut*'s info into the .ncs, so I am not sure what sort of behavior you were seeing.

Now, if you forget to put one or both of the files in your .mod file, it would obviously be smaller and the script won't work unless both of the files are present in either templates.bif or the override folder.

If you'd like to provide a script and the required gff's that I can use to reproduce this problem, I'd be happy to take a look at it.

Darkkender
10-21-2005, 02:12 PM
Ok so should I compile the script with the .utc file that I made for the NPC or without it? If without I have no idea why it isn't working as I have changed all the relevant data in the .utc to fit the new name.

What is the name of the file itself that you use when compiling?

Also does the code of your script look exactly as you have it listed above?

If the name of the file minus ".utc" does not match exactly with the script referencing it and if the template resref field in the utc file differs from the name of the file you are going to have conflicts and things won't launch properly.


@Fred it could easily be possible that you have made a change that I wasn't aware of in your later versions that fixed that bug. This has been a scripting method that I have known to do for so long that the context of the original answer may be different from the method we are discussing. This particular need of the gff files in the compile folder may only be needed when using one of the functions in the recruit related scripts and not the createobject function. I was just relying on this old method as a matter of course from ingrained process that was taught to me.

Pavlos
10-21-2005, 02:38 PM
k_204tel_enter.utc is the name of my .utc file
k_204tel_enter.ncs is the name of my compiled script
k_204tel_enter.nss is the name of my uncomplied script
1k_204tel_enter.ncs is the name of the original script that I tell it to load from once it has loaded my script.

The script is as stated above. The name in the Templateresref field is m, should it be m_templateresref? I have tried both but nothing changes. I really don't know what I am doing wrong.

Fred Tetra
10-21-2005, 02:47 PM
The script name doesn't matter.

Here is my script again, altered to match a waypoint created from scratch for this second experiment:

void main()
{

CreateObject(1, "203_merc005", GetLocation(GetObjectByTag("wp_spawn_test", 0)), 0);
}

In a sample module, I specifed "spawn" as the OnEnter script for a trigger, created a mapnote waypoint and gave it a tag of "wp_spawn_test".

I then built the .mod file and warped to it in-game. When I cross the trigger, the mercenary spawns at the designated waypoint. None of the objects mentioned in the script were present when it was compiled, and none of them share a resref in common. And it works. :)

Also, I have not made any changes to the nwnnsscomp code (ever) that would cause it to reference the gff files. It is just not that sophisticated.

This all reminds me of a story... One day, my wife was preparing a turkey for the oven, and she always cuts the legs off before doing so. This has always seemed odd to me, so this time I asked her why she does that. She replied, "You have to, so it turns out right! My mother always did, and her's was always nice and juicy". Being a programmer/engineer, this answer did not satisfy me, so I asked her mother about this technique. Her reply was the same! Fortunately, my wife's grandmother is still around, so I called her and asked her about it. She started laughing and said, "Oh yes, that's what I used to do when I made turkey, but it has nothing to do with the juiciness. I just had a small oven and couldn't fit the turkey inside without cutting the legs off!"

:)

Fred Tetra
10-21-2005, 03:03 PM
k_204tel_enter.utc is the name of my .utc file
k_204tel_enter.ncs is the name of my compiled script
k_204tel_enter.nss is the name of my uncomplied script
1k_204tel_enter.ncs is the name of the original script that I tell it to load from once it has loaded my script.

The script is as stated above. The name in the Templateresref field is m, should it be m_templateresref? I have tried both but nothing changes. I really don't know what I am doing wrong.

The .utc is the creature. Let's pretend that you renamd it to fred.utc for clarity. ;)

Also, let's pretend that you renamed the original enter script to orig_ent_script.nss.

You didn't say what file has the tag field set to "o", so I cannot analyze the
!GetIsObjectValid(GetObjectByTag("o")) line of code fully, but if your intention was to prevent more that one spawn of the "fred" creature, you have to be sure that you set the Tag field in fred.utc to "o" so that doesn't happen.

void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
if (!GetIsObjectValid(GetObjectByTag("o")))
{
CreateObject(OBJECT_TYPE_CREATURE, "fred", Location(Vector(-78.45780,14.12259,0.0), 0.0));
}

ExecuteScript("orig_ent_script", OBJECT_SELF);
}
}

Pavlos
10-21-2005, 03:43 PM
Thanks, Fred! I forgot to name the tag to o it was still blank. Now it is working fine! Yay! I'm happy I've just made my first NPC! Now to do something with him.

Edit: Ok so if I create a .dlg file then how would I go about attatching it to the particular NPC, I have looked in the links that people have provided above but they don't seem to be that much use.

Edit: Ok I poked around a bit and I know how to attatch the dialogue to the NPC. My rudimentary dialogue, purely for testing, will only come up in one of the floating boxes, I have a reply option of just let me shop but it obviously isn't working. But on the plus side I feel I'm starting to get the hang of the whole modding thing, lol.

Edit: Ok I changed a little tiny thing and that was making sure the response was saved, lol. Now all I get is the floating box and then the merchant screen pops up. I'll try a bit of messing around and I should be able to sort it out.

Edit: Problem solved I just needed to make sure the line the script to open up the store was on a line that was spoken by the NPC and had no actual speaking in it. Thankyou all for your help, now all I need to do is write my dialogue and customise the items in my store. Hmmz I don't want to cheap out and just have the beeping for the droid I have made, so maybe I'll voice it I'm pretty good with sound tools, or maybe I could get microsoft sam to do the voice of the droid? Is that against any copyright? Anyhow I apologise for the amount of edits, it is just neater than posting multiple, erm, posts.

Pavlos
10-21-2005, 06:13 PM
I decided on using my own voice and robotising it with some editing. I am going to add in another NPC, the chief medical officer on Citadel Station (Why is that medical centre empty? Does it have anything to do with the stealing medical supplies quest or that quest where you have to go to the comm station? I'll check later but if anyone knows if the emptiness is because of that I'll have to reasess what I have planned) I'm planning for you to be allowed to be healed by her for free, or receive medpacs if you like, if you are below a certain HP. How would I go about setting up a script like this? A tutorial might be nice as I like to think things through myself so I understand them, rather than just being told this is it. Thanks again for all the help above which eventually boiled down to my own stupidity of forgetting to tag my NPC.

RedHawke
10-22-2005, 01:33 AM
The reason I stated it that way was because you need to have the gff file in the folder you are compiling it at when using the resref. Otherwise the the script will not link properly at compilation so it will not spawn the creature object in game. This has always confused me as to the need of this but this is what was recomended to me from one of our scripting guru's long time ago.
Well DK to confirm what Fred said, I have never compiled a script with any of the GFF files present, and they all work fine, and I still use the original compiler we used for KOTOR I. :D

Just an FYI. ;)

@ ROFL at Fred's Turkey story! :lol:

Pavlos
10-22-2005, 01:33 PM
Ok so I'm having some success at the moment. I'm fiddling around with NPCs etc. But one of my objectives is to have a holo record, of the news which can be accessed from a terminal, like the one on Onderon. How would I go about setting up a script to spawn an NPC when a particular item was selected, and then switching the conversation type from console to person.