Salk

[KotOR] Store buying prices

Recommended Posts

Hello!

Anyone knows if it is possible to make a specific store buy specific items at a higher or lower price than market value? 

Case in point: I would like Crattis on Dantooine to pay more for crystals.

Thanks!

Share this post


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

Iirc, every "store" is its own. Thus, you just need to edit the merchant in question.

Share this post


Link to post
Share on other sites
1 hour ago, Qui-Gon Glenn said:

Iirc, every "store" is its own. Thus, you just need to edit the merchant in question.

Yes, of course.

OpenStore() would allow me to dynamically change the buy/sell ratio for each store but the problem here is that it'd apply to all items, rather than a selected few.

Has anyone seen ChangeItemCost() used anywhere?

 

Share this post


Link to post
Share on other sites
6 minutes ago, Salk said:

Anyone knows if it is possible to make a specific store buy specific items at a higher or lower price than market value?

Case in point: I would like Crattis on Dantooine to pay more for crystals.

Has anyone seen ChangeItemCost() used anywhere?

Try to take a look at what's inside this mod. I have just had a slight view to it, and it seems it had all the information you needed; particularly with the k_pdan_generals.ncs, it seems. 🤔

Edited by ebmar

Share this post


Link to post
Share on other sites
7 hours ago, ebmar said:

Try to take a look at what's inside this mod. I have just had a slight view to it, and it seems it had all the information you needed; particularly with the k_pdan_generals.ncs, it seems. 🤔

Unfortunately, all it does is to make Crattis sell at a more expensive price (115% more expensive) than it would in the non modded game.

Share this post


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

Have you looked at Suvam? He buys for more.

Share this post


Link to post
Share on other sites

What I am trying to accomplish here is not to have a merchant buy everything for more or less.

I aim to make a merchant buy and sell only some particular items (any crystal) for more. 

At the moment I changed k_pdan_generals.ncs as following (I had to crate a new Global Boolean just to keep track of Crattis' proposal to buy the crystals) and it seems to be working fine but I am not really very confident about it:

void main() { 
  object oPC = GetPCSpeaker();
  object oStore = GetObjectByTag("dan_general");
  object oItem = GetFirstItemInInventory(oPC);
  if (GetGlobalBoolean("CRATTIS_CRYSTAL") == TRUE) {
    while(oItem != OBJECT_INVALID)
    {
      if ((GetTag(oItem) == "g_w_sbrcrstl01") || (GetTag(oItem) == "G_W_SBRCRSTL02") || (GetTag(oItem) == "G_W_SBRCRSTL03") || (GetTag(oItem) == "G_W_SBRCRSTL04") || (GetTag(oItem) == "G_W_SBRCRSTL05") || (GetTag(oItem) == "G_W_SBRCRSTL06") || (GetTag(oItem) == "G_W_SBRCRSTL07") || (GetTag(oItem) == "G_W_SBRCRSTL08") || (GetTag(oItem) == "G_W_SBRCRSTL09") || (GetTag(oItem) == "G_W_SBRCRSTL10") || (GetTag(oItem) == "G_W_SBRCRSTL11") || (GetTag(oItem) == "G_W_SBRCRSTL12") || (GetTag(oItem) == "G_W_SBRCRSTL13") || (GetTag(oItem) == "G_W_SBRCRSTL14") || (GetTag(oItem) == "G_W_SBRCRSTL15") || (GetTag(oItem) == "G_W_SBRCRSTL16")|| (GetTag(oItem) == "G_W_SBRCRSTL17")|| (GetTag(oItem) == "G_W_SBRCRSTL18")|| (GetTag(oItem) == "G_W_SBRCRSTL19"))
      {
        ChangeItemCost(GetTag(oItem), 1.25);
        DelayCommand(1.0, ChangeItemCost(GetTag(oItem), 1.0));
      }
      oItem=GetNextItemInInventory(oPC);
    }
  }
    DelayCommand(0.2, OpenStore(oStore, oPC, 0, 0));
}

 

Suggestion for code improvements always very welcome.


Thanks!

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, Salk said:

I had to crate a new Global Boolean just to keep track of Crattis' proposal to buy the crystals

You shouldn't need to do that. A less complicated way (no messy 2DA editing) would be to use one of Crattis' local booleans. This is done more often in K2, with several numbers being reserved for such things, but in K1, local booleans 49 through 58 are unused as far as I can tell. Local booleans are set and checked the same way as global booleans, except they are set and checked for a specific object, in this case Crattis.

  • Thanks 1

Share this post


Link to post
Share on other sites
2 minutes ago, JCarter426 said:

You shouldn't need to do that. A less complicated way (no messy 2DA editing) would be to use one of Crattis' local booleans. This is done more often in K2, with several numbers being reserved for such things, but in K1, local booleans 49 through 58 are unused as far as I can tell. Local booleans are set and checked the same way as global booleans, except they are set and checked for a specific object, in this case Crattis.

Thank you for the suggestion!

Share this post


Link to post
Share on other sites

Also, rather than checking each crystal's tag, you could just check the base item type:

if( GetBaseItemType(oItem) == BASE_ITEM_LIGHTSABER_CRYSTALS )

That way it'll apply to modded crystal items as well.

Assuming the price change method actually checks out, I can think of at least one other merchant that would benefit from such adjustment. Everybody in the game says to go to Fazza to sell wraid plates, but of course he buys them at the same default price as anybody, which means it's more profitable to trek all the way to Yavin and sell them there with Suvam's discount.

  • Like 2

Share this post


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

Anything to get rid of that ginormous OR stack.

 

Now that I understand what you were asking, JC has given one suggestion I would have made, and one I didn't think of. So, winning for you :p

Share this post


Link to post
Share on other sites

If I'm reading the script right, though, ChangeItemCost is going to permanently change the cost of items in the player's inventory and the price change isn't going to be limited to Crattis. I'm guessing this function is related to the kolto price hikes and wasn't intended to be used in this manner. But I'm thinking it could be made to work if there were another script that restores the item cost.

Crattis' heartbeat or the OnExit script if there is one for that area already would be good options. I'd also attach something to the other merchants in that module to be safe, so opening their stores resets the price, in the event that you manage to talk to them before the price is otherwise corrected.

Share this post


Link to post
Share on other sites

Thanks for the suggestion, JC.

The ChangeItemCost() function does keep the altered price for the item but I reset it with 

DelayCommand(1.0, ChangeItemCost(GetTag(oItem), 1.0));

which seems to work, returning the original value of the crystals.

Since I am here asking for help and you are kindly giving assistance, would you know how to convert the X, Y, Z Orientation/Position I get for an object in the GIT file into valid coordinates for the Vector parameter in the CreateObject() function?

Case in point. Under Creature list:

XOrientation: 0

XPosition: 339.387878417969

YOrientation: 1

YPosition: 145.786026000977

ZPosition: 56.140998840332

If I was to spawn a creature at exactly the same place what X,Y,Z values should I use for Vector?

Thanks!

UPDATE: I shamelessly ask for more scripting advice. Can I use GetIsObjectValid() as condition to check whether or not a certain creature is already present in an area?

Edited by Salk
Asked for additional scripting advice

Share this post


Link to post
Share on other sites
16 hours ago, Salk said:

The ChangeItemCost() function does keep the altered price for the item but I reset it with 


DelayCommand(1.0, ChangeItemCost(GetTag(oItem), 1.0));

which seems to work, returning the original value of the crystals.

Hmm, I wouldn't have expected that to work. I can see why it might, but I guess I'm not so optimistic when it comes to predicting the game's behavior. Are the prices still correct if you switch back and forth between the buy and sell options? If all the prices are locked down when the store first opens, that would be a welcome surprise.

16 hours ago, Salk said:

would you know how to convert the X, Y, Z Orientation/Position I get for an object in the GIT file into valid coordinates for the Vector parameter in the CreateObject() function?

The XYZ coordinates are the same. The only difference is the orientation, which I believe is a quaternion in the GIT file, just with some of the data missing.

A quaternion with the values (0, 1, 0, 1) is equivalent to (0, 90, 0) in standard Euler XYZ degrees. It looks like the GIT file only bothers with the first two quaternion values (stored as XOrientation and YOrientation) because creatures aren't rotated along the Z axis and the real part is assumed to be 1. So the proper quaternion would be (XOrientation, YOrientation, 0, 1). This online calculator seems to convert correctly.

I believe whatever output value isn't 0 is your float angle for the script, but I'm not entirely sure.

16 hours ago, Salk said:

I shamelessly ask for more scripting advice. Can I use GetIsObjectValid() as condition to check whether or not a certain creature is already present in an area?

Yes. :)

Share this post


Link to post
Share on other sites

JC,

first of all, thank you again. I owe you, DarthParametric and others like the very missed Fallen Guardian a lot and I would like to repay sometimes in the future.

Said that, I will make more tests about the store prices soon and will keep you and everyone else who may have an interest updated. I also didn't expect it to work, honestly. But I tried and I was as surprised as  you are. Once in Tatooine I will like to follow your suggestion and increase the wraid plates purchase price for Fazza. Very good suggestion!

I checked the calculator and it is a bit complex for me. In what field should I enter those X,Y,Z positions values I found in the GIT file? 

Cheers! :cheers:

 

Edited by Salk
Stumped with the calculator.
  • Light Side Points 1

Share this post


Link to post
Share on other sites

Yeah, it might not even be worth trying to calculate the orientation given that almost all of the time they're spawned facing a cardinal direction, which is really easy to figure out.

So, you can get the XYZ position from the GIT. Based on your original data...

 XOrientation: 0

XPosition: 339.387878417969

YOrientation: 1

YPosition: 145.786026000977

ZPosition: 56.140998840332 

That would be...

Vector(339.387878417969, 145.786026000977, 56.140998840332)

For the orientation, you can just start at 0 and and if that doesn't work, rotate to fix it.

Location(Vector(339.387878417969, 145.786026000977, 56.140998840332), 0.0)

Then if 0.0 doesn't work, I'd suggest trying 90.0, 180.0, and 270.0 (or -90.0) until you got the right one. Scripting is in standard 360 degrees, no quaternions or radians, so that's not so bad to figure out manually. Good luck. :)

  • Thanks 1

Share this post


Link to post
Share on other sites
18 hours ago, Salk said:

If I was to spawn a creature at exactly the same place what X,Y,Z values should I use for Vector?

I am so curious of what's actually going on there! :detective:

Share this post


Link to post
Share on other sites

Hello, ebmar!

5 hours ago, ebmar said:

I am so curious of what's actually going on there! :detective:

I have been working long and hard on the Sandral/Matale feud quest in the past and I am attempting to polish it even further. I have improved the flow of the mission in more than one way and today I decided to remove the droid outside of the Sandral estate once the Sandral/Matale quest starts. It will return (hence the need to spawn it again in the same spot - and it does, I just tested it) once you have talked with Alan Matale first (it makes more sense that way under a narrative point of view). It is part of a rationalization/bug fixing process for a quest that was originally very broken.

And since I am in Dantooine I killed for the first time Juhani and noticed how Belaya reacts to her death BUT only if the player decides to talk to her. I found it plainly wrong so I am trying to change things a bit with the following addition made to k_pdan_belaya_d.ncs called from within k_pdan_init_bel.ncs if DAN_JUHANI_PLOT is 2 (Juhani killed):

    if ((GetUserDefinedEventNumber() == 11)) {
        ClearAllActions();
    ActionMoveToObject(oPC,TRUE,7.5);
        ActionStartConversation(oPC, "", 0, 0, 1, "", "", "", "", "", "", 0);
    }

This works but I would like to know how to make it into a proper cutscene. 

The way it is now is such that there is no pause in the game. Instead I would like to make it so that a cutscene removes control from the player and the screen changes to letterbox to make the whole sequence more cinematic.

When doing this with the Infinity Engine (I scripted a little there when modding Baldur's Gate) there was a specific function called StartCutSceneMode() and I wonder if something similar exists here.

Thoughts?

Cheers! :cheers:

  • Light Side Points 1

Share this post


Link to post
Share on other sites

That's actually pretty simple. A cutscene in KotOR is always a conversation. So all you have to do is swap the conversation start and the move command.

But then she'll start talking while walking towards the player. To fix that you'll need to add an empty entry to the beginning of the dialog with the proper delay and also make it unskipable. That should do the trick.

  • Like 2

Share this post


Link to post
Share on other sites
12 hours ago, Kexikus said:

That's actually pretty simple. A cutscene in KotOR is always a conversation. So all you have to do is swap the conversation start and the move command.

But then she'll start talking while walking towards the player. To fix that you'll need to add an empty entry to the beginning of the dialog with the proper delay and also make it unskipable. That should do the trick.

Hello, Kexikus!

Yes, I remember now I asked about this in the past (my memory, really...) and it was indeed quite easy. Now this small cutscene works as intended. Belaya approaches the player if they killed Juhani. The only minor gripe I have is that that during the running animation the camera is on Belaya's face. I should use another static camera angle instead. I added cameras before when I worked on restoring Xor on Tatooine. Of course I forgot everything. 😉

Cheers!

Share this post


Link to post
Share on other sites
2 hours ago, Salk said:

Hello, Kexikus!

Yes, I remember now I asked about this in the past (my memory, really...) and it was indeed quite easy. Now this small cutscene works as intended. Belaya approaches the player if they killed Juhani. The only minor gripe I have is that that during the running animation the camera is on Belaya's face. I should use another static camera angle instead. I added cameras before when I worked on restoring Xor on Tatooine. Of course I forgot everything. 😉

Cheers!

Before you go through the trouble of creating a new static camera, you can try to play around with the CameraAngle in the dialog file. According to an old tutorial by Tupac Amaru they stand for:

Quote
  • CameraAngle = 1 will show a close-up of the current speaker,
  • 2 will show the current speaker and place the camera behind the player,
  • 3 will show speaker and player from the side,
  • 4 is used for animated cameras,
  • 5 focuses on the player according to this thread. I have never seen this work, though.
  • 6 is used for placeable cameras.

2 or 3 might work well. But you can also try the others.

If that doesn't work, you'll need a new static camera. I'll just refer you to FallenGuardian's tutorial for that.

  • Like 2

Share this post


Link to post
Share on other sites

JC,

I did test my little hack with a number of merchants and it seems to be working fine already the way it is, as surprising as it might be.

I will soon leave for Tatooine and do the same trick with Fazza.

Cheers!

Share this post


Link to post
Share on other sites

Cool! I guess all the prices are set once the store is open for both buy and sell. I wasn't sure they would be because the upgrade system in K2 gets refreshed when you switch between things. But all the better for us.

Share this post


Link to post
Share on other sites

Well, I am at Fazza's and now he buys the wraid plates at a higher price.

The only thing I would like to figure out is if I can hide other items from the "Show Sell Item" window because I feel it'd be interesting if some specific merchants would only buy specific items. In the case of Fazza only wraid plates.

  • 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.