Script Weird Insanity
Hawkwinter
Member Posts: 14
So, I'm trying to set up a fairly basic "On Enter" script. It should strip out everything the player is carrying, give them 3000gp, 10 potions, a torch, a set of commoner's clothes, and then set their level to 3.
I'm getting all kinds of weirdness though, and it's proving very difficult to debug. From what's showing up in the console, commands are often being run out of order, and it throws errors when I start trying to add "DelayCommand" instructions to some of the functions I'm calling.
Frequently, it would give the gold before removing the gold they walked in with, and then remove everything. I'm not new to programming (but I am somewhat rusty), and it's been like 15 years since I've touched NWScript, but I can't understand why I'm getting all of this weirdness.
What could be causing this weirdness?
{Edit: After a bunch of fiddling around I have made partial progress. But still. It's only creating 3 potions, not 10 (tried it as 1 command and as a for loop), and it's not running "CraftSupplies(oPC);", even though that function works fine when I call it on a rest.}
I'm getting all kinds of weirdness though, and it's proving very difficult to debug. From what's showing up in the console, commands are often being run out of order, and it throws errors when I start trying to add "DelayCommand" instructions to some of the functions I'm calling.
Frequently, it would give the gold before removing the gold they walked in with, and then remove everything. I'm not new to programming (but I am somewhat rusty), and it's been like 15 years since I've touched NWScript, but I can't understand why I'm getting all of this weirdness.
What could be causing this weirdness?
{Edit: After a bunch of fiddling around I have made partial progress. But still. It's only creating 3 potions, not 10 (tried it as 1 command and as a for loop), and it's not running "CraftSupplies(oPC);", even though that function works fine when I call it on a rest.}
//:://///////////////////////////////////////////// //:: Default On Enter for Module //:: x3_mod_def_enter //:: Copyright (c) 2008 Bioware Corp. //::////////////////////////////////////////////// /* This script adds the horse menus to the PCs. */ //::////////////////////////////////////////////// //:: Created By: Deva B. Winblood //:: Created On: Dec 30th, 2007 //:: Last Update: April 21th, 2008 //:: Updated By: Valas //:: First Updated: 2019-04-27 //:: Last Update: 2019-04-27 //::////////////////////////////////////////////// #include "x3_inc_horse" #include "1x_craftsupplies" int BaseGear(object oPC){ /****************************** * This script clears the inventory of the entering player character. * It is suitable for use in an OnEnter or OnClientEnter event. *******************************/ int nSlot, nCount, nVentory = 0; // Make sure oPC is a PC (not necessary in a module's OnClientEnter). if ( !GetIsPC(oPC) ) return 0; // Destroy the items in the main inventory. object oItem = GetFirstItemInInventory(oPC); while ( oItem != OBJECT_INVALID ) { nVentory = 1; DestroyObject(oItem); oItem = GetNextItemInInventory(oPC); } // Destroy equipped items. for ( nSlot = 0; nSlot < NUM_INVENTORY_SLOTS; ++nSlot ){ DestroyObject(GetItemInSlot(nSlot, oPC)); } // Remove all gold. AssignCommand(oPC, TakeGoldFromCreature(GetGold(oPC), oPC, TRUE)); //Give 3000 Gold to Spend. DelayCommand(4.0, GiveGoldToCreature(oPC, 3000)); object oCloth = CreateItemOnObject("nw_cloth022", oPC, 1); DelayCommand(0.5, AssignCommand(oPC, ActionEquipItem(oCloth, INVENTORY_SLOT_CHEST))); //Give 3 healing potions, a torch, and some rags. CreateItemOnObject("nw_it_torch001", oPC, 1); //DelayCommand(0.2, AssignCommand(oPC, ActionSpeakString("Torch"))); for (nCount = 0; nCount < 10; ++nCount) { CreateItemOnObject("nw_it_mpotion001", oPC, 1); } //DelayCommand(0.2, AssignCommand(oPC, ActionSpeakString("10 Healing Potions"))); CraftSupplies(oPC); return 1; } void main() { object oPC=GetEnteringObject(); ExecuteScript("x3_mod_pre_enter",OBJECT_SELF); // Override for other skin systems if ((GetIsPC(oPC)||GetIsDM(oPC))&&!GetHasFeat(FEAT_HORSE_MENU,oPC)) { // add horse menu HorseAddHorseMenu(oPC); if (GetLocalInt(GetModule(),"X3_ENABLE_MOUNT_DB")) { // restore PC horse status from database DelayCommand(2.0,HorseReloadFromDatabase(oPC,X3_HORSE_DATABASE)); } // restore PC horse status from database } // add horse menu if (GetIsPC(oPC)) { // more details // restore appearance in case you export your character in mounted form, etc. if (!GetSkinInt(oPC,"bX3_IS_MOUNTED")) HorseIfNotDefaultAppearanceChange(oPC); // pre-cache horse animations for player as attaching a tail to the model HorsePreloadAnimations(oPC); DelayCommand(3.0,HorseRestoreHenchmenLocations(oPC)); // Strip PC Gear BaseGear(oPC); //Raise Level to 3 int nGoalXP = 5 * (5 - 1) * 500; //SetXP(oPC, 0); SetXP(oPC, nGoalXP); } // more details }
Post edited by Hawkwinter on
0
Comments
You can also change
into
Also you can use To guarentee that
will work
I don't whats in your CraftSupplies(oPC);
since its implemented in the include.
You also may want to avoid init characters if they're DM or DM possessed creatures...
>"TakeGold from EnterArea or Module events will fail, use AssignCommand(object, action) in that case."
Isn't that what I'm already doing? I'm confused.
"AssignCommand(oPC, TakeGoldFromCreature(GetGold(oPC), oPC, TRUE));"
>"CreateItemOnObject("nw_it_mpotion001", oPC, 10);"
That's what I had first. It doesn't work. The loop doesn't work. Both give you 3 potions and then stop.
>I don't whats in your CraftSupplies(oPC);
Right. fair.
Checks if you have the crafting feats, and whichever ones you have, it should give you a blank crafting item for it if you don't have any. The idea being that then people won't be dependent on the module having proper support of it for their crafting feats to work (modules which I am not making - we're probably gonna start with SOU, do a bridging module, then play HOTU, we may grab others to play online after that, and my plan once I have it ironed out is to toss the other scripts in my override and then make sure I'm the one to host, but I will check the modules to see if I need to do any additional tweaking to them on top of that just in case. As for this character builder module, I'll use it to make sure everyone is on the same level for gear before we start playing, but I'm also using it to test my override scripts.
>You also may want to avoid init characters if they're DM or DM possessed creatures...
If I ever go to publish it I will keep that in mind (or if the check for it is simple I'll throw it in), but it won't come up in our usecase, it's just gonna be a co-op romp against the AI in a premade adventure.
As to the potions. It's creating 10. The first 7 are getting added to the stack of 3 that's already there and marked for delete. Then the three that go over the stack size make a new item with stack size 3. Objects are not actually deleted in scripts until the script ends. You can fix that by delaying the potion creation. Better might be to split your basegear() into two functions. One to remove stuff, which you can just call. And then another to give the new stuff. You can then delay that call a bit.
As to the level... you are saying you want level 3 but explicitly setting to level 5.
For the crafting items, make sure the resref is correct. The GetItemPossessedBy takes a tag. The createItem call takes a resref. They are not guaranteed to be the same.
>Objects are not actually deleted in scripts until the script ends.
Thats the part that was screwing me up. And I had no idea. I thought object targeted for deletion was deleted before running the next command in the script. What if I put the delete in a separate script and then run an executescript from inside the 'onenter'?
>And then another to give the new stuff. You can then delay that call a bit.
Can you explain why I would need to delay it? Shouldn't it be executing the commands in order?
>As to the level... you are saying you want level 3 but explicitly setting to level 5.
3 is the final target, but 5 allows me to easily test it with a wizard with all three crafting feats - whose script I've also been tweaking. That part works great,
>avoid deleting the skin item since you just went through the trouble of adding the horse menu to it. You can just skip that slot in the loop.
Fair enough. I'll figure out what slot that is and then add an exception to skip it.
>For the crafting items, make sure the resref is correct. The GetItemPossessedBy takes a tag. The createItem call takes a resref. They are not guaranteed to be the same.
I'll doublecheck those. They work reliably when I execute that function from onRest, but often not from onEnter. Probably because the weirdness of commands executing out of order you have been describing.
Is there documentation on these commands happening out of order so I can avoid future issues like this coming up again?
DelayCommand would allow the script to end before the delayed commands run. That way the potions would be deleted before you did the creation of the new ones. DelayCommand can be a function. So DelayCommand(0.1, createStartingItems(oPC)); would work. That will run after the onenter script finishes and thus the potions will be gone.
You know about the lexicon right?
If the crafting script works on rest then the resrefs are not the issue. You might try delaying that call too and see what it does. Not sure why that isn't working unless the PC is not fully formed because this is module enter. In PWs people often run this sort of code in the on area enter script of the default starting location (or a trigger painter around such location) so that the PC is sure to be fully functional.
Anyway, keep at it. There are some quirks but it's not madness
Edit: "often" is often spelled "often" not "of".
>DelayCommand(0.1, createStartingItems(oPC)); would work.
Then that's how I'll do it.
>In PWs people of run this sort of code in the on area enter script of the default starting location (or a trigger painter around such location) so that the PC is sure to be fully functional.
Hmm. This particular script isn't going to be an override to use with other modules, it'll be fired from a character building module that's a single room, so that could work too. I'll play around with it and see where I get.
>DelayCommand would allow the script to end before the delayed commands run.
>DelayCommand is not a delay before executing the next instruction, still in orde, it pulls the command out of sequence to be executed after the script finishes
I really need to read the lexicon more closely.
Thanks!