Aller au contenu

Photo

NWNX2 Issue


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

#1
Demkey

Demkey
  • Members
  • 18 messages

I implemented the NWNX2 scripting to a new module that I've been putting together and it has addressed the issues I had with making it a PW module. However, after testing I've discovered that the OnAquire scripts that I created (i.e. aq_xxxxxxx) are no longer working.

 

Can someone shed some light as to why this is happening, and hopefully how to fix it? I have a total of about 3 dozen aq_xxxxxx files that are currently affected.



#2
BelowTheBelt

BelowTheBelt
  • Members
  • 394 messages
What errors are you getting? Have you tried debugging to see where the issue is (I.e to make sure it is firing and that all data is being captured)? Are those scripts using any of the nwnx functions?

I presume those were working before you installed nwnx? What plugins are you running?

#3
Demkey

Demkey
  • Members
  • 18 messages

I’m not getting any in-game errors being broadcast, nor am I seeing any errors in the server log. They simply aren’t doing their job.

 

Very briefly, every encounter has a Soul Stone in its inventory, when the player loots that Soul Stone the scripts do three basic things, give out bonus XP/Gold, they run a random item creator that places an item in the players inventory, then the script deletes the Soul Stone.  And yes the scripts were running fine just prior to installing NWNX2. They were created prior to me even discovering that NWNX2 was out there, so if there is any special NWNX2 OnAquire functions, then no I'm not using them.

 

All I’m running is the Core NWNX2 program with the ODBC add-on.



#4
Baaleos

Baaleos
  • Members
  • 1 329 messages
NWNX2.exe itself doesn't directly affect any onAcquire scripts - to knowledge.

Have you tried placing a line such as

AssignCommand(GetModuleItemAcquiredBy(),SpeakString("I have acquired an item"));

in your onAcquire script, to verify if the script is firing.
Try placing the message/debug statement at various points within your script to identify the location the script fails/breaks etc.
Also remember to recompile the script before re-testing. Sometimes saving the module isn't enough, an actual compile / build scripts solves problems like this.

#5
Demkey

Demkey
  • Members
  • 18 messages

The very first thing the script does is to give XP & gold to the party, and that's not happening, so it seems to be failing right away. Here is what the beginning of the script does. I'm only including the beginning of it since it's a somewhat lengthy script.

 

#include "nw_i0_tool"
void main()
{

object oPC = GetModuleItemAcquiredBy();
int nStackSize = 50;
object oItem;
oItem = GetModuleItemAcquired();
if (!GetIsPC(oPC)) return;
RewardPartyXP(50, oPC, TRUE);
RewardPartyGP(80, oPC, TRUE);

.....script continues

 

I did do a rebuild on the module after I added NWNX2.



#6
Baaleos

Baaleos
  • Members
  • 1 329 messages
The only thing I can think of is that for some reason oPC is not coming back as true in the GetIsPC check.
Have you tried debug statements before that if statement?

NWNX shouldnt be overriding any scripts unless you have nwnx_resman in use - and even then, it will only override if it detects an external version of that script to replace it with.

#7
Demkey

Demkey
  • Members
  • 18 messages

No I haven't tried any debugging. I'm not a programmer/scripter so I'm not sure how to go about doing that. My only experience with scripting is using Lilac. Is there a short piece of coding I can insert in it to do that?



#8
Baaleos

Baaleos
  • Members
  • 1 329 messages
Place this line

AssignCommand(GetModuleItemAcquiredBy(),SpeakString("I have acquired an item"));

above the line that reads

if (!GetIsPC(oPC)) return;


When you pick up an item, if you speak "I have acquired an item" then we know your script is firing, but for some reason its not getting past the if statement.

#9
Demkey

Demkey
  • Members
  • 18 messages

It didn't come back and say "I have acquired an item". So that means the script isn't firing off at all???



#10
Baaleos

Baaleos
  • Members
  • 1 329 messages
It would suggest that it isnt.
The script is definitely attached to the modules onAcquire event?

And also - are any haks being used?

#11
Demkey

Demkey
  • Members
  • 18 messages

According to Lilac I have to use the below coding and name the script the same as the Resref of the object that I'm placing in the encounter's inventory as the drop (which would be soulstone50). Then I'm suppose to create a second file that contains the above script with the same name but with a leading aq_ so it would be aq_soulstone50. Like I mentioned earlier the script was running fine up until yesterday when I installed NWNX2.

 

Here is what I have in the soulstone50 file:

 

#include "x2_inc_switches"
void main()
{
int nEvent =GetUserDefinedItemEventNumber();
switch (nEvent)
   {
   case X2_ITEM_EVENT_ACTIVATE:
ExecuteScript("ac_"+GetTag(GetItemActivated()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_EQUIP:
ExecuteScript("eq_"+GetTag(GetPCItemLastEquipped()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_UNEQUIP:
ExecuteScript("ue_"+GetTag(GetPCItemLastUnequipped())
, OBJECT_SELF); break;
   case X2_ITEM_EVENT_ACQUIRE:
ExecuteScript("aq_"+GetTag(GetModuleItemAcquired()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_UNACQUIRE:
ExecuteScript("ua_"+GetTag(GetModuleItemLost()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_SPELLCAST_AT:
ExecuteScript("sp_"+GetTag(GetModuleItemLost()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_ONHITCAST:
ExecuteScript("on_"+GetTag(GetSpellCastItem()),
OBJECT_SELF); break;
   }
}



#12
Baaleos

Baaleos
  • Members
  • 1 329 messages
Am I correct in assuming that you have this script running from the UserDefined event on the module?

If thats the case then you should be naming your script the same as whatever the tag of the item is, and not the resref.

You are using gettag in the above switch statement, which means you should put aq_soulstone50 as your tag name for the soul stone.

The above script would need to be in the user defined script event I believe.

#13
Demkey

Demkey
  • Members
  • 18 messages

I made the tag name and ResRef the same on these soul stones.



#14
BelowTheBelt

BelowTheBelt
  • Members
  • 394 messages

From the Lexicon,  GetModuleItemAcquired returns the item from an OnAcquiredItem event.  If this script is run from a User Defined event, would that run into issues?  Or, is the UD Acquire still considered an OnAcquired event?

 

To expand on debuggings, update your scripts with the following some debug code:

void main()
{
SendMessageToPC(GetFirstPC(), "DEBUG:  User Defined script Firing.");

int nEvent =GetUserDefinedItemEventNumber();
SendMessageToPC(GetFirstPC(), "DEBUG:  User Defined Event = "+IntToString(nEvent));

switch (nEvent)
   {
   case X2_ITEM_EVENT_ACTIVATE:
ExecuteScript("ac_"+GetTag(GetItemActivated()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_EQUIP:
ExecuteScript("eq_"+GetTag(GetPCItemLastEquipped()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_UNEQUIP:
ExecuteScript("ue_"+GetTag(GetPCItemLastUnequipped())
, OBJECT_SELF); break;

case X2_ITEM_EVENT_ACQUIRE:

{
SendMessageToPC(GetFirstPC(), "DEBUG:  Acquire event firing.  Item tag= "+GetTag(GetModuleItemAcquired()));

ExecuteScript("aq_"+GetTag(GetModuleItemAcquired()),
OBJECT_SELF);

}

break;

...rest of your script...

 

 

In your first script, 

void main()
{

SendMessageToPC(oPC, "DEBUG:  Script Firing.");

object oPC = GetModuleItemAcquiredBy();

SendMessageToPC(GetFirstPC(), "DEBUG:  oPC = "+GetName(oPC));

int nStackSize = 50;
object oItem;
oItem = GetModuleItemAcquired();

SendMessageToPC(GetFirstPC(), "DEBUG:  oItem = "+GetName(oItem)+" with tag "+GetTag(oItem));
if (!GetIsPC(oPC)) return;
RewardPartyXP(50, oPC, TRUE);
RewardPartyGP(80, oPC, TRUE);

 

See what messages you get, if any.



#15
Demkey

Demkey
  • Members
  • 18 messages

I'm getting the below message when I trying saving the script in toolset on the first line you gave me to add to the script, SendMessageToPC(oPC, "DEBUG:  Script Firing.");

 

aq_soulstone50.nss(10): ERROR: VARIABLE DEFINED WITHOUT TYPE



#16
BelowTheBelt

BelowTheBelt
  • Members
  • 394 messages

sorry about that - change the "oPC" to "GetFirstPC()"



#17
Demkey

Demkey
  • Members
  • 18 messages

Still no message at all. Wow, this thing is really busted. I loaded a backup I made just prior of adding in NWNX2 just to make sure it wasn't something more sever, and the script runs fine on that backup copy.



#18
Baaleos

Baaleos
  • Members
  • 1 329 messages
What I would consider is this
 
1. Your script is using GetUserDefined  - which suggests it needs to run from the OnUser Defined event on your module. This event will fire when a UserDefined event is triggered- to be honest, I am not an avid user of this, so I cannot guide you with regards to this.
 
2. In most conventional modules, the onAcquired event of the module is used for onAcquire of items. If you remove your GetUserDefined, and the switch statement from your script and then have the script in the onAquire event of the module, it would normally work.
 
From what I can see you are using your script like a 'super script' or a 'god file'
This from a coding point of view is when a script/class starts doing too much.
 
If you are open to the idea, I'd recommend you take
ExecuteScript("aq_"+GetTag(GetModuleItemAcquired()),OBJECT_SELF); break;
 
and place it in a script of its own.
Then put that script in the onAcquire event of the module.
 
Other lines like 
ExecuteScript("ue_"+GetTag(GetPCItemLastUnequipped()), OBJECT_SELF); break;
 
I would recommend they also go in separate scripts and in the events related to them as well.
Eg: onUnequipped script into the onUnequipped module event etc


#19
BelowTheBelt

BelowTheBelt
  • Members
  • 394 messages
Agree with Baaleos. Best solution is really to break your script up and put the pieces into their respective Module events.

Barring that, how do you have the User Defined event triggering? User Defined events need some code to tell the engine to run that script. Is there something in your module OnAcquire that sets a User Defined condition?

Post your mod's OnAcquire script.

Compare the scripts of the NWNX mod (the two above plus your module's OnAcquire script) with that if your working version to check for differences. Since you can't have two mods open simultaneously, use Notepad or something to copy the scripts from one mod, close the mod and open your other mod.

#20
Demkey

Demkey
  • Members
  • 18 messages

I got it to work!! WOO HOO!!

 

Thanks to you guys I started really taking a hard look at the scripts in the module properties. The NWNX2 OnModuleLoad (aps_onload) replaces out the original script (x2_mod_def_load). I started reviewing the original scripts and noticed the below lines were missing from the NWNX2 script, which seemed to me to be a critical component to what I was experiencing. So I went ahead and added those lines into the aps_onload. I received an compiling error when doing that so I just did a copy&paste of the whole x2_mod_def_load into the aps_onload and rebuilt the module, and it now works.

 

   SetModuleSwitch (MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS, TRUE);
   if (GetModuleSwitchValue (MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)

 

Thanks so much guys for your time and help, I would have never had looked that closely if it weren't for you two.

 

Hopefully I won't run into any issues with the NWNX2 stuff after doing this. What are your thoughts on that?



#21
Shadooow

Shadooow
  • Members
  • 4 468 messages

According to Lilac I have to use the below coding and name the script the same as the Resref of the object that I'm placing in the encounter's inventory as the drop (which would be soulstone50). Then I'm suppose to create a second file that contains the above script with the same name but with a leading aq_ so it would be aq_soulstone50. Like I mentioned earlier the script was running fine up until yesterday when I installed NWNX2.

 

Here is what I have in the soulstone50 file:

 

#include "x2_inc_switches"
void main()
{
int nEvent =GetUserDefinedItemEventNumber();
switch (nEvent)
   {
   case X2_ITEM_EVENT_ACTIVATE:
ExecuteScript("ac_"+GetTag(GetItemActivated()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_EQUIP:
ExecuteScript("eq_"+GetTag(GetPCItemLastEquipped()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_UNEQUIP:
ExecuteScript("ue_"+GetTag(GetPCItemLastUnequipped())
, OBJECT_SELF); break;
   case X2_ITEM_EVENT_ACQUIRE:
ExecuteScript("aq_"+GetTag(GetModuleItemAcquired()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_UNACQUIRE:
ExecuteScript("ua_"+GetTag(GetModuleItemLost()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_SPELLCAST_AT:
ExecuteScript("sp_"+GetTag(GetModuleItemLost()),
OBJECT_SELF); break;
   case X2_ITEM_EVENT_ONHITCAST:
ExecuteScript("on_"+GetTag(GetSpellCastItem()),
OBJECT_SELF); break;
   }
}

Im late to the party it seems but...

 

Where have you digg this crap? Thats a probably worst way how to deal with that seriously. Creating 7 scripts for each item, omg.

 

Baaleos advice is fine and Im using that method often, but if you have more items it might blow up your module scripts and make them disorganized. Probably the best way to do this is still using an UserDefined but with a single script for each item. Read this tutorial.



#22
Demkey

Demkey
  • Members
  • 18 messages

I would agree with you that it's allot of scripts to do simple functions. When it comes to these Soul Stone I have 20 different levels of them that do essentially the same thing but have some subtle differences to them. What that means is that I now have 40 scripts to hand those 20 object. But I'm not a scripter/programmer so I have to rely on Lilac, and that's the method that Lilac says to handle OnAquire scripting. I wish I knew a better way!



#23
Baaleos

Baaleos
  • Members
  • 1 329 messages
Hi Demkey,
Lilac Souls Generator is good for getting your foot in the door,
but I really do recommend you try to ween yourself off it soon.

There is only so far it can take you, and then you will eventually run out of ground and either have to fly or fall.

With the scripting language, the limitation really is whatever your imagination allows for.
Lilac Souls generator doesnt really allow you to stretch those muscles.

Generate some code, and then study it, and try to understand what its doing, and then try writing the same code yourself in future, and do slight optimizations as you go.

At the end of the day, the better scripter of the two (yourself and lilac souls generator) will always be you.
Because Lilac Souls Generator
1. Is only as smart as Lilac Soul was able to code it to be. Computer programs really aren't that smart.
2. It is incapable of that imaginative thinking mentioned, that a human can do.
3. It kinda promotes reliance on a 3rd party - you need to flex those muscles and learn from what you have.


The best way to do your scripting is to use
nwnlexicon.com

If you want to do a script that fires everytime 'something' is acquired, then study the
Events -> Module Events -> onAcquire
http://www.nwnlexico...e=OnAcquireItem

This is definitely your first step towards learning how to fly.

#24
BelowTheBelt

BelowTheBelt
  • Members
  • 394 messages

What that means is that I now have 40 scripts to hand those 20 object.

 

You can probably do it with 1 or only a couple scripts and 1 soulstone object by applying local integers on the soulstone item when it's created.

 

Start with a generic soulstone that is given to a PC.  When the item is created, have the script creating the object look at the circumstances of how it is created (the tag of the area, the level of the PC, or whatever the key differentiating factors are, etc...).  Then, SetLocalInt "SoulStoneType" on the item between 1 and 20.  Now you can tell what type of item it is just by using GetLocalInt on the item to look for that variable (rather than having 20 separate items).

 

In the OnAcquire, have it look for that variable, rather than the object tag/resref and take action accordingly...Int 1 = give 50gp/50xp.  int 2 = give 75gp/100xp, etc...  

 

This is much less to maintain and requires fewer resources.  What's more, it's scalable - you can add a limitless number of different variations of soulstones without having to make new scripts, items, etc...  Plus, a good challenge to learn!



#25
Demkey

Demkey
  • Members
  • 18 messages

Thanks for all the advice guys, and your help, I appreciate it. I just don't have the logic skills to code, somethings I can understand, but how to go about putting together anything complex is beyond my brain to figure out. What I need is my Coder back, but I don't think he has the time anymore so I'm going to have to make this module ugly I guess. LOL