Persistent Var Storage on PC item question
Dreadlord_Anwyn
Member Posts: 48
So, Im trying to make this script by scratch
It seems logical if you just go, "SetLocalInt" on the token object, it might not know which one, given the same resref is carried on every character. Does this function automatically choose the speaker of the conversation/user of the item/nearest PC? It would make sense that it does not, thats what GetPC type commands are for.
So, I looked up SetLocalObject and both that page and GetLocal Object on the Lexicon tell me there is an issue with resets and not to use them for this. But it doesnt point me to what I should use instead.
So, Im writing this here script, but there is an issue with the line " !GetIsObjectValid(oObject);" so Im assuming I either did syntax wrong or you cant use that command that way.
The point of why Im doing that loop check in there is to look for the object ~ta_fatetoken~ in the speaking/using PC's inventory because as I mentioned before, I dont see how SetLocalInt is going to discriminate and the Lexicon told me no no no about SetLocalObject. https://nwnlexicon.com/index.php/GetLocalObject
Anyone willing to help?
Heres what I wrote. I script badly when Im in unfamiliar territory
//// ta_bindloc
// Binds the character to a new location, so they respawn here
// after leaving limbo and after server resets
// set a local string on the fate token called BINDLOC
// BINDLOC should have a default waypoint tag near the start point of your mod
// This script changes that string every time it is used
// set a local string on the creature or placable called BINDPOINT
// This should be set to the ResRef of the new waypoint to respawn at
void main()
{
string sVarName = "BINDLOC";
string sValue = "BINDPOINT";
string oObject = "ta_fatetoken";
object oItem = GetFirstItemInInventory(GetFirstPC());
while (GetIsObjectValid(oItem))
{
!GetIsObjectValid(oObject);
oItem = GetNextItemInInventory(GetFirstPC());
}
SetLocalString(oObject, sVarName, sValue);
}
It seems logical if you just go, "SetLocalInt" on the token object, it might not know which one, given the same resref is carried on every character. Does this function automatically choose the speaker of the conversation/user of the item/nearest PC? It would make sense that it does not, thats what GetPC type commands are for.
So, I looked up SetLocalObject and both that page and GetLocal Object on the Lexicon tell me there is an issue with resets and not to use them for this. But it doesnt point me to what I should use instead.
So, Im writing this here script, but there is an issue with the line " !GetIsObjectValid(oObject);" so Im assuming I either did syntax wrong or you cant use that command that way.
The point of why Im doing that loop check in there is to look for the object ~ta_fatetoken~ in the speaking/using PC's inventory because as I mentioned before, I dont see how SetLocalInt is going to discriminate and the Lexicon told me no no no about SetLocalObject. https://nwnlexicon.com/index.php/GetLocalObject
Anyone willing to help?
Heres what I wrote. I script badly when Im in unfamiliar territory
//// ta_bindloc
// Binds the character to a new location, so they respawn here
// after leaving limbo and after server resets
// set a local string on the fate token called BINDLOC
// BINDLOC should have a default waypoint tag near the start point of your mod
// This script changes that string every time it is used
// set a local string on the creature or placable called BINDPOINT
// This should be set to the ResRef of the new waypoint to respawn at
void main()
{
string sVarName = "BINDLOC";
string sValue = "BINDPOINT";
string oObject = "ta_fatetoken";
object oItem = GetFirstItemInInventory(GetFirstPC());
while (GetIsObjectValid(oItem))
{
!GetIsObjectValid(oObject);
oItem = GetNextItemInInventory(GetFirstPC());
}
SetLocalString(oObject, sVarName, sValue);
}
0
Comments
So, I went to my waypoints and got the tag of the one next to the mod start
Then I gave my Fate Token three starting Variables:
BIND (string) ~waypoint tag~
NEWB (int) 1
DEAD (int) 0
Im guessing I need to set a string on the stone with the PCs name?
So should I add
NAME (string) 0
and then update that?
And then reference from there on? It would then look for NEWB at that first handout conv and then assign the fate token the character's name string to NAME, and set NEWB to 0.
void main()
{
object oTarget = GetPCSpeaker();
string sItemTemplate = "ta_fatetoken"; // pc persistance token
CreateItemOnObject(sItemTemplate, oTarget);
GiveGoldToCreature(oTarget, 300);
string sTag = "ta_fatetoken";
object oObject = GetObjectByTag(sTag);
string sVarName2 = "CharName";
string sValue2 = GetPCPlayerName(oTarget);
SetLocalString(oObject, sVarName2, sValue2);
string sVarName3 = "PlayrCDKey";
string sValue3 = GetPCPublicCDKey(oTarget);
SetLocalString(oObject, sVarName3, sValue3);
string sVarName4 = "PCIPAdd";
string sValue4 = GetPCIPAddress(oTarget);
SetLocalString(oObject, sVarName4, sValue4);
}
I use oPC generally in scripts that only reference a PC. You'll want to use the waypoint's tag, rather than resref.
//// ta_bindloc (version 1) // Binds the character to the location of a waypoint, so they respawn here // after leaving limbo and after server resets. // // Checks for Fate Token. If not found, creates it, gives starting gold, and sets // initial variables on the token. // // Created by: The Amethyst Dragon // Created on: 2018 January 19 void main() { object oPC = GetPCSpeaker(); // Used in conversation if (oPC == OBJECT_INVALID) // Used if called by placeable activation instead (script set on trigger) { oPC = GetLastUsedBy(); } if (oPC == OBJECT_INVALID) // Used if called by item activation instead (item activation script) { oPC = GetItemActivator(); } if (oPC == OBJECT_INVALID) // Used if called by PC entering a trigger (script set on trigger) { oPC = GetEnteringObject(); } if (GetIsPC(oPC) != TRUE) // If what calls the script isn't a PC, stop the script { return; } object oFateToken = GetItemPossessedBy(oPC, "ta_fatetoken"); // Check for exising token if (oFateToken == OBJECT_INVALID) // If no token... { oFateToken = CreateItemOnObject("ta_fatetoken", oPC); // ...create a token... GiveGoldToCreature(oPC, 300); // ...give starting gold... SetLocalString(oFateToken, "BINDLOC", "BINDPOINT"); // ...set variable on token... SetLocalString(oFateToken, "CharName", GetPCPlayerName(oPC)); // ...set variable on token... SetLocalString(oFateToken, "PlayrCDKey", GetPCPublicCDKey(oPC)); // ...set variable on token... SetLocalString(oFateToken, "PCIPAdd", GetPCIPAddress(oPC)); // ...set variable on token } }
For your last variable (player IP address)... If you're using this a part of a scripted account security thing, it might not be a good idea. People's IP addresses can and do change, and even if they don't, this would prevent them from logging into their own characters from somewhere else.
Oh, and make sure your Fate Token item is set to plot, non-droppable so PCs can't lose it or sell it.
Each valid binding waypoint should have a unique tag (otherwise your PC will always end up at the same spot). In this version of the script, you'd be looking for waypoints with tags that all start with "BINDPOINT_".
//// ta_bindloc (version 2) // Binds the character to the location of a waypoint, so they respawn here // after leaving limbo and after server resets. // // Checks for Fate Token. If not found, creates it, gives starting gold, and sets // initial variables on the token. // // Checks radius (currently 20 meters) for waypoint that has a TAG that starts // with "BINDPOINT_". If found, sets that as the bind point location. // // Created by: The Amethyst Dragon // Created on: 2018 January 19 void main() { object oPC = GetPCSpeaker(); // Used in conversation if (oPC == OBJECT_INVALID) // Used if called by placeable activation instead (script set on trigger) { oPC = GetLastUsedBy(); } if (oPC == OBJECT_INVALID) // Used if called by item activation instead (item activation script) { oPC = GetItemActivator(); } if (oPC == OBJECT_INVALID) // Used if called by PC entering a trigger (script set on trigger) { oPC = GetEnteringObject(); } if (GetIsPC(oPC) != TRUE) // If what calls the script isn't a PC, stop the script { return; } object oFateToken = GetItemPossessedBy(oPC, "ta_fatetoken"); // Check for exising token if (oFateToken == OBJECT_INVALID) // If no token... { oFateToken = CreateItemOnObject("ta_fatetoken", oPC); // ...create a token... GiveGoldToCreature(oPC, 300); // ...give starting gold... SetLocalString(oFateToken, "CharName", GetPCPlayerName(oPC)); // ...set variable on token... SetLocalString(oFateToken, "PlayrCDKey", GetPCPublicCDKey(oPC)); // ...set variable on token... SetLocalString(oFateToken, "PCIPAdd", GetPCIPAddress(oPC)); // ...set variable on token } string sBindWP_Prefix = "BINDPOINT_"; // Check 20 meter radius for waypoint with tag that starts with this prefix string sBindWP_Tag; location lPC = GetLocation(oPC); object oBindWP = GetFirstObjectInShape(SHAPE_SPHERE, 20.0, lPC, FALSE, OBJECT_TYPE_WAYPOINT); while (oBindWP != OBJECT_INVALID) { sBindWP_Tag = GetTag(oBindWP); if (GetStringLeft(sBindWP_Tag, 10) == sBindWP_Prefix) { SetLocalString(oFateToken, "BINDLOC", sBindWP_Tag); // Set new bind point only if there was a valid binding waypoint within the radius return; } oBindWP = GetNextObjectInShape(SHAPE_SPHERE, 20.0, lPC, FALSE, OBJECT_TYPE_WAYPOINT); } }
I was basically just grabbing the IP information as part of general data. Like, in case later down the line with NWNX or something you needed to use that information. But its a useful reminder, so thanks.
Your scripts are better than mine, so Im going to use them instead. But Im proud of myself anyway, Im more of an art nerd than a computer nerd and I did that at 4-5 am.
--edit--
Well, at least I'll deconstruct them and re-construct them. The tokens already have the first bind set as a variable and they set the second bind as a variable (the ResRef and tags of my custom items are the same, due to the thing with custom items using ResRefs and default items using Tags). And my current script changes the Tag/ResRef value right before teleporting them. So, unless the server crashes -right then- (?)
Here's the script as before I went to sleep again:
//ta_griefpassed
//on conversation script for the NPC Mister Grief
//after a short quiz on disruptive gameplay, this is on Actions Taken
//by Dreadlord_Anwyn
void main()
{
object oTarget = GetPCSpeaker();
string sItemTemplate = "ta_fatetoken"; // pc persistance token
CreateItemOnObject(sItemTemplate, oTarget);
GiveGoldToCreature(oTarget, 300);
string sTag1 = "ta_fatetoken";
object oObject1 = GetObjectByTag(sTag1);
string sVarName2 = "CharName";
string sValue2 = GetPCPlayerName(oTarget);
SetLocalString(oObject1, sVarName2, sValue2);
string sVarName3 = "PlayrCDKey";
string sValue3 = GetPCPublicCDKey(oTarget);
SetLocalString(oObject1, sVarName3, sValue3);
string sVarName4 = "PCIPAdd";
string sValue4 = GetPCIPAddress(oTarget);
SetLocalString(oObject1, sVarName4, sValue4);
string sTag2 = "WP_TAbind002";
object oObject2 = GetObjectByTag(sTag2);
location lLocation = GetLocation(oObject2);
AssignCommand(oTarget, ActionJumpToLocation(lLocation)); //there is no returning to this room MUA HA HAAAAA
//the module start is in a room with two signs, no exit, and Mister Grief
//the character starts stripped of inventory
//the teleport waypoint and the WP for the bind location change from default are the same
}
But, like I said, your script is still better - because of the oPC as an object and the tagbased script advice.
Thanks again!
I started with what you posted, then just tried to streamline it and make it easier to read.
I've been using NWScript for years now, so I generally know how to make it do what I want. Given time and practice, yours can look polished as well. I taught myself, starting with Lilac Soul's Script Generator and looking at other people's scripts.
I tried to put in useful comments so you can see which parts of the code do what. It's also handy to pull someone else's script into the script editor in the toolset so you can double click on a function to get a description for it in the bottom of the window.
Feel free to keep asking questions around here or the forums at the Vault. It may not always be right away, but there are one or more people out there with the answers (or can help you find them).
My primary scripting experience was prior to NWN2 with neverwinterconnections, and I would often make little adventures and get a party and DM the module for them. I would mostly Lilac Soul stuff at that point.
Then, when NWN2 came out I got enlisted by this PW called Knights of Winterhaven. At that point I started to learn to do stuff by scratch. I made some scripts Im still proud of, like a trap script that mimicked 3.5 more closely, using a function to switch static items to usable so that you wouldnt see a "red square" but instead, you would get floating text and then you would have to find a trap box and disarm it. It was a bit more like DDO was. I also made a wandering monster script using the same kind of SetObjectActive or whatever the command is so youd enter a trigger and it would rand /case which encounter to set active and spawn.
Right now Im working on a treasure table that uses an inaccessible invisible hidden chest, floattoint, and variables to generate loot drops and container loot, also the aforementioned wandering monster type idea to make random locations for bosses and the best treasure containers of an area.
Here's my PW (work in progress) entry on the vault if you wanna take a peek:
https://neverwintervault.org/project/nwn1/module/gameworld/time-atlantis
Oh and I reverse-engineered your scripting up there since I have both bindpoints and origin points.
Like, origin points is for resets: starter, mid-starter, player lobby, limbo(dead PC)
And bind points is for porting there from player lobby or death respawns, etc.
I of course, left your credits in there. So anyone who looks at them will see them haha.