Aller au contenu

Photo

Merchant Source Code


16 réponses à ce sujet

#1
Nodrak

Nodrak
  • Members
  • 144 messages
I was hoping that maybe someone from Bio could help me here, I was looking to figure out how merchants handle their items with regard to level scaling, among other things, and was dismayed to find that merchant_core.nss is blank.  Now, either this class truly is emtpy, or the source was stripped :(

If this is on purpose, then can I ask for a description of what the following variables do?

Merchant_Counter_1
Merchant_Counter_2
Merchant_Counter_3
Merchant_Is_Scaled  (I can guess this one, even though it is of type INT)
Merchant_Level_override 
Merchant_Level_Modifier 
Merhcant_High_Chance

I can surmise the basics of the last 4, but they are still left undocumented and unreferenced, not in code, the source, or the wiki.

Thank you in advance to anyone with answers.

#2
AND04

AND04
  • Members
  • 154 messages

Nodrak wrote...

 (I can guess this one, even though it is of type INT)


there is no bolean or bit datatype here - TRUE/FALSE is defined as an INT.

#3
Nodrak

Nodrak
  • Members
  • 144 messages
Yea, I was used to that already, but the item scaling code uses int to define the maximum and/or minimum level of scaling 1-7 for the basic setup, (or 40-47 iirc if you want the 'real' value for weapons).

Modifié par Nodrak, 20 novembre 2009 - 03:51 .


#4
BryanDerksen

BryanDerksen
  • BioWare Employees
  • 273 messages
Merchant_core really is blank. We created "default" event-handler scripts for all of the basic resource types, but in the case of merchants there was no particular default event-handling behavior in need of scripting support.



I don't know what the variables are used for, I presume some of them are used by the treasure system.

#5
Nodrak

Nodrak
  • Members
  • 144 messages
Thanks for clearing that up, I will look around to see if I can find what I need, but I might be back asking about details if it turns out it is handled in the engine Posted Image

Modifié par Nodrak, 20 novembre 2009 - 04:49 .


#6
SilentCid

SilentCid
  • Members
  • 338 messages
I just curious on how to connect the Merchant with the NPC. This is what I have:


#include "events_h"


void main()

{
   object oStore = GetObjectByTag("store_" + GetTag(oMerchantOwner));
   if(IsObjectValid(oStore))
      OpenStore(oStore);
   else
      Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");

}

Getting this error  Variable defined without type (while compiling var_constants_h.nss)

Any ideas? Did I forget the header file for the type it wants?

#7
weriKK

weriKK
  • Members
  • 106 messages
In order to use a merchant first you have to create one in game space. This is rather tricky because the CreateObject function is unable to create objects from merchant resources. This means that your only option to create a merchant is placing it in a custom area you create with the toolset.



Since you can not edit the single player areas at the moment due to the lack of the official assets, you not only have to find a way to load your areas, but you have to load them in a way that you can access it's resources while you are in another area (um, hope this makes sense).



Either way, if you fiddle a little bit more with the wiki you will find Area lists. These lists group areas in a way that they can be loaded together in the memory. You can notice these groupped areas in game because they have no real loading screen between area changes, only a fast fade in and fade out while the game teleports your character to the other area of the same group. Good examples are the inside and the outside areas of Flemeth's hut or the teleports in the Fade.



Because these areas are grouped and loaded as one unit into the memory, they share resources too. You can exploit this to place your merchant in a tiny, unaccessible area, then add this area to the area list which contains the zone you want to access your merchant from.



Now, - if you are still following - this is where things actually get interesting, because there is no area list 2da file provided to you with the toolset. What you will have to do is actually open up the official single player erf file that contains all the designer area data, export the area list you need, modify it using the toolset and use it to override the default one.



After you went through all this, you should be able to access your merchant. I know looks kinda scary and it is quite vague but I hope it gives you a general guideline of what you should explore to make them work.

#8
Axe_Murderer

Axe_Murderer
  • Members
  • 279 messages

SilentCid wrote...

I just curious on how to connect the Merchant with the NPC. This is what I have:


#include "events_h"


void main()

{
   object oStore = GetObjectByTag("store_" + GetTag(oMerchantOwner));
   if(IsObjectValid(oStore))
      OpenStore(oStore);
   else
      Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");

}

Getting this error  Variable defined without type (while compiling var_constants_h.nss)

Any ideas? Did I forget the header file for the type it wants?

You are getting this error because you are trying to use a variable (oMerchantOwner) in the first line which has never been defined or given a value. You need:
object oMerchantOwner = ????;
before  you try to use it. The ???? must be replaced by the appropriate method to identify the correct NPC (probably OBJECT_SELF but I'm not positive about that).

#9
SilentCid

SilentCid
  • Members
  • 338 messages

weriKK wrote...

In order to use a merchant first you have to create one in game space. This is rather tricky because the CreateObject function is unable to create objects from merchant resources. This means that your only option to create a merchant is placing it in a custom area you create with the toolset.

Since you can not edit the single player areas at the moment due to the lack of the official assets, you not only have to find a way to load your areas, but you have to load them in a way that you can access it's resources while you are in another area (um, hope this makes sense).

Either way, if you fiddle a little bit more with the wiki you will find Area lists. These lists group areas in a way that they can be loaded together in the memory. You can notice these groupped areas in game because they have no real loading screen between area changes, only a fast fade in and fade out while the game teleports your character to the other area of the same group. Good examples are the inside and the outside areas of Flemeth's hut or the teleports in the Fade.

Because these areas are grouped and loaded as one unit into the memory, they share resources too. You can exploit this to place your merchant in a tiny, unaccessible area, then add this area to the area list which contains the zone you want to access your merchant from.

Now, - if you are still following - this is where things actually get interesting, because there is no area list 2da file provided to you with the toolset. What you will have to do is actually open up the official single player erf file that contains all the designer area data, export the area list you need, modify it using the toolset and use it to override the default one.

After you went through all this, you should be able to access your merchant. I know looks kinda scary and it is quite vague but I hope it gives you a general guideline of what you should explore to make them work.




Yeah wasn't my intention to add this to a the main campaign, if you were talking to me.

#10
SilentCid

SilentCid
  • Members
  • 338 messages

Axe_Murderer wrote...

SilentCid wrote...

I just curious on how to connect the Merchant with the NPC. This is what I have:


#include "events_h"


void main()

{
   object oStore = GetObjectByTag("store_" + GetTag(oMerchantOwner));
   if(IsObjectValid(oStore))
      OpenStore(oStore);
   else
      Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");

}

Getting this error  Variable defined without type (while compiling var_constants_h.nss)

Any ideas? Did I forget the header file for the type it wants?

You are getting this error because you are trying to use a variable (oMerchantOwner) in the first line which has never been defined or given a value. You need:
object oMerchantOwner = ????;
before  you try to use it. The ???? must be replaced by the appropriate method to identify the correct NPC (probably OBJECT_SELF but I'm not positive about that).



That fixed the error now just have to fix the part where it opens the store every 10 seconds.

#11
Axe_Murderer

Axe_Murderer
  • Members
  • 279 messages
I'd say you're missing event processing in there. The way it's written it will do those things whenever any event at all occurs.

#12
SilentCid

SilentCid
  • Members
  • 338 messages
I figured it out, I added the script to the creature instead of the conversation resource.

This is what I put

#include "events_h"
#include "plt_gen00pt_generic_actions"
#include "wrappers_h"

void main()
{
   
 object oMerchantOwner = GetMainControlled();
 object oStore = GetObjectByTag("store_" + GetTag(oMerchantOwner));
 if(IsObjectValid(oStore))
     OpenStore(oStore);
     else
      Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");

}

I change the OBJECT_SELF to the GetMainControlled(); included the "plt_gen00pt_generic_actions" so that it opens when via plot.

Modifié par SilentCid, 20 novembre 2009 - 08:53 .


#13
SuperD-710

SuperD-710
  • Members
  • 130 messages
So did anyone find out how to enable auto item level scaling (like camp merchant or soldier's peak blacksmith) on your custom merchant? I know it's the those variables mentioned in the first post as the camp merchant had them all set to zero.

Modifié par SuperD-710, 13 décembre 2009 - 10:14 .


#14
Craig Graff

Craig Graff
  • Members
  • 608 messages
Merchants are scaled when first opened, but this can easily be reset by setting MERCHANT_IS_SCALED back to 0 . Check out ScaleStoreItems in core_h.nss

Modifié par Craig Graff, 14 décembre 2009 - 02:36 .


#15
SuperD-710

SuperD-710
  • Members
  • 130 messages

Craig Graff wrote...

Merchants are scaled when first opened, but this can easily be reset by setting MERCHANT_IS_SCALED back to 0 . Check out ScaleStoreItems in core_h.nss


Thank you very much. This answers a lot of questions.

But when(which event trigger) does the game call ScaleStoreItems? When does it reset MERCHANT_IS_SCALED back to 0? Are the done on open/close or on area load? Or during conversation?

EDIT: I also found a piece of weird code:

int nStoreBase = GetLocalInt(oStore, "MERCHANT_LEVEL_OVERRIDE");
    int nStoreLevel;
    if (nStoreLevel > 0)
    {
        nStoreLevel = nStoreBase;
    } else
    {
        nStoreLevel = GetLevel(GetHero());
    }

As you can see, the if statement, using nStoreLevel as condition, is right after the declaration of the variable. What does that do exactly? Were the condition supposed to be nStoreBase > 0?

Modifié par SuperD-710, 14 décembre 2009 - 06:54 .


#16
Craig Graff

Craig Graff
  • Members
  • 608 messages
That does seem likely, doesn't it.

As for when things happen - that is up to you. Before any call to OpenStore, ScaleStoreItems should be called. If you want to want to reset the scaling, either use the optional bReset parameter or SetLocalInt(oMerchant, MERCHANT_IS_SCALED, FALSE) before calling on the function or plot flag that calls ScaleStoreItems.

From gen00pt_generic_actions.nss:

case GEN_OPEN_STORE:
{
    object oStore = GetObjectByTag(STORE_PREFIX + GetTag(oConversationOwner));
    if (IsObjectValid(oStore))
    {
        ScaleStoreItems(oStore);
        OpenStore(oStore);
    }
    else
    {
        Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");
    }
        break;
}

Modifié par Craig Graff, 14 décembre 2009 - 07:53 .


#17
SuperD-710

SuperD-710
  • Members
  • 130 messages

Craig Graff wrote...

That does seem likely, doesn't it.

As for when things happen - that is up to you. Before any call to OpenStore, ScaleStoreItems should be called. If you want to want to reset the scaling, either use the optional bReset parameter or SetLocalInt(oMerchant, MERCHANT_IS_SCALED, FALSE) before calling on the function or plot flag that calls ScaleStoreItems.

From gen00pt_generic_actions.nss:

case GEN_OPEN_STORE:
{
    object oStore = GetObjectByTag(STORE_PREFIX + GetTag(oConversationOwner));
    if (IsObjectValid(oStore))
    {
        ScaleStoreItems(oStore);
        OpenStore(oStore);
    }
    else
    {
        Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");
    }
        break;
}


Thank you very much. One final question: Looking at the code, ScaleStoreItems should also work on any object/placable with an inventory? Get/Set parameters should do nothing on the absense of "MERCHANT_IS_SCALED" on another placable right? Or is a custom scale code needed?