Aller au contenu

Photo

Random Buried Treasure and Maps


  • Veuillez vous connecter pour répondre
36 réponses à ce sujet

#1
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
 I'm looking for a good system like this. 

I've an idea that requires some knowledge that I don't have: I'm looking to make Useable map items that, once used, will spawn a waypoint to a random location on a random area, and then it would tell the player on which area the waypoint is. Or better yet, if it could be made so that everytime the player uses the map, it will tell you which direction you must walk towards (North, East, South, West... ) to get to that waypoint. 

Once you'd reach the waypoint, (On percieved script?) it would spawn an "X" on the waypoint (There's a nice X placeable) that would only be visible to the player who used this map. Then you could use a shovel to dig the treasure up. I have random treasure system on place already, but now I want this random buried treasure system.

Anyone got any great ideas ?

#2
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
This is not going to be all that difficult to code. Due to varying complications (walkability/reachability of random spots, for one), however, I'd recommend a few tweaks that will drastically reduce dev time for the same net effect:
1) Use preset points, as many as you like, each marked with a waypoint (you could use coordinates with an area, but I'm going for simplicity here).
2) On use of the map, run everything else. If no spot has been picked yet, pick one and store it on the map item as a variable. Then, if the user is not in the destination area, do a floating text on the user telling them the name of the area the treasure is in. Else, if they're not within x meters of the treasure, tell them what direction it's in, with vector math (probably the trickiest bit, converting a float to a string with cardinal/ordinal direction, with a custom function). Else, spawn the treasure and destroy the map item.

Funky

#3
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
That sounds really good, but is there a way to use something like spawning a waypoint that I have now tagged as jer_randomtres_wp, so that this waypoint would be spawned in a -random area- so even I could not tell where it will be spawned ? But like you implied (I think you did... :D), the problem might be if it spawns into unwalkable tiles (water, cliff,) So is there a command to use to spawn it into a valid location that would be a walkable tile?

Also, I'm completely dumb with scripts, I know something works but I don't know why it works...
So what I need is atleast a template script that I can modify to suit my needs.

Here's a numbered list of what I need and wish:

1. I want to make using this map spawn the waypoint at a random area, to a random walkable location in an area. Spawning it on a raised level without a slope isn't a problem, because I'll make climbing gear later. Likewise spawning it on some little islet that is technically walkable but surrounded by unwalkable water won't be a problem because I will put in ways to get there (Swim... boat..)

2. I'm looking to make different quality maps (Authentic / Unauthentic style, so you might just get a chest full of broken bottles... or a chest full of gold.) so it would be a gamble to get a map instead of gold at a dice table :P

3. How can I make placeables like the X only visible to the player who activated the said map, so that other players who activate a map with the same tag would not see this aswell ? Can I maybe use "Once per game" conditional, or will it also apply to other maps with it's tag?(These items will create in your inventory when you get them, from the palette. This affects plenty of things in items too, as I've noticed)

4. A template, because my scripting skill is horrible, I can modify things to a point but I can't make stuff from scratch. So I'll need a skilled superhero make me something like this :P

5. I do think that what you said would be best with how it would run: First it sends you a chatbox message (Name of the area it is in) and when you reach the area, it will tell you in which direction to walk to find it. However, if possible I'd love to have it check some skills like search to successfully determine where it is. I'm not a big fan of not requiring any non-combat skills to be invested in to use cool features. "Wasting power" in favor of RP character build should be heavily rewarded. Always.

#4
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Here I'm wondering should I try to get an Include script done, that lists the areas by tags or resrefs that I want it to spawn the waypoint in ? Perhaps paint a trigger on each area (A trigger that'd be painted over the walkable locations) and would I be then able to command a script to spawn a placeable at random location -on that trigger-. ? :)

#5
Squatting Monk

Squatting Monk
  • Members
  • 444 messages
The way Funky suggested is totally the way to go. You need to just bite the bullet and scatter waypoints throughout the module where you'd like your treasure to spawn. Scripting a system to generate treasure points is far more trouble than it's worth.

Also, making the red X visible only to a particular PC is going to require NWNX. There are basic NWScript workarounds to keep others from sniping treasure from treasure hunters.

Here's a version I whipped up at work. It compiles and seems to work fine, but there may be a bug or two. I would appreciate any advice folks more experienced than me would have.

The gist is this: when a PC uses the map item, it fires a tag-based script that picks a random waypoint tagged "TreasureWP". If it's in a different area, it tells the PC the area it's in. If it's in the same area, it tells the PC the approximate distance and direction (N, NE, E, etc.) in which the treasure lies. If the PC is within five meters of the treasure waypoint, the treasure chest spawns and the map is destroyed.

Treasure is generated when the chest is opened for the first time. Whether it is junk, normal treasure, or ph4t l00t depends on a die roll. Only the PC who found the treasure may open the chest. The chest will despawn three minutes after it is first opened. Until then, more treasure will not be found at this waypoint. Any PCs unlucky enough to have randomly gotten the same treasure waypoint before the chest has despawned will be informed that someone else has already found the treasure and their map will be destroyed.

To use it:

1: Save this script in your module with its script name as "treasuremap".
2: Save this script as "treasurechest".
3: Make your treasure map item, giving it the Unique Power: Self Only item property and setting its tag to "treasuremap".
4: Make the treasure container (you could use a red X or the buried chest) and set its resref to "treasurechest". Make it usable and give it an inventory. Set its OnOpen script to "treasurechest".
5: Make a waypoint template, giving it the tag "TreasureWP". Place an instance of this waypoint anywhere in the module that you'd like treasure to be found.
6: Edit treasurechest.nss to add the item creation code as indicated by the comments.

Modifié par Squatting Monk, 08 août 2013 - 05:08 .


#6
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages

JerrodAmolyan wrote...

That sounds really good, but is there a way to use something like spawning a waypoint that I have now tagged as jer_randomtres_wp, so that this waypoint would be spawned in a -random area- so even I could not tell where it will be spawned ? But like you implied (I think you did... :D), the problem might be if it spawns into unwalkable tiles (water, cliff,) So is there a command to use to spawn it into a valid location that would be a walkable tile?


If there were, I wouldn't have suggested the approach I did. There is actually a GetIsWalkable in nwnx_functions, but there is still no way to tell if there is a way for a pc to arrive at that walkable spot. By far the simplest way to build that fairly complex determination into the system is just to place the waypoints yourself.

Funky

#7
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Thanks for replies guys.

Monk, I'll try this out today, thanks a lot.
Though I might modify it (If I am able) to spawn an X you can talk to and pick "*dig up treasure*" and maybe I can make it perform an animation (I know there's animations like some earth worm tossing around dirt, just need to find it :D) and then spawn the chest on the X. Maybe. If not, this will do until I get my brains working, hehe. :) Thanks alot !

#8
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
I've a question though. Item creation code ? I feel dumb but I don't know what I'm supposed to write :P

#9
Squatting Monk

Squatting Monk
  • Members
  • 444 messages
You could just do CreateObject() if there are a few particular things you wanna make. You could also use a simple treasure generation function like the NWN OC's GenerateTreasure(). Try looking at the stock scripts on containers in the toolset to see how they generate treasure.

#10
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Ah, thanks. But if I want it to pick a few random objects from a "List" I could try to use source chests... right ?

#11
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
You could, but there's no reason to. Just spawn them by resref, and put the resrefs into a random switch. Like so:
string GetRandomResRef() {
    string sRes;
    switch (Random(9)) {
        case 0: sRes = "resref001";
        case 1: sRes = "resref002";
        case 2: sRes = "resref003";
        case 3: sRes = "resref004";
        case 4: sRes = "resref005";
        case 5: sRes = "resref006";
        case 6: sRes = "resref007";
        case 7: sRes = "resref008";
        case 8: sRes = "resref009";
    }
    return sRes;
}

Random yeilds a random number from 0 to (x-1), where x is the number you input. So, if you have 9 item resrefs, you want cases 0-8.

Funky

#12
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Thanks, will try this out :)

#13
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Okay: The map thing doesn't work, everything else seems to. I don't know why, since it looks good to me, but it doesn't do anything. No messages no nothing when you use it. :P

I did make the map "treasuremap" and I have that script saved with the same name.
I have TreasureWP waypoint set on the map aswell. I tried to just put in the chest and it seems the chest itself works. The map just doesn't. *Shoulder shrug*

#14
Squatting Monk

Squatting Monk
  • Members
  • 444 messages
Have you verified that tag-based scripting is turned on in your module?

#15
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Actually: I had tag based scripting derped around... no wonder things have been difficult.

But as it happens, it seems like the map gets destroyed but the chest won't spawn.
Now I really am stumped. heh.

#16
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
*Sigh* Okay, everything works now :D Nothing else is wrong than I won't get any treasure in the chest. Tried to do the source chest thingie, since I cringe at the thought of having to type the resrefs of every item ^^ Oh well... Thanks, this thing works from your part, now I just gotta get it spawn treasure.

(Tried to make it set SourceChest string to a tag of a chest filled with junk, decent or jackpot stuff depending on the dice roll. Not sure why it doesn't work... I guess you can't set and immediately check for a variable :P)

#17
Squatting Monk

Squatting Monk
  • Members
  • 444 messages
You usually can't set and then get variables off of an object during the same script that creates it. That said, show me your code. I'll see what I can do.

Modifié par Squatting Monk, 09 août 2013 - 07:40 .


#18
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
*Got it working* Didn't need variables after all. Just made it pick from the source chests directly and duplicate the randomly picked item to the treasure chest.

#19
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
// Local variable name for the PC who found the treasure.
const string TREASURE_PC = "TreasurePC";

// Local variable name for a flag noting the treasure has been opened.
const string TREASURE_OPENED = "TreasureOpened";

// Delay to destroy treasure container after it is first opened
// Default: 180 seconds (3 IRL minutes).
const float TREASURE_DELAY = 180.0;

void MakeTreasure(string sChest,object oChest)
{
int nCountItems;
int nRandomItem;
object oSource;
object oItem;
string sResRefItem;
oSource = GetObjectByTag(sChest);
if(!GetIsObjectValid(oSource))return;
//count item logic
oItem=GetFirstItemInInventory(oSource);
nCountItems = 0;
while(GetIsObjectValid(oItem)){
nCountItems++;
oItem=GetNextItemInInventory(oSource);
}
//now get random item
nRandomItem=Random(nCountItems)+1;
oItem=GetFirstItemInInventory(oSource);
while(nRandomItem>1){
nRandomItem--;
oItem=GetNextItemInInventory(oSource);
}
sResRefItem = GetResRef(oItem);
CreateItemOnObject(sResRefItem,oChest);
}


void main()
{
// Get the PC opening the treasure and make sure it's the one who found it.
object oPC = GetLastOpenedBy();
object oThisChest = OBJECT_SELF;
string sSourceChest; // Source of Treasure
sSourceChest = GetLocalString(oThisChest,"SourceChest");
if (GetLocalObject(OBJECT_SELF, TREASURE_PC) != oPC)
{
// It's not the same person, send them a message and abort. This is to
// prevent someone from sniping treasure from its rightful owner.
FloatingTextStringOnCreature("This treasure was found by someone else.", oPC, FALSE);
AssignCommand(oPC, ClearAllActions());
return;
}

// If it's the first time this treasure is being opened, spawn some treasure
// and then DelayCommand() the treasure's destruction.
if (!GetLocalInt(OBJECT_SELF, TREASURE_OPENED))
{
// Flag the treasure as having been opened before.
SetLocalInt(OBJECT_SELF, TREASURE_OPENED, TRUE);

// Delay the destruction of the treasure so it won't tie up this
// treasure waypoint indefinitely. We do this before creating the
// treasure in case any custom code added to the treasure generation
// code times us out.
DestroyObject(OBJECT_SELF, TREASURE_DELAY);

// Create treasure on the container. We'll roll a d20 and base the
// quality of the find on the roll.
switch (d20())
{
// On a roll of 1-5, find junk.
case 1: case 2: case 3: case 4: case 5:
{ // Set a local string.

FloatingTextStringOnCreature("Oi! This is ****!", oPC, FALSE);
// Creation code here.
MakeTreasure("jer_src_****treasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_****treasure",oThisChest);
if(d3() > 1 ) MakeTreasure("jer_src_****treasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_****treasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_****treasure",oThisChest);
} break;

// On a roll of 6-19, find decent treasure.
case 6: case 7: case 8: case 9: case 10:
case 11: case 12: case 13: case 14: case 15:
case 16: case 17: case 18: case 19:
{
FloatingTextStringOnCreature("Aye! Not bad!", oPC, FALSE);
// Creation code here.
MakeTreasure("jer_src_decenttreasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_decenttreasure",oThisChest);
if(d3() > 1 ) MakeTreasure("jer_src_decenttreasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_decenttreasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_decenttreasure",oThisChest);

} break;

// On a roll of 20, find ph4t l00t!
case 20:
{
FloatingTextStringOnCreature("Arr! This be a jackpot!", oPC, FALSE);
// Creation code here.
MakeTreasure("jer_src_jackpottreasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_jackpottreasure",oThisChest);
if(d3() > 1 ) MakeTreasure("jer_src_jackpottreasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_jackpottreasure",oThisChest);
if(d2() > 1 ) MakeTreasure("jer_src_jackpottreasure",oThisChest);
} break;
}
}
}

#20
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
That one works now, I just need to fine tune it a bit, I took parts from my random treasure system and merged that with what you gave me.

#21
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages

Squatting Monk wrote...

You usually can't set and then get variables off of an object during the same script that creates it.

Sure you can. Never had an issue with that, and a ton of stuff in our mod wouldn't work without it. Lest ye doubt, here's a test function:

void main()
{
    object oPC = GetLastUsedBy();
    object oItem = CreateItemOnObject("nw_cloth020", oPC);
    int nX, nCheck;
    for (nX = 0; nX < 20; nX++) {
        SetLocalInt(oItem, "Test", nX+1);
        nCheck = GetLocalInt(oItem, "Test");
        SpeakString(IntToString(nCheck) + " = Test var value");
    }
}

Funky

#22
Squatting Monk

Squatting Monk
  • Members
  • 444 messages
Seems I was wrong. Thanks for the correction, Funky. :)

#23
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
Ok, I have it working mostly like I want it to, Only problem I have now are stackable items (Misc item coins, potions, arrows) that have a stack set as something. I know it can be done so that it will create the stack of item it picks (For example I have different versions of same coin with different stack size) instead of picking 1 item from the stack... What should I add to that script so it will grab the whole stack if the random roll hits that item ?

#24
meaglyn

meaglyn
  • Members
  • 807 messages
The Lexicon is a good source of info. See the entry for CreateItemOnObject.

Something like this would probably do it:

int nStack = GetItemStackSize(oItem);
sResRefItem = GetResRef(oItem);
CreateItemOnObject(sResRefItem,oChest, nStack);

Or collapse it a bit:
CreateItemOnObject(sResRefItem,oChest, GetItemStackSize(oItem));

#25
JerrodAmolyan

JerrodAmolyan
  • Members
  • 89 messages
That looks good otherwise, but I'm using source chests so I don't have to write up all the resrefs, will it work with those too ?