Ok so I’ve been playing around with the TK script gen as well as the in toolset script help and cannot get this to work.
I’m curious if someone can give me a functioning script I can compare to mine and see wth I’m doing wrong.
Basically when a player joins the module, I’d like the script to look for [TEST] in the players name.
If that is present set the variable “test” to 1 otherwise set “test” to 0.
If “test” == 1 grant player 780,000 xp and move them to area testchamber. If “test” != 1 grant them 6000 xp and end script.
This way players can test a build but would not be able to use it to play beyond the test chamber.
Bonus points if there’s a way to make sure the player is moved back to test chamber if rejoining with a test character and that the 6000 xp is not granted every time the player joins.
Better yet would be if there’s a way to have test characters deleted upon leaving the module somehow.
void main()
{
object oPC = GetEnteringObject();
string sPlayerName = GetPlayerName(oPC);
int nIsTestPlayer = 0;
// Check if entering object is a player
if (GetIsPC(oPC)
{
// Check if player's name is "[TEST]"
if (sPlayerName == "[TEST]")
nIsTestPlayer = 1;
// Give 780.000XP to the player named "[TEST]"
if (nIsTestPlayer == 1)
{
GiveXPToCreature(oPC, 780000);
}
// Give 6000XP to the player that is not named "[TEST]"
else
{
GiveXPToCreature(oPC, 6000);
}
}
}
I can’t test it at the moment, thus I’m not sure if it’s gonna work correctly, but try it out.
Adding some more building blocks to that:
You can use FindSubString() to check for the presence of a substring:
if (FindSubString(sName, "[TEST]") != -1)
{
}
One (not necessarily the best for PW development, I suspect but do not know for sure) way to store variables persistently is to store them on the creature skin.
#include "x3_inc_skin"
SetSkinInt(oPC, "BOOPBOOPIAMAROBOT", TRUE);
To jump a character elsewhere, use ClearAllActions() and JumpToLocation or JumpToObject.
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, JumpToObject(GetWaypointByTag("WP_TESTAREA_ENTER")));
To delete characters from the servervault, I think you may need NWNX.
I will expand on this.
There are at least 5 methods without NWNX how to do give something to the player only once (persistently).
-
When its experiences, then the most common method is to check player’s XP. If the XP == 0 then it is new character and so you give him XP you need. However, you should make sure player never drops under 1XP as that would allow him to relog and get the one-time only treatment again.
-
Similarly, you can grant player undroppable system item on his first entry. Player without this item is new character. You need to make sure to never delete this item via scripts.
-
Use vanilla nwn database, functions SetCampaignInt, however database has one issue with characters of same name so if you want to use database, then you need to assign player ID first, which requires method 4).
-
Store variable on undroppable system item. This is similar to the 5), however it is safer. If you would want to use method 3) then you need to have item like this, and store player ID on it. And then use this ID when using Campaign functions.
-
Use skin. However this is unsafe, skin is normally destroyed during OnEnter if the server uses ILR or ELC. Community patch prevents the destructtion of the skin and makes this method safe again however you would need to use NWNX or merge module event scripts to get this functionality. Overally, better not rely on skin unless you are not running ILR and ELC.
With nwnx there are more possibilities, for example I was storing player’s ID as a tag. This allows to avoid having system item in inventory. Another possibility is to reuse some unused player character statistic for this such as BodyBag…
1 Like
@silentrocks
That’s actually very similar to what I’m currently using.
It compiles fine but oddly doesnt fire OnEnter.
I must have it set up wrong somewhere.
But as players wont be named strictly [TEST]
I’ll need something like what
@TheBarbarian mentioned with a substring method.
Also thanks for the other tips regarding having it only fire once.
I’ll have time to look at it more tonight so I’ll try it out.
Appreciate all the great advice guys.
I think you meant OnModuleLoad rather than OnEnter.
OnEnter is what I need.
Now I’m running into more trouble.
I can’t use the script editor in the toolset as for some reason its buggy as hell on linux.
So the script gen is the only way I can create useable .erf files but the generator doesnt have the findsubstring available.
Are there any user friendly .erf unpack/repack programs that work on mint?
void main()
{
//Storing Variables
object oPC = GetEnteringObject();
string sPlayerName = GetName(oPC);
int nTestPlayer = 0;
//Check if entering object is player
if (!GetIsPC(oPC) || GetIsDMPossessed(oPC))
return;
{
//Set Value for nTestPlayer
if (FindSubString(sPlayerName, “TEST”) != -1)
nTestPlayer = 1;
//Decide how much XP to grant Player and where to place them
if (nTestPlayer == 1)
{
// Have the PC perform a sequence of actions.
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionWait(3.5));
AssignCommand(oPC, ActionJumpToObject(GetObjectByTag("tm_builderwp_01")));
//Grant Player 780,000xp
GiveXPToCreature(oPC, 780000);
}
else
{
//Grant Player 6000xp
GiveXPToCreature(oPC, 6000);
}
}
}
This works so far I’ll just have to figure out how to make sure it doesn’t keep firing.
Thanks for all the help guys.
To make sure it only fires once. Use this at the start of the script
object oPC = GetEnteringObject();
if (GetLocalInt(oPC, "DO_ONCE_ON_ENTER")) return;
SetLocalInt(oPC, "DO_ONCE_ON_ENTER", 1);
That won’t work.
As I wrote previously, he needs to use another method because this won’t be persistent if we are talking here about multiplayer module (which wasn’t clarified by OP I believe). There the variable DO_ONCE_ON_ENTER will be again 0 after server is restarted.
Yes you’re right. I just assumed single player.
Yes, sorry about that.
Whichever method I use it would need to be able to be persistent in some fashion.
If u don’t want to add XP on every module entry, I think the easiest workaround would be to check that player’s current XP and skip that GiveXPToCreature
function if that character has less than 780.000XP and add 6000XP to only newly created chars (they should have 0XP by default; I assume that’s what you wanted to achieve).
void main()
{
//Storing Variables
object oPC = GetEnteringObject();
string sPlayerName = GetName(oPC);
int nTestPlayer = 0;
int nCurrentXP = GetXP(oPC);
//Check if entering object is player
if (!GetIsPC(oPC) || GetIsDMPossessed(oPC))
return;
//Set Value for nTestPlayer
if (FindSubString(sPlayerName, “TEST”) != -1)
nTestPlayer = 1;
//Decide how much XP to grant Player and where to place them
if (nTestPlayer == 1 && nCurrentXP < 780000)
{
//Have the PC perform a sequence of actions.
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionWait(3.5));
AssignCommand(oPC, ActionJumpToObject(GetObjectByTag("tm_builderwp_01")));
//Grant Player 780,000xp
GiveXPToCreature(oPC, 780000);
}
else if (nTestPlayer == 0 && nCurrentXP == 0)
{
//Grant Player 6000xp
GiveXPToCreature(oPC, 6000);
}
}
1 Like
if (nTestPlayer == 1 && nCurrentXP > 780000)
Should be nCurrentXP < 780000
.
Ouch, my bad. Fast typing without checking the code Edited my post.
Yup that works well, thanks silentrocks.
That’s it for my on entry for now.
The daunting task of trying to build a forge lies ahead