Problem with unique random treasure

Hi. I’m trying to implement the random treasure system from (I believe) SoU in my module: where you have base treasure chests for low, medium, high and unique treasure and when the PC opens/destroys a chest it picks random loot from the corresponding base chest, using the script x0_i0_treasure.

It all works fine except for the “unique” chest. It’s supposed to pick one item from the unique level base chest at random, copy it into the chest the PC is opening and delete the original item (so it will never be picked again). But when I test it, it doesn’t generate anything at all.

I’ve found one other mention of this problem online: x0_o2_anyuniq Error — Beamdog Forums

Unfortunately, ForSerious’s suggestion here hasn’t worked for me, the chests are still empty. I’ve double checked all the other obvious causes too, tags being wrong etc.

Has anyone else encountered this problem? Can anyone help?

Pr0tip: avoid using OC and SoU systems. Go with their HotU counterparts if possible. Or even better: avoid inbox BW libraries at all. They are meant to help sell the game Neverwinter Nights and its expansions. The fact they can be wrought to somehow work with custom modules is a byproduct, not a design feature. If you do insist on using them for production rather than inspiration, be prepared for a lot of grief.

You should post your script so we can see what you have already. It’s hard to guess.

But given the above, have you tried replicating that functionality with custom script? All you need is to get the (nearest?) source chest by tag and pick X random items from it. Scan its inventory to get their total count (n), then CopyItem() item pointed to by Random(n) X times. Then delete all instances of those items from the chest (read: in case the random variable is not uniform). Then mark the target chest as “done”. Extra care might be needed around stacks, but everything should be otherwise doable in much less lines of code than those in x0_i0_treasure.

Alternatively look around the Vault for complete solution. Search for “chest treasure”.

2 Likes

Thanks for your help. I didn’t realise the official resources were generally hard to implement in custom modules.

My understanding of scripting is basically non-existent (I use Lilac Soul’s for everything) so I won’t be able to replicate it myself, but I’ve managed to find a good script on these forums that does it by way of random numbers stuck on the end of a string that’s shared by all the item resrefs.

Thanks again!

Yes, they are tailored to work in specific context of given game, are usually inflexible (especially below HotU, SoU is closer to OC in this regard) and sometimes do something else than advertised (example), which is fine for the source expansion, but may not translate well into custom modules.

Anyway, this would be a good scripting experience. But since you’ve found a ready solution, you may want to link to it here so readers of your thread can also try that.

You’re right, I should!

Here’s the random treasure script I’ve ended up with, for anyone in search of such a thing:

void main()
{

object oPC = GetLastOpenedBy();

if (!GetIsPC(oPC)) return;

int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF));

if (DoOnce==TRUE) return;

SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);



{
int nItemNum = Random (30) + 1;

{
string sItem = ("randomitem_" + IntToString(nItemNum));
CreateItemOnObject(sItem, OBJECT_SELF, 1);
}
}
}

I tinkered with a script taken from this thread.

To use my version:

  • make the 30 items you want to pop up randomly, and make each one has the resref: randomitem_ followed by a number from 1 to 30.
  • put the script in the OnOpen of any container you want to contain random item.
  • if you want some number of items other than 30, change the number in the brackets in this line: int nItemNum = Random (30) + 1; Just make sure you have the right number of items with the correct number sequence for their resrefs.

I’m sure it’s not very elegant or efficient, since I had to use Lilac Soul to make the script only run once (so the chests don’t create a new random item every time the player opens them) and bodge it together into a weird Frankenstein’s monster.

Also, the player might well get the same item more than once in a playthrough as I don’t know how to prevent this. And it only works when the container is opened, not when it’s destroyed. Aside from these issues, it’s good enough for my purposes. I leave it to other more knowledgeable builders to tinker with further if you please.

1 Like

Haven’t tried your script but here it is tidied up and indented properly -

void main()
{
    object oPC = GetLastOpenedBy();

    if(GetIsPC(oPC))
    {
        int DoOnce = GetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF));

        if(! DoOnce)
        {
            SetLocalInt(OBJECT_SELF,  GetTag(OBJECT_SELF), TRUE);

            int nItemNum = Random (30) + 1;

            string sItem = ("randomitem_" + IntToString(nItemNum));
            CreateItemOnObject(sItem, OBJECT_SELF, 1);
        }
    }
}

To be honest, I haven’t even examined the logic of it, just tidied it up.

TR

1 Like

The easiest way to do this is to change the way how you do this to this:

  1. create a chest in unreachable area or position. Give it certain tag.
  2. fill it with items you want to drop thorough your module.
  3. in the random loot script, get the chest by that certain tag, loop all items to determine count, then select random number of that count and copy nTh item to placeable player opened or his inventory, and then DestroyObject the original item in that chest.

That way you wouldn’t even need to give the items specific tag as you did.

@Tarot_Redhand Thanks! I have no idea what I’m doing when it comes to scripting.

@Shadooow Yeah that’s how the SoU system does it, but it doesn’t work in my module for some reason. Again, no idea about scripting so I’m not able to implement my own version of it.