Author Topic: Script Naming Requirements for tag-based scripting  (Read 419 times)

Legacy_UnrealJedi

  • Full Member
  • ***
  • Posts: 226
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« on: March 20, 2012, 03:23:06 pm »


               Hello all:

I have searched the web and found tutorials on tag-based scripting but there is conflicting information about how the scripts need to be named for TBS to work.

Would someone mind posting a definitive listing of how the scripts need to be named for the following? I have NWN, SoU, and HoTU all installed, updated to 1.69 and have CEP 2.4 (I think that's the latest version).

Thanks!

OnActivateItem
OnAcquireItem
OnPlayerEquipItem
OnPlayerUnEquipItem
OnUnAcquireItem
               
               

               
            

Legacy_Quillmaster

  • Full Member
  • ***
  • Posts: 126
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #1 on: March 20, 2012, 04:08:05 pm »


               OnActivateItem: ac_+TAG
OnPlayerEquipItem: eq_+TAG
OnPlayerUnequipItem: ue_+TAG
OnPlayerAcquireItem: aq_+TAG
OnPlayerUnacquireItem: ua_+TAG

There is of course a little more to it than that, but I'm presuming you have the rest all ready set up.  I got the above info from Lilac Souls Script Generator, which also describes what you need to do to get the whole thing working.  Has worked fine for me whenever I've used it. '<img'>
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #2 on: March 20, 2012, 06:34:33 pm »


               

Quillmaster wrote...

OnActivateItem: ac_+TAG
OnPlayerEquipItem: eq_+TAG
OnPlayerUnequipItem: ue_+TAG
OnPlayerAcquireItem: aq_+TAG
OnPlayerUnacquireItem: ua_+TAG

There is of course a little more to it than that, but I'm presuming you have the rest all ready set up.  I got the above info from Lilac Souls Script Generator, which also describes what you need to do to get the whole thing working.  Has worked fine for me whenever I've used it. '<img'>


Looks like Lilac has added extra functionality.

By default the script used is just the item's tag.   If you set a module prefix then you would use the module prefix before + tag for the script name.  Below is the script function that is called to get the script name.


string GetUserDefinedItemEventScriptName(object oItem)
{
    string sPrefix = GetLocalString(GetModule(),"MODULE_VAR_TAGBASED_SCRIPT_PREFIX");
    string sTag = sPrefix + GetTag(oItem);
    return sTag;
}
               
               

               


                     Modifié par WhiZard, 20 mars 2012 - 06:34 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #3 on: March 20, 2012, 08:09:01 pm »


               

Quillmaster wrote...

OnActivateItem: ac_+TAG
OnPlayerEquipItem: eq_+TAG
OnPlayerUnequipItem: ue_+TAG
OnPlayerAcquireItem: aq_+TAG
OnPlayerUnacquireItem: ua_+TAG

There is of course a little more to it than that, but I'm presuming you have the rest all ready set up. I got the above info from Lilac Souls Script Generator, which also describes what you need to do to get the whole thing working. Has worked fine for me whenever I've used it. '<img'>



I always wondered where and who came up with that mess,  In my opinion it totaly goes against what TBS has going for it.  That being, placing all of the code for a single item into one script.   Since I have high reguards for Lilac, I can only guess that the system predates the X2 expansion pack.  If you plan on making a module of a fair size, splitting the events into single scripts for each event will only increase the rate you aproach the 16k resource limit.  TBS itself is bad enough at that. there is no reason is compound it with increasing the script count even more.  

Wizard has the answer you where looking for.    
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #4 on: March 20, 2012, 08:43:34 pm »


               So the recommended why of handling tag based scripts is to capture the event type at the top of the tag based script, and then follow that with a switch statement that controls which code executes per each event type. If you want to see a detailed example of this I can post a copy of one, but I imagine one of the script experts here will beat me to it.

With Whizard and Lightfoot you are in very good hands.
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #5 on: March 20, 2012, 09:09:37 pm »


                <sailing a couple scrolls...>

There are a couple good sources to look at here: The Krit's Tag-based Template and Axe Murderer's tutorial (Anyone have a better link to this? I had to go to the Wayback Machine to find it :-P )

<...across the room>
               
               

               
            

Legacy_UnrealJedi

  • Full Member
  • ***
  • Posts: 226
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #6 on: March 21, 2012, 02:13:50 am »


               Thanks all. Looking at the instructions in LS's Script Generator (which I have used heavily, because I work and go to school full time plus I have a wife and 1 1/2 yr old...leaves little time to put in to learn scripting) I see this:

#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;
   }
}

If I am following the logic of the Script Generator (and I understand LS added in additonal functionality), I make a script for an item that, once it has been acquired by the PC, updates the PC's journal. The name of the script that actually updates the PC's jornal should be named aq_ITEMNAME. The above script should fire aq_ITEMNAME when the PC acquires any item with the same tag as ITEMNAME (minus the aq). Am I correct?

So, here is where I am confused. Where do I place the script I pasted above? I feel like the instructions in the Script Generator are telling me to use the script I pasted AS aq_ITEMNAME (naming it as such) but then the line ExecuteScript("aq_"+GetTag(GetModuleItemAcquired()),throws me, becauses this means it is being told to RUN the aq_ITEMNAME script. It's like I am being told to have the same script run itself. :-)

All this because I simply want an item to update the PC's journal once it has been acquired....

Thanks for the help guys!
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #7 on: March 21, 2012, 02:37:29 am »


               

UnrealJedi wrote...

Thanks all. Looking at the instructions in LS's Script Generator (which I have used heavily, because I work and go to school full time plus I have a wife and 1 1/2 yr old...leaves little time to put in to learn scripting) I see this:


There may be a possibility the quoted script is not firing.  Where does it appear and how is it called.  The answer may be that some module events are not making a user defined call.
               
               

               
            

Legacy_Quillmaster

  • Full Member
  • ***
  • Posts: 126
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #8 on: March 21, 2012, 08:59:51 am »


               

UnrealJedi wrote...

Thanks all. Looking at the instructions in LS's Script Generator (which I have used heavily, because I work and go to school full time plus I have a wife and 1 1/2 yr old...leaves little time to put in to learn scripting) I see this:

#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;
   }
}

If I am following the logic of the Script Generator (and I understand LS added in additonal functionality), I make a script for an item that, once it has been acquired by the PC, updates the PC's journal. The name of the script that actually updates the PC's jornal should be named aq_ITEMNAME. The above script should fire aq_ITEMNAME when the PC acquires any item with the same tag as ITEMNAME (minus the aq). Am I correct?

So, here is where I am confused. Where do I place the script I pasted above? I feel like the instructions in the Script Generator are telling me to use the script I pasted AS aq_ITEMNAME (naming it as such) but then the line ExecuteScript("aq_"+GetTag(GetModuleItemAcquired()),throws me, becauses this means it is being told to RUN the aq_ITEMNAME script. It's like I am being told to have the same script run itself. :-)

All this because I simply want an item to update the PC's journal once it has been acquired....

Thanks for the help guys!


Using Lilacs system, the above would simply be saved as the tag of the item in question, so for example, if the item were called myring, then the acquire script would be aq_myring and the above script simply saved as myring. 

I'm in a similar position with regard my time, particularly as a single parent with a 5 year old fast approaching 50.  Being an old dog unable to be taught new tricks in thanks mainly to a terrible memory, I love that I can use Lilacs generator with its pull down menus and options.  It's enabled me to do things even if it can't do it itself, as I can create the bulk then fine tune to what I'm trying to do, even learning the odd thing along the way, so I see nothing wrong with using it, although I do appreciate learning how to do things properly is more preferable.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #9 on: March 21, 2012, 09:43:16 am »


               I'd have to agree with some of the others that posted in reply. When I first got into scripting I depended heavily on Lilac's as well. When I got into the tag based scripting Lilac's confused the bajeezus out of me. And you end up 2 scripts for every tag based item/script that you make. I do not recommend doing tag based scripts with Lilac's. Don't get me wrong. I LOVE the script generator and it taught me a heck of a lot. But it just isn't very good for the tag based stuff.

You only need the 1 script that Lilac's makes for you. The one that it tells you to name "ac_xxxxxx", "eq_xxxxxx", etc. But it needs a simple event check at the top of the script that the generator does NOT add. The check will just make sure that the script will run fully if the item was activated in one of the specific ways(activated, equipped, etc). If you add that check then you just name this script the same as the tag of your item. No need to add any "ac", "eq", etc.

If you are having trouble with a specific script, post it here and we will show you how to add the check at the top.

Example:

#include "x3_inc_horse"
#include "x2_inc_switches"
void main()
{
    //This is a check to make sure that the item was "Activated".
    //Not equipped, unequipped, acquired, unacquired, etc.
    int nEvent =GetUserDefinedItemEventNumber();
    if(nEvent !=  X2_ITEM_EVENT_ACTIVATE)return;
    //End of check.

    object oPC = GetItemActivator();
    object oTarget = oPC;
    object oArea = GetArea(oPC);
    int nAreaType = GetIsAreaNatural(oArea);

    if (HorseGetIsMounted(oPC))
    {
        FloatingTextStringOnCreature("You are already on a horse.", oPC);
        return;
    }
    if (nAreaType != AREA_NATURAL)
    {
        FloatingTextStringOnCreature("You are unable to summon a horse here.", oPC);
        return;
    }
    else
    {
        AssignCommand(oTarget, ActionStartConversation(oPC, "warhorse_talk"));
    }
}


Good Luck.
               
               

               


                     Modifié par GhostOfGod, 21 mars 2012 - 09:45 .
                     
                  


            

Legacy_UnrealJedi

  • Full Member
  • ***
  • Posts: 226
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #10 on: March 21, 2012, 10:29:03 am »


               Thanks guys. Here's my script:

/*   Script generated by
Lilac Soul's NWN Script Generator, v. 2.3

For download info, please visit:
http://nwvault.ign.c...=4683&id=625    */

void main()
{
object oPC = GetModuleItemAcquiredBy();
object oItem;
oItem = GetModuleItemAcquired();
if (!GetIsPC(oPC)) return;
if (GetLocalInt(oPC, "ac_"+GetTag(oItem))) return;
SetLocalInt(oPC, "ac_"+GetTag(oItem), TRUE);
AddJournalQuestEntry("sarahsletter", 1, oPC, TRUE, FALSE);
}

I really appreciate all the help! I'd try to figure out the event check on my own but I am running late for work!

Thanks again!
               
               

               
            

Legacy_Quillmaster

  • Full Member
  • ***
  • Posts: 126
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #11 on: March 21, 2012, 11:59:11 am »


               So if I understand this correctly, ideally the script saved as the item name should have the execute script lines replaced with the code that lilac would have us place in a seperate script, with each activity designated as a case?  I think I'm getting it from the links Rolo Kipp provided.  I can only assume Lilac took the route he did to make it easier on the generator.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #12 on: March 21, 2012, 03:35:18 pm »


               

UnrealJedi wrote...

Thanks guys. Here's my script:

/*   Script generated by
Lilac Soul's NWN Script Generator, v. 2.3

For download info, please visit:
http://nwvault.ign.c...=4683&id=625    */

void main()
{
object oPC = GetModuleItemAcquiredBy();
object oItem;
oItem = GetModuleItemAcquired();
if (!GetIsPC(oPC)) return;
if (GetLocalInt(oPC, "ac_"+GetTag(oItem))) return;
SetLocalInt(oPC, "ac_"+GetTag(oItem), TRUE);
AddJournalQuestEntry("sarahsletter", 1, oPC, TRUE, FALSE);
}

I really appreciate all the help! I'd try to figure out the event check on my own but I am running late for work!

Thanks again!


So your script should look like this then:


/*   Script generated by
Lilac Soul's NWN Script Generator, v. 2.3

For download info, please visit:
http://nwvault.ign.c...=4683&id=625    */

//required "include" script
#include "x2_inc_switches"

void main()
{
//check that this is "acquired" event. If not return.
int iEvent = GetUserDefinedItemEventNumber();
if (iEvent != X2_ITEM_EVENT_ACQUIRE) return;
//end item event check.

object oPC = GetModuleItemAcquiredBy();
object oItem;
oItem = GetModuleItemAcquired();
if (!GetIsPC(oPC)) return;
if (GetLocalInt(oPC, "ac_"+GetTag(oItem))) return;
SetLocalInt(oPC, "ac_"+GetTag(oItem), TRUE);
AddJournalQuestEntry("sarahsletter", 1, oPC, TRUE, FALSE);
}



Keep in mind this is just the simple method of checking for one type of item event and stopping if it is not that event. You can do other things like Henesua suggested above where you can check for multiple item events in one script as well.

Hope it helps.
               
               

               


                     Modifié par GhostOfGod, 21 mars 2012 - 03:48 .
                     
                  


            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #13 on: March 21, 2012, 03:50:32 pm »


               

Quillmaster wrote...

So if I understand this correctly, ideally the script saved as the item name should have the execute script lines replaced with the code that lilac would have us place in a seperate script, with each activity designated as a case?  I think I'm getting it from the links Rolo Kipp provided.  I can only assume Lilac took the route he did to make it easier on the generator.


Yep. '<img'>
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Script Naming Requirements for tag-based scripting
« Reply #14 on: March 23, 2012, 12:41:30 am »


               

GhostOfGod wrote...

Quillmaster wrote...

So if I understand this correctly, ideally the script saved as the item name should have the execute script lines replaced with the code that lilac would have us place in a seperate script, with each activity designated as a case?  I think I'm getting it from the links Rolo Kipp provided.  I can only assume Lilac took the route he did to make it easier on the generator.


Yep. '<img'>


I guess a viable alternative would be to change the scripts called in the module events (and the on-hit:cast spell unique power script) so that each event calls a different prefixed script.  This would eliminate the need for doing a check as to how it was called and would not cause a doubling up of scripts.