Jump to content

Home

How to create merchants?


StrangeJ

Recommended Posts

Originally posted by StrangeJ

I've searched (probably missed it though), but couldn't find any tutorial or guide to creating merchants...

 

So can someone point me to the right thread or tutorial please?

 

I'm rather poor at explaining things and my english isn't the best, but hopefully this will give some hint at least.. :)

 

The easiest way is probably to extract an existing merchant template and modify that to your need.

 

For example, in KotorTool, open RIMs --> Modules --> 202TEL_s.rim --> Blueprint, Merchant. Select the file named m_202_003.utm and press the Extract button. This is the merchant template for Samhan Dobo, the "immoral" Duros Merchant on Citadel Station.

 

Now, rename this file to something unique and then open it in the GFF Editor. Change the fields in the GFF Editor to match how you want your Store to work:

 

BuySellFlag (BYTE):

Determines if the merchant will sell items, buy items or do both.

1 = Only sells

2 = Only buys

3 = Buys and Sells

 

ID (BYTE):

I think this is the Palette ID in the toolset for Stores, but since we have no toolset it probably makes no difference. It's always set to 5 for Stores as far as I can see, so I suggest you leave it at that.

 

LocName (CExoLocString):

Set this string to the name of the store. This is usually the name of the merchant NPC who owns the store.

 

MarkDown (INT):

Set this to the percentage of the base item value that the store will pay for items you sell to it. 50 makes the store give you 50% of the item's base value for it.

 

MarkUp (INT):

Set this to the percentage of the base item value that the store will charge for an item when you buy it. 100 makes the store sell items for their base value, 125 will make items 25% more expensive than their base value.

 

OnOpenStore (CResRef):

This is a Resref (filename) to a script that will be triggered when the Store is started. Unless you want something special to happen whenever the store is opened, just leave this blank.

 

Resref (CResRef):

This should be set to match the name of the file exactly, but without the .UTM suffix. If you renamed the file above to "st_customstore.utm", then you'd set this field to "st_customstore". Note that Resrefs shouldn't be longer than 16 characters.

 

Tag (CExoLocString):

This is an identifier that scripts can use to access your store. For simplicity you'll probably want to set this to the same value as the Resref field, unless you have a good reason not to.

 

ItemList (List):

This category contains a list of all the items the stort will initially contain. The easiest way is to just modify the item entries that are already in the list from the store you copied, and change the InventoryRes field to point to the items you wish the store to contain. Delete any leftover entries from the old store when you are done.

 

If you need to add more entries, select one of those presently in the list and click "Copy Node/Subtree" in the Edit menu. Then click on the "ItemList" top entry and click "Paste as child node" in the Edit menu. Now select your newly created entry and in the panel to the right in the GFF Editor, change the value in the "FieldID" field to a value one higher than the highest of the indexes of the already existing entries. I.e. if the last entry was 30, type 31 here.

 

Each entry in this list contains the fields:

* InventoryRes (CResRef): A Resref (filename) to the item blueprint for this item. For example putting "a_robe_08" here would place a standard Jedi Robe in the store.

 

* Repos_PosX, Repos_PosY (WORD): X and Y coordinates for where in the store the item should appear. I don't know if they are actually used or merely leftovers from Neverwinter Nights since KOTOR/TSL uses a list to present inventory content. Just in case make sure that no items have the same set of X/Y coordinates.

 

* Infinite (BYTE): This field is optional, but if it exists and is set to 1, the store will have an infinite supply of this item.

 

Note that if you want more than one of a specific item in the store, but don't want an infinite supply, you'll have to create a separate entry for each of the duplicate items, and set the InventoryRes of the entries to point to the same item blueprint.

 

-----

 

Now you've created the blueprint for your store. Place it in the override folder. In order to actually use this store in the game though, you'll need to do two things. First you need to create an object of your store in-game, then you'll need to create or add onto an NPCs conversation that will start the store.

 

This is done the easiest way through a script that you attach to the dialog node that will start your store. I believe a script like this would work:

 

// ST: st_startstore.nss

void main() {
object oStore = GetObjectByTag("TAG_OF_STORE_HERE");

if (!GetIsObjectValid(oStore))
	oStore = CreateObject(OBJECT_TYPE_STORE, "RESREF_OF_STORE_HERE", GetLocation(OBJECT_SELF));

if (GetIsObjectValid(oStore))
	DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));
}

 

Edit the script and put the tag you specified above where it says "TAG_OF_STORE_HERE", and put the resref you specified above where it says "RESREF_OF_STORE_HERE".

 

Then name the script something unique, compile the script and put it in the override folder. In your Dialog file, where you want the store to start, put the name of this file in the field labeled "Script #1" if you are using the DLG Editor.

Link to comment
Share on other sites

Originally posted by RedHawke

Merchant Creation

--------------------------------------------------

The script to activate a merchant is in the ORD Mandell source scripts as well (Though you will have to change the merchant tag in the script for your own use).

 

All you really have to do is create an NPC and a dialogue for them with a tree ending with a node that has the PC select something like "What do you have for sale?" and you attach the open merchant script at that point, with KT now having a Merchant Editor it is rediculously easy to create the actual merchant file.

 

With KT simply open an existing or create a Merchant .utm file for your NPC, place in the Items you want them to sell, and save the .utm.

 

Pack the (1)activate script, (2)the NPC .utc, (3)the NPC .dlg, (4)and the NPC .utm, plus (5)the NPC spawn script and edited game dialogue (if any) into your module or drop them into override and go in the game to your spawned or placed NPC and test it out.

 

Check out my Elder Rodian Merchant Mod for reference on how to do a merchant.

 

Both of these tasks arent really very hard, Quest Creation is just tedious, write everything out beforehand and take notes step-by-step on where you are in the quest creation process, especially what dialogue file activates what stage, this helps immensely.

 

I hope this helps with a couple of the things you asked about!

 

 

Don't know if this helps or not, but I saw and figured I would repost it.

 

Edit tk102: Added hyperlink to original post

Link to comment
Share on other sites

Originally posted by StrangeJ

If it is a custom module do you need to do anything in the *.git file, since there is a "store list" list?

 

You don't need to.. It's a choice you have, just like with creatures, placeables, etc.

 

You can reference a store object in the GIT file, or you can spawn it dymanically using CreateObject function. (stoffe's example above)

Link to comment
Share on other sites

Originally posted by Xcom

You don't need to.. It's a choice you have, just like with creatures, placeables, etc.

 

You can reference a store object in the GIT file, or you can spawn it dymanically using CreateObject function. (stoffe's example above)

 

While it you can use a script to create and spawn objects. It is much cleaner and takes up less space in the module and in your overide if you edit the Git and are files. As these files are performing your same scripted functions of placing a creature or object or whatever else at a set location. If you create a seperate script to do this in a custom module then you are simply adding extra work for yourself.

Link to comment
Share on other sites

Originally posted by Darkkender

While it you can use a script to create and spawn objects. It is much cleaner and takes up less space in the module and in your overide if you edit the Git and are files. As these files are performing your same scripted functions of placing a creature or object or whatever else at a set location. If you create a seperate script to do this in a custom module then you are simply adding extra work for yourself.

 

There is one microscopic advantage to spawning stores dynamically. Since they won't be created until you actually need them they don't take up space until then in the savegame and makes the areas load unnoticably faster, since store objects contain the object instances of the items and not just blueprint references once created.

 

Not that it would really matter though unless you have an area with lots of different stores containing a huge number of items where the player won't browse them all ASAP. :)

Link to comment
Share on other sites

Originally posted by stoffe -mkb-

There is one microscopic advantage to spawning stores dynamically. Since they won't be created until you actually need them they don't take up space until then in the savegame and makes the areas load unnoticably faster, since store objects contain the object instances of the items and not just blueprint references once created.

 

Not that it would really matter though unless you have an area with lots of different stores containing a huge number of items where the player won't browse them all ASAP. :)

 

There are actually quite a few differences albeit each one small and minor. The first if you enter them directly in the Git & Are files you save file size space for the overall module. Entering the them in as a seperate script for each different type of spawn creates a script which is 3 times the byte value of the entries being predefined in the git & are's. When you get to crafting large scale modules for others to download you want save the file size as much as possible. You create your scripts for the special encounters triggers and events within the module. Something like a merchant is likely to be there as a constant.

 

When I first was building the tomb of Jesset Dal Kest I discovered how much of a difference this single factor made in the end result of the modules. Not to mention the time that gets consumed in writing each script even if it is simple copy pasting followed by compiling the script.

Link to comment
Share on other sites

Originally posted by Darkkender

If you create a seperate script to do this in a custom module then you are simply adding extra work for yourself.

 

And you don't consider modifying Git files as "work"?

 

Something like a merchant is likely to be there as a constant.

Why? Most K2 stores are populated with items dynamically, and you obviously need the script to actually open the store, so you'll be using a script one way of the other. Check for example 301Nar_s module. It has

 

a_stock_kodin

a_openkodinstore

a_stock_geeda

a_opengeedastore

etc.

 

Granted, most stores are still defined in the GIT, but they could have been created on the spot just as well. I mean according to what you say, CreateObject (in conjunction with store objects) has no purpose at all.

 

Originally posted by Darkkender

Entering the them in as a seperate script for each different type of spawn creates a script which is 3 times the byte value of the entries being predefined in the git & are's.

 

Adding an entry of a single store into a git file adds apprx. 125 bytes. (Just checked)

 

compiling the line

 

void main()
{
object oStore = CreateObject(OBJECT_TYPE_STORE, "somestore", GetLocation(GetFirstPC()));
}

 

outputs apprx. 85 bytes.

 

Stoffe's script above is 254 bytes. Jee, I guess users with 54K modems will have big problem now. :D

Seriously, I agree it's important to save disk space, but let's use some common sense here, okay.

 

Not to mention the time that gets consumed in writing each script even if it is simple copy pasting followed by compiling the script.

 

I imagine this is a matter of personal preference. I find writing scripts to be less troublesome than poking around in GFF files.

Also, GFFEditor will corrupt your camera list in the GIT file when you edit it.

Link to comment
Share on other sites

I agree with Xcom. Let's use common sense and keep it simple.

 

If you create a custom module, it definitely becomes a matter of personal preference. I do not believe the file size is an issue here.

 

However, if you only add a few npcs and a merchant or two to an existing game module to make a side quest, repackaging everything is way overkill, notwithstanding the fact that it is a potential source of mod conflicts. I think modders should avoid this unless there is no other solution. Think of the end user who would have to verify the content of the modules in addition to the override folder....

Link to comment
Share on other sites

I guess we were talking slightly of 2 different things. I was talking about one of the static elements of a module the actual merchant him/herself. While you are talking about the dynamic aspect the everchanging inventory aspect depending on certain variables within game. The main reason for the git and are files are to define your static aspects of a module. Every time you enter that module "Joe" vendor will be in "X" location. The scripts and dialogues are there to define the dynamic aspects of a module. "Joe Vendors inventory now carries lightsaber crystals because you built your lightsaber." I don't disagree in the least bit about the using the scripting for the dynamic everchanging aspects only on the static aspects. I discovered writing a seperate script to spawn each and every placeable as static elements when you enter the module was alot more effort than was needed.

 

Also static elements being spawned for the first time when entering a module take longer to load and create when spawned via scripting than those that are spawned via the git and are files. The reason is your asking your computer to execute and run a seperate subprogram every time the game runs a script. Versus the git and are files which are static elements and the main program itself is reading the information for that area without having to execute a subprogram.

 

However as Darth333 eloquently put it "a matter of personal preference." So I shall end it at that.

Link to comment
Share on other sites

What exactly do you mean by "static"?

 

Correct me if I am wrong, but ARE files define the static elements, and GIT file define the dynamic elements of the module.

I've never seen anything related to merchants in the ARE files. Well, I haven't looked through all of them, but what's defined there?

 

I was talking about one of the static elements of a module the actual merchant him/herself.

 

The actual merchant? That would be NPC, a creature.

How can npc be a static element?

 

Well, you totally lost me. :confused::nut:

Link to comment
Share on other sites

Originally posted by Xcom

What exactly do you mean by "static"?

 

Correct me if I am wrong, but ARE files define the static elements, and GIT file define the dynamic elements of the module.

I've never seen anything related to merchants in the ARE files. Well, I haven't looked through all of them, but what's defined there?

 

 

 

The actual merchant? That would be NPC, a creature.

How can npc be a static element?

 

Well, you totally lost me. :confused::nut:

 

"Static" meaning unchanging or constant. A NPC, A creature that is always present in a module from the first time you enter it untill the game is over is a "Static" element as much as the various containers that are scattered about.

 

Since I don't have the actual git and are files in front of me I can't recall which ones define which elements. For the most part I believe the git file is the one I should be talking about.

 

The ARE file if I'm recalling it correctly defines the appearance of the module to a certain respect.

 

Meanwhile if that is the case then the GIT file defines where each of the "static" elements are located at, placeables, doors, encounters, triggers, waypoints, creatures, sounds, & any other gff file related element that can be placed somewhere.

 

Now the actual utm files used by a merchant creature should be accessed via a scripted event. I think this is where we started confusing each other in our conversation above. The UTM file is "Dynamic" or ever changing while the merchant themself(the UTC) is "Static".

 

Does this make what I was talking about more clear.

Link to comment
Share on other sites

Hmm.. doesn't seem to work :(

After the dialogue, nothing happens.

 

Here's what I've done:

 

Dialogue: script: merchantarm98

 

merchantarm98.ncs (yes compiled):

 

void main() {
object oStore = GetObjectByTag("merchantarm99");

if (!GetIsObjectValid(oStore))
	oStore = CreateObject(OBJECT_TYPE_STORE, "merchantarm99", GetLocation(OBJECT_SELF));

if (GetIsObjectValid(oStore))
	DelayCommand(0.1, OpenStore(oStore, GetPCSpeaker()));
}

 

merchantarm99.utm:

BuySellFlag      [bYTE]       = 3
Comment          [CExoString] = 
ID               [bYTE]       = 5
ItemList         [List]       = ...
...
KTGameVerIndex   [iNT]        = 0
KTInfoDate       [CExoString] = 29 March 2005 09:41:33
KTInfoVersion    [CExoString] = 1.0.1900.40262
LocName          [CExoLocString] = 1 strings
MarkDown         [iNT]        = 25
MarkUp           [iNT]        = 100
OnOpenStore      [CResRef]    = 
ResRef           [CResRef]    = merchantarm99
Tag              [CExoString] = merchantarm99

Link to comment
Share on other sites

Originally posted by StrangeJ

Hmm.. doesn't seem to work :(

After the dialogue, nothing happens.

 

Here's what I've done:

 

Dialogue: script: merchantarm98

 

merchantarm98.ncs (yes compiled):

 

void main() {
object oStore = GetObjectByTag("merchantarm99");

if (!GetIsObjectValid(oStore))
	oStore = CreateObject(OBJECT_TYPE_STORE, "merchantarm99", GetLocation(OBJECT_SELF));

if (GetIsObjectValid(oStore))
	DelayCommand(0.1, OpenStore(oStore, GetPCSpeaker()));
}

 

 

Change the line:

DelayCommand(0.1, OpenStore(oStore, GetPCSpeaker()));

 

To:

DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));

 

...and it should work. At least it works in my game. :)

 

Seems like the game needs a short bit of time between creating the store and it can be launched, for some odd reason.

 

Also double-check that you have assigned the script to the dialog node. It seems the DLG Editor sometimes doesn't save changes unless you select another node in the hierarchy after you have edited one.

Link to comment
Share on other sites

that whole 0.5(second?) wait time to start the store actually really interesting(annoying), considering that it can't be that much data in terms of bytes that the game has to process to open the store. i wonder if anyone's already checked that out...

do you guys know if you've gotta up the wait time to open a store with a much larger number of items?

Link to comment
Share on other sites

do you guys know if you've gotta up the wait time to open a store with a much larger number of items?

 

Would make sence since as far as I have gathered(which isn't much) each item is actually loaded into the shop when loaded (don't quote)

 

My shop was huge compared to normal shops, which is probably why I must have had to wait for 0.5 secs...

Link to comment
Share on other sites

Originally posted by coaxmetal

that whole 0.5(second?) wait time to start the store actually really interesting(annoying), considering that it can't be that much data in terms of bytes that the game has to process to open the store. i wonder if anyone's already checked that out...

do you guys know if you've gotta up the wait time to open a store with a much larger number of items?

 

Well, it has to create all the items to populate the store, but I can't see that taking much time either. It's a bit odd that CreateObject() finishes execution before the object it created is ready to use. It does after all return a valid object.

 

Don't know if you have to wait a full half a second to start the store, I was just using a safety margin. 0.1 was apparently too short though.

 

If you want to play it safe I suppose you could split the script functionality in two parts like this:

 

void main() {
int nParam = GetScriptParameter(1);
object oStore = GetObjectByTag("merchantarm99");

if (nParam == 0) {
	if (!GetIsObjectValid(oStore))
		oStore = CreateObject(OBJECT_TYPE_STORE, "merchantarm99", GetLocation(OBJECT_SELF));
}
else {
	if (GetIsObjectValid(oStore))
		DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));
}
}

 

Attach the script to the first node of conversation as well and set the P1 field in DLG Editor of that script to 0.

 

And then, where the store should start, attach the script and set the P1 field to 1. That way you won't spawn the store and open it in the same script execution.

Link to comment
Share on other sites

Originally posted by Darkkender

Does this make what I was talking about more clear.

 

clear- yes, but that doesn't make it true. :p

 

Originally posted by Darkkender

"Static" meaning unchanging or constant. A NPC, A creature that is always present in a module from the first time you enter it untill the game is over is a "Static" element as much as the various containers that are scattered about.

 

According to BioWare documentation, NPCs and placeables are NOT static objects. Why? Because they can be affected by scripts and destroyed. That makes them dynamic as far the Odyssey engine is concerned.

There are all kinds of NPCs defined in the GIT, also the hostiles.. whom you are supposed to kill. Obviously, they won't be present in the module until the game is over. How do you explain that? :D

 

The ARE file if I'm recalling it correctly defines the appearance of the module to a certain respect.

 

Yes, I know that. But what's defined there in regard to merchants? This is what I wanted to know because you kept mentioning are files and we are talking about stores and merchants.

 

The UTM file is "Dynamic" or ever changing while the merchant themself(the UTC) is "Static".

 

UTMs are dynamic, and so are the UTCs. Actually, whole GIT file is "ever changing" as you put it. The game keeps the track of changes in the module and saves the GIT in the sav file. For example, if you kill the NPC, and immediately save your game. Then load the game. You will see a corpse of the NPC where you left it; you won't see NPC re-appearing where he initially was. The game will save the states of all objects in the GIT, and that's what makes it all "dynamic" (not the fact the they don't walk.. or that they are always present).

Link to comment
Share on other sites

Originally posted by Xcom

clear- yes, but that doesn't make it true. :p

According to BioWare documentation, NPCs and placeables are NOT static objects. Why? Because they can be affected by scripts and destroyed. That makes them dynamic as far the Odyssey engine is concerned.

There are all kinds of NPCs defined in the GIT, also the hostiles.. whom you are supposed to kill. Obviously, they won't be present in the module until the game is over. How do you explain that?

 

Okay so now your going to argfue semantics of how I was defining and explaining my understanding of something. As much as these objects are "dynamic" as you explained they are just as much "static" from the simple state in which I explained it. As I said semantics.

 

Yes, I know that. But what's defined there in regard to merchants? This is what I wanted to know because you kept mentioning are files and we are talking about stores and merchants.

 

While you were quoting you must have missed the 2nd paragraph.

 

Originally posted by Me

Since I don't have the actual git and are files in front of me I can't recall which ones define which elements. For the most part I believe the git file is the one I should be talking about.

 

I had been using the are and git file names interchangeably because I didn't have either available to look at in front of me. So I was interghanging due to my uncertaintey.

 

I think my original point was gotten across well enough. That and we have really derailed the original topic into nitpicking how somebody defines/understands something. So I shall cease carrying it on. If you really want to continue you could PM me.

Link to comment
Share on other sites

Xcom was referring to the official documentation concerning .are and .ifo format...and it's not just semantics...

 

While we do appreciate your efforts to help on the boards, Darkkender, sometimes you should verify your information or it could lead to confusion, especially if the person asking the question is new to Kotor modding (no offense meant).

 

Now back on topic.

 

You can also find the documentation on the store format here but stoffe -mkb- already made an excellent job with the tutorial above. It will definitely be added to the tutorial section (I can't do it before this evening).

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...