Need help testing two spells - and scripting help

Hi everyone,

I know there are the following spells on many modules out there but many do not have them. They are the “Comprehend Languages” and “Tongues” spells.

I could never script those from other modules into mine because the scripting was too integrated into those modules scripting functions (new stuff I’ve never seen before).

So this is my attempt to add these spells to my module and then release them to the vault to those who struggle with getting these two spells into their modules too.

I have almost finished this…I am using the entry from the vault:

Language System & More widgets (NWN Vault)

https://neverwintervault.org/project/nwn1/script/language-system-and-more-widgets

I am using this system in the attached demo module I have attached.

I need to be able to have the current scripts I tried to get ChatGPT to script for me to accomplish this.

The scripts are in the DEMO module in the zipped file.

It’s all set up…I just need to know how to make the scripts do what they are suppose to do:

Tongues
Divination
Level: 3rd
Casting Time: 1 action
Range: Touch (Caster in NWN)
Components: V, S
Duration: 1 hour (10 minutes in NWN)

You grant the ability to understand and speak any spoken language. The target can comprehend and verbally respond in any language it hears, allowing seamless communication across language barriers. This spell does not enable the understanding of secret codes or mystical symbols that aren’t part of a spoken language.

**
Comprehend Languages Spell.zip (208.2 KB)
**

Comprehend Languages
Divination
Level: 1st
Casting Time: 1 action
Range: Self or Person
Components: V, S
Duration: 1 hour (10 minutes in NWN)
Save: No

You gain the ability to understand the literal meaning of any spoken language that you hear. You can also understand any written language that you see, but you must be touching the surface on which the words are written. It takes about 1 minute to read one page of text. This spell doesn’t decode secret messages in a text or a glyph, such as an arcane sigil, that isn’t part of a written language.

I’m the last person who should try to help you with this, but I tried anyway since I think you’re a nice guy. I loaded your demo module and everything seems fine. In the toolset all the scripts compile. There’s only a dwarf in the demo module and an old man giving you xp, then the spells are on the ground it seems. The dwarf says “Hello” whenever you click on him. I tried casting the spells and everything seems fine, by that I mean that the spells were cast and there were messages displayed that the PC should understand different languages now. If one is to speak Lizard shouldn’t there be a lizard there to test this? I don’t know how to help with this when I can’t test it properly and see what doesn’t work. Again, I should probably not even try to help you being so inexperienced with NWN1. So, if there were some creatures in the test module you could really test this on, and to really know what the result should look like, it would probably be a lot easier to try to help. But right now I’m at a total loss. Just asking “Please script this so it works” is way to vague for me to try to help with this, sorry.

EDIT: Checking the Language System and More widgets. | The Neverwinter Vault doesn’t say much of how to implement this. It seems you have placed the scripts in all the right places, but I don’t know… Maybe you need to place one of them on the OnConversation of the dwarf for example. Anyway, I don’t think I can help with this as it is too complicated, also it’s on NWN1 which complicates things even further, and I’m not sure what to do since the scripts are already there and seems legit.

Thanks bud again for your desire to help

You are correct in everything you said above.

I put the dwarf in there and a few language widgets on the ground…one of which is dwarven.

If you click on any of the language widgets on the ground when one is in your inventory you will see that in the chat bar it says you are now speaking …“dwarven” for example if you used the dwarven widget in your inventory. If you type something in the chat bar and hit enter your PC will speak and you will see the language in Dwarven pop up above its head but in the chat bar below it will be in “common”.

This part works as per the downloaded language system from the vault.

What I do not know is how to script it…to test it. To actually see if the NPC dwarf can say something in dwarven to test if my spell scripts are working.

I put the dwarf NPC there hoping someone could do that for me.

In the toolset in the custom items - special - custom 5 you will see all the languages there. I just put a few on the ground so you can see if they all work if you put any of the widgets in your inventory and right click on it in your inventory.

I just put the dwarf in there and “dwarven” for testing one of the languages. I do not know how to make an NPC speak in conversation in dwarven.

I would assume you would have to have the NPC speak a message like: “Hello, my name is…”

But if you do not know the language it would give you the response in dwarven not common until you either have the widget in your inventory or you cast one of the spells.

One spell (Comprehend Languages) lets you understand it…the other (Tongues) you could respond back in dwarven and he gives further dialogue in dwarven.

That seems too hard for me to script…I tried one script that compiled by ChatGPT it is in the toolset called:

“dwarfconv”…but I do not know where to put it…nor whether it will work

Note…I noticed that once you pick up one of the widgets and put it in your inventory you cannot drop it after. You would have to make the widget “dropable”…ugh forgot to toggle the box on the widget (uncheck it) to make it dropable from inventory.

You would have to bring in a new character after to test the spells.

Using the widget in inventory would only be to test the conversation first to see if you can get it to work…next would be to come in after with a new character after you get the conversation to work…to test the spells to see if they work.

I tried something, but I can’t quite get it to work fully though, but maybe it’s a step in the right direction. I put the “dwarfconv” on the OnConversation of the dwarf. Then I modified the script slightly to this (working in the NWN1 toolset is very uncomfortable and wonky for me):

// Script: npc_dwarf_convo
#include "pjr_chat_inc"  // Ensure you have necessary language translation includes

void main()
{
    object oPC = GetFirstPC();         // Player character initiating conversation
    object oNPC = OBJECT_SELF;           // The NPC
    string sDwarfPhrase = "'Welcome stranger'"; // NPC's Dwarven greeting
    string sDwarfApology = "Sorry, I don't understand you."; // NPC's apology

    // Check if PC has Dwarven language item or Comprehend Languages effect
    int bHasDwarvenItem = FALSE;
    object oItem = GetFirstItemInInventory(oPC);
    while (GetIsObjectValid(oItem))
    {
        if (GetTag(oItem) == "hlslang_4") // If player has the Dwarven language item
        {
            bHasDwarvenItem = TRUE;
            break;
        }
        oItem = GetNextItemInInventory(oPC);
    }

    int bHasComprehend = GetLocalInt(oPC, "pr_comprehend_4"); // Check if player has Comprehend Languages for Dwarven
    int bHasTongues = GetLocalInt(oPC, "pr_tongues"); // Check if player has Tongues spell effect

    // Process Dwarven phrases using your translation function
    string sGreetingInDwarf = ProcessDwarf(sDwarfPhrase);
    string sApologyInDwarf = ProcessDwarf(sDwarfApology);

    // If player has comprehension, NPC greets in Dwarven; otherwise, NPC apologizes
    if (bHasDwarvenItem || bHasComprehend)
    {
        FloatingTextStringOnCreature(TMESSAGE_TEXT + sGreetingInDwarf + COLOR_END, oPC, FALSE);

        if(bHasComprehend)
        {

               FloatingTextStringOnCreature("As you understand the language, you notice he says: " + sDwarfPhrase , oPC, FALSE);

        }

        // If player has Tongues, enable them to reply in Dwarven
        if (bHasTongues)
        {
            SetLocalInt(oPC, "pr_language", 4); // Set player's current language to Dwarven
            FloatingTextStringOnCreature(TMESSAGE_TEXT + "The NPC listens to your response in Dwarven." + COLOR_END, oPC, FALSE);
        }
    }
    else
    {
        FloatingTextStringOnCreature(TMESSAGE_TEXT + sApologyInDwarf + COLOR_END, oPC, FALSE);
    }
}

Thanks bud…

Getting closer…the script at least has the dwarf speaking in dwarven, but my spells and using the dwarven widget still do not allow me to understand the dwarf speaking in his language.

At least you got a lot further than I did :slight_smile:

Don’t you see the " As you understand the language, you notice he says: ‘Welcome stranger’"
in the chat window? I do when I test.

Nope never saw that. I picked up the dwarven widget and I spoke to him. All he says is hello in common. My PC repeats a dwarven comment that is not translated into common below in the chat.

I even use the dwarven widget and activate it and it does the same thing…I just see my PC speak a string of what looks lie dwarven, but no common translation. And both of the spells don’t work.

Are you in a debug mode?

What I did was I picked up both the things in the chest. Activated them and also the dwarven widget. When I did that I see the " As you understand the language, you notice he says: ‘Welcome stranger’". I believe the local ints are set when you do that and that’s what the dwarfconv script checks here:

if(bHasComprehend)
        {

               FloatingTextStringOnCreature("As you understand the language, you notice he says: " + sDwarfPhrase , oPC, FALSE);

        }
``

I see, but it defeats the purpose of the spells though

I cast them and he can’t understand the language without the widget in his inventory.

But at least now having the widget in the inventory allows the PC when it is activated to understand the dwarf :slight_smile:

Almost there, just need the spells to work now

This system is a bit too deep for me to get into, sorry. I think you’ll have to ask a much more experienced user of NWN:EE instead.

I just went by your script “dwarfconv” and noticed that it didn’t display any translation for the greeting in dwarf (at least I think so, but this is a bit beyond my capabilities):

FloatingTextStringOnCreature(TMESSAGE_TEXT + sGreetingInDwarf + COLOR_END, oPC, FALSE);

That’s why I put sDwarfPhrase in my FloatingTextStringOnCreature.

Ah, well, it’s time I left others more capable taking care of this. If you need help with very specific script questions where I know exactly what you want instead of just “I need to cast a spell that supposed to work like this” then I think I might be able to help, but to try and understand a whole system not made by myself with very little description by the original author is pretty daunting. I did that in my own module with the horse riding and manipulating/changing 4760’s scripts, that took several days and a lot of headache. I don’t have the time, energy and I’m not smart enough for something like this, I’m afraid.

Ok, so against my better judgment, I tried some more. I took the scripts into Notepad++ so I could watch several scripts at once, something that the NWN EE toolset permits me to do it seems.

In your “dwarfconv” scripts it asks to check for the local int “pr_tongues”. From what I can see of of all the scripts, this isn’t set anywhere.

This is why when testing when just casting the Comprehend Languages you only get the dwarf speak visible. If you look at this code:

 if (bHasDwarvenItem || bHasComprehend)
    {
        FloatingTextStringOnCreature(TMESSAGE_TEXT + sGreetingInDwarf + COLOR_END, oPC, FALSE);
}

This only displays (to my understanding) the sGreetingInDwarf and not the translation.

EDIT: What’s more odd is that when trying to read through the extensive pjr_chat_inc, I can’t see any function for translating back what the dwarf is saying. It should be something simple to just display what he says in common language, but I don’t know how to do that.

EDIT2: I might be on the verge of solving this. I’ll just be at it for an hour more…

EDIT3: I’m not sure I’ve been able to fix this fully, but it’s a step in the right direction, I believe.

Here’s the updated version of the “dwarfconv” script:

// Script: npc_dwarf_convo
#include "pjr_chat_inc"  // Ensure you have necessary language translation includes

void main()
{
    object oPC = GetFirstPC();         // Player character initiating conversation
    object oNPC = OBJECT_SELF;           // The NPC
    string sDwarfPhrase = "'Welcome stranger'"; // NPC's Dwarven greeting
    string sDwarfApology = "Sorry, I don't understand you."; // NPC's apology

    // Check if PC has Dwarven language item or Comprehend Languages effect
    int bHasDwarvenItem = FALSE;
    object oItem = GetFirstItemInInventory(oPC);
    while (GetIsObjectValid(oItem))
    {
        if (GetTag(oItem) == "hlslang_4") // If player has the Dwarven language item
        {
            bHasDwarvenItem = TRUE;
            break;
        }
        oItem = GetNextItemInInventory(oPC);
    }

    int bHasComprehend = GetLocalInt(oPC, "pr_comprehend_4"); // Check if player has Comprehend Languages for Dwarven
    int bHasTongues = GetLocalInt(oPC, "pr_tongues"); // Check if player has Tongues spell effect

    // Process Dwarven phrases using your translation function
    string sGreetingInDwarf = ProcessDwarf(sDwarfPhrase);
    string sApologyInDwarf = ProcessDwarf(sDwarfApology);


    // If player has comprehension, NPC greets in Dwarven; otherwise, NPC apologizes
    if (bHasDwarvenItem || bHasComprehend)
    {
        FloatingTextStringOnCreature(TMESSAGE_TEXT + sGreetingInDwarf + COLOR_END, oPC, FALSE);
        FloatingTextStringOnCreature(sDwarfPhrase + COLOR_END, oPC, FALSE);

        // If player has Tongues, enable them to reply in Dwarven
        if (bHasTongues)
        {
            SetLocalInt(oPC, "pr_language", 4); // Set player's current language to Dwarven
            FloatingTextStringOnCreature(TMESSAGE_TEXT + "The NPC listens to your response in Dwarven." + COLOR_END, oPC, FALSE);
        }
    }
    else
    {
        FloatingTextStringOnCreature(TMESSAGE_TEXT + sApologyInDwarf + COLOR_END, oPC, FALSE);
    }
}

As per this script, the only thing that the dwarf says will be “Welcome stranger” since that’s the only thing here. I have no idea how to implement other random phrases at the moment. Still the “pr_tongues” isn’t set anywhere to my knowledge.

Here’s the updated version of “sp_comprehendlan” script:

// Comprehend Languages Spell Script
#include "pjr_chat_inc"
#include "x2_inc_switches"

// Duration of the "Comprehend Languages" effect in seconds
const float fDuration = 600.0; // Adjust as needed for desired duration

void ApplyLanguageComprehension(object oPC);
void RemoveLanguageComprehension(object oPC);

void main()
{
    object oCaster = OBJECT_SELF;

    // Apply comprehension of all languages
    ApplyLanguageComprehension(oCaster);

    // Set a delayed action to remove language comprehension when the duration expires
    DelayCommand(fDuration, RemoveLanguageComprehension(oCaster));

    // Inform the player
    SendMessageToPC(oCaster, "You feel a surge of understanding for other languages.");
    FloatingTextStringOnCreature("You are able to comprehend all languages for a limited time.", oCaster, FALSE);
}

void ApplyLanguageComprehension(object oPC)
{
    object oItem;
    int iLan;

    // Cycle through items in inventory and check for language tags
    for (oItem = GetFirstItemInInventory(oPC); GetIsObjectValid(oItem); oItem = GetNextItemInInventory(oPC))
    {
        string sTag = GetTag(oItem);

        // Check if the item is a language item
        if (GetStringLeft(sTag, 8) == "hlslang_")
        {
            iLan = GetLanguageNumber(sTag);

            // Set language comprehension variables
            SetLocalInt(oPC, "pr_comprehend_" + IntToString(iLan), TRUE);

        }
        else if(sTag == "ComprehendLanguages" || sTag == "Tongues")
        {

              int nLanguage = 1;

              while (nLanguage <= 81)
                {
                SetLocalInt(oPC, "pr_comprehend_" + IntToString(nLanguage), TRUE);
                nLanguage = nLanguage + 1;
              }
        }
    }
}

void RemoveLanguageComprehension(object oPC)
{
    object oItem;
    int iLan;

    // Cycle through items in inventory and remove comprehension variables
    for (oItem = GetFirstItemInInventory(oPC); GetIsObjectValid(oItem); oItem = GetNextItemInInventory(oPC))
    {
        string sTag = GetTag(oItem);

        if (GetStringLeft(sTag, 8) == "hlslang_")
        {
            iLan = GetLanguageNumber(sTag);

            // Remove language comprehension variables
            DeleteLocalInt(oPC, "pr_comprehend_" + IntToString(iLan));
        }
    }

    // Inform the player
    SendMessageToPC(oPC, "The effect of Comprehend Languages fades, and you lose the understanding of other languages.");
    FloatingTextStringOnCreature("Your comprehension of languages has ended.", oPC, FALSE);
}

At the moment this works if you activate the dwarven widget (or what it’s called) or use the Comprehend Languages scroll/spell.

Now I leave this in more capable hands, someone else with much deeper understanding of scripting than my surface knowledge.

Again for those who wishes to help @Imtherealthing further, here are additional scripts used in this system (so that you don’t have to download the whole thing and muck about in the toolset):

The pjr_mod_activate script that I think runs when casting a spell looks like this:

//Example on Activate Script. Either use as is or cut and paste the included function into your own.
//Don't forget the include file as well
#include "pjr_chat_inc"


//#include "x2_inc_switches" //uncomment for tag-based scripting (commented out for export)
void main()
{
    object oItem = GetItemActivated();

/////////////////////////////Begin language changes///////////////////////
    object oPC=GetItemActivator();
    string sTag=GetTag(oItem);

    if(GetStringLeft(sTag, 8) == "hlslang_")
    {
        int bSpeaking=GetLocalInt(oPC,"pr_speaking");
        if (!bSpeaking)
        {
            string sTag=GetTag(oItem);
            int iLan=GetLanguageNumber(sTag);
            string sSpeaking=GetLanguageName(iLan);
            SetLocalInt(oPC,"pr_language",iLan);
            SetLocalInt(oPC,"pr_speaking",TRUE);
            SendMessageToPC(oPC,sTag);
            FloatingTextStringOnCreature(TMESSAGE_TEXT+"You are now speaking "+sSpeaking+". To return to speaking common, use this widget again."+COLOR_END,oPC,FALSE);
            return;
        }
        DeleteLocalInt(oPC,"pr_speaking");
        DeleteLocalInt(oPC,"pr_language");
        FloatingTextStringOnCreature(TMESSAGE_TEXT+"You are now speaking common."+COLOR_END,oPC,FALSE);
        return;
    }
//////////////////////////End language changes

     // * Generic Item Script Execution Code
     // * If MODULE_SWITCH_EXECUTE_TAGBASED_SCRIPTS is set to TRUE on the module,
     // * it will execute a script that has the same name as the item's tag
     // * inside this script you can manage scripts for all events by checking against
     // * GetUserDefinedItemEventNumber(). See x2_it_example.nss
/*     if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)
     {
        SetUserDefinedItemEventNumber(X2_ITEM_EVENT_ACTIVATE);
        int nRet =   ExecuteScriptAndReturnInt(GetUserDefinedItemEventScriptName(oItem),OBJECT_SELF);
        if (nRet == X2_EXECUTE_SCRIPT_END)
        {
           return;
        }

     } Uncomment the above section for tag-based scripting (commented out for export)*/

}

@Imtherealthing - I modified the the sp_tongues script that is run when the Tongues spell is cast. It looks like this after my modifications:

// Tongues Spell Script
// sp_tongues

#include "pjr_chat_inc"
#include "x2_inc_switches"

// Duration of the "Tongues" effect in seconds
const float fDuration = 600.0; // Adjust as needed for desired duration

void ApplyLanguageComprehensionAndSpeaking(object oPC);
void RemoveLanguageComprehensionAndSpeaking(object oPC);

void main()
{
    object oCaster = OBJECT_SELF;

    // Apply comprehension and speaking ability for all languages
    ApplyLanguageComprehensionAndSpeaking(oCaster);

    // Set a delayed action to remove the effect when the duration expires
    DelayCommand(fDuration, RemoveLanguageComprehensionAndSpeaking(oCaster));

    // Inform the player
    SendMessageToPC(oCaster, "You feel empowered to both understand and speak all languages.");
    FloatingTextStringOnCreature("You are now able to comprehend and speak all languages for a limited time.", oCaster, FALSE);
}

void ApplyLanguageComprehensionAndSpeaking(object oPC)
{
    object oItem;
    int iLan;


    // Cycle through items in inventory and check for language tags
    for (oItem = GetFirstItemInInventory(oPC); GetIsObjectValid(oItem); oItem = GetNextItemInInventory(oPC))
    {

        string sTag = GetTag(oItem);
        // Check if the item is a language item
        if (GetStringLeft(sTag, 8) == "hlslang_")
        {
            iLan = GetLanguageNumber(sTag);

            // Set language comprehension and speaking variables
            SetLocalInt(oPC, "pr_comprehend_" + IntToString(iLan), TRUE);
            SetLocalInt(oPC, "pr_speaking_" + IntToString(iLan), TRUE);  // Allow speaking
        }

        if(sTag == "Tongues")
        {
               SendMessageToPC(oPC,"Languages script running");
              int nLanguage = 1;
              int nSpeaklangue = 1;

              while (nLanguage <= 81)
              {
                SetLocalInt(oPC, "pr_comprehend_" + IntToString(nLanguage), TRUE);
                nLanguage = nLanguage + 1;
              }

              while (nSpeaklangue <= 81)
              {
                SetLocalInt(oPC, "pr_speaking_" + IntToString(nSpeaklangue), TRUE);
                nSpeaklangue = nSpeaklangue + 1;
              }

         }

    }



}

void RemoveLanguageComprehensionAndSpeaking(object oPC)
{
    object oItem;
    int iLan;

    // Cycle through items in inventory and remove comprehension and speaking variables
    for (oItem = GetFirstItemInInventory(oPC); GetIsObjectValid(oItem); oItem = GetNextItemInInventory(oPC))
    {
        string sTag = GetTag(oItem);

        if (GetStringLeft(sTag, 8) == "hlslang_")
        {
            iLan = GetLanguageNumber(sTag);

            // Remove language comprehension and speaking variables
            DeleteLocalInt(oPC, "pr_comprehend_" + IntToString(iLan));
            DeleteLocalInt(oPC, "pr_speaking_" + IntToString(iLan));
        }
    }

    // Inform the player
    SendMessageToPC(oPC, "The effect of Tongues fades, and you lose the ability to comprehend and speak other languages.");
    FloatingTextStringOnCreature("Your comprehension and speaking ability for languages has ended.", oPC, FALSE);
}

EDIT: Made a mistake in the sp_tongues script. Updated now.

Thanks andgalf, :slight_smile:

So far it looks like when I cast the spell it allows me to understand the dwarf. I will need to test this in multiplayer now with a friend talking to another PC.

I’ll let you know how that goes when I do

I appreciate ALL the time and effort you put into this for me bud

@Imtherealthing - You’re welcome. Now you got me worried though since you want to involve multiplayer in this too. The way the “dwarfconv” script is setup is that it the oPC object is GetFirstPC(); described by you as // Player character initiating conversation. With multiple player characters involved I don’t know if this is the right function to use. I have no experience with multiplayer stuff since I always only do things for singleplayer, and for NWN2.

Hopefully someone else can help you with that detail (and other details if this shouldn’t work the way you want to). I stress again and again that I’m totally the wrong person to help you with this, LOL, but since no other has come to your help with this particular system, I tried my best at least.
Maybe @Mmat or @Kamiryn can help out as they did with your other stuff, I don’t know…

GetFirstPC() should only be used in GetFirstPC()/GetNextPC() loops or in single player modules.

In conversations use GetPCSpeaker() to get the player char.

1 Like

Thanks Kamiryn :slight_smile:

Thanks andgalf :slight_smile:

Could you do the script with that part Kamiryn added?

@Kamiryn @Imtherealthing If you mean replacing GetFirstPC() with GetPCSpeaker(), the answer is no. Why, you may ask? Well, your original script, Imtherealthing, had GetPCSpeaker() instead of GetFirstPC() and that’s why it didn’t work. I think GetPCSpeaker() may actually only work inside or at the start of a conversation, but I’m not sure. So to trigger the “dwarfconv” which is put on the OnConversation of the dwarf, I had to change it to GetFirstPC() for it to trigger. So in this case I don’t know what else to use. Like I said, I’m only used to singleplayer NWN2 stuff and how it works there.
Just to be sure though, I’ll try it out with GetPCSpeaker() in case it was some other stuff that made it not working, but…well…

@Imtherealthing EDIT: Tested it, and it’s just like I said. GetPCSpeaker() doesn’t work since it’s not a real conversation that starts. It’s just a bunch of FloatingTextStringOnCreature that is used. Remember, everything you see in the test module is displayed in the chat window or above the creature’s heads. No dialogue window shows up. I have no idea how this system would/could work with real NWN conversations, and maybe that also defeats the purpose if it’s to be used in multiplayer in the chat window.
As always I have too litte information regarding the use of this system. How exactly it is meant to be implemented in modules or adventures? I need something a lot more concrete to go on, like an example of a scene inside an adventure, but again, I know nothing of multiplayer stuff. I’m used to be in full control of what happens in the adventure through my singleplayer modules/campaigns. This whole system feels pretty - and you’ll have to excuse me for saying this, but - odd to me, the whole thing, to be honest. I get you want to make something that’s for builders to download and use, but…it’s so vague.