Ventriloquism Spell (RESOLVED/DONE)

Hi everyone,

I was wondering how one (if it is possible) would be able to make an NPC, PC, or creature say words that are not theirs but yours (You cast the spell and type in the words you want to be spoken in the chat bar) then target the NPC, PC, or monster. I think if its possible it would be a fun spell.

Anyone know how to script this? I can do the rest, spell icon, 2da lines, tlk entries, etc and then post it to the vault with your name as main credit for that script. :slight_smile:

I’ve used stuff where the player has put in text that I’ve then used later for NWN2. I think it should work similar in NWN1. What you do is use a custom token:

For the input of words I’ve used a custom GUI with the function DisplayInputBox.

The scripting should be pretty straight forward but I wonder if it will be useful. Seems like it will just be eye (ear?) candy without a lot of situation specific scripting to make other NPCs react to it. You can make joe-npc (or joe-pc for that matter) say “piss off” to the barbarian in the tavern, but that won’t start a bar fight by itself.

You can capture the chat text and manipulate it, stopping the PC who typed it from displaying it. So your premise should work. Below is an OnChat script. This is lifted from a different script of mine and edited to show the idea, and compiles, but I have not tested this edit. It assumes you use the spell to target a valid object, which saved as a local object on the PC. When you want the target to say something, it is typed in chat with a special lead character “@”. I do not have a sample of the spell script idea itself - these are just my guesses on how you might want to do it. ; )

void main()
{
    object oPC = GetPCChatSpeaker();
    int nVolume = GetPCChatVolume();
    int nSpeak= GetLocalInt(oPC, "SPELL_SPEAK");
    string sSaid = GetPCChatMessage();
    string sSpeak = sSaid;

    if (nVolume != TALKVOLUME_SILENT_SHOUT)
    {
        // eat leading whitespace
        while (GetStringLeft(sSaid, 1) == " ")
        {
            sSaid = GetStringRight(sSaid, GetStringLength(sSaid)-1);
        }

        string sLeadChar = GetStringLeft(sSaid, 1);
        string s2ndChar = GetStringRight(GetStringLeft(sSaid, 2), 1);
        if (sLeadChar == "@" && nSpeak!=0)//Preface what target should say
        {
        object oPCCopy = GetLocalObject(oPC, "SPELL_TARGET");
        AssignCommand(oPCCopy, SpeakString(sSpeak, TALKVOLUME_TALK));
        SetPCChatMessage("");
        }
    }
}

-------------- As for usefullness, if one can make an NPC say a string, one can have script checks to modify the actions of others nearby. They can even have the script check the spoken string for particular words and have particular actions called for that.

Wow…thanks all…much appreciated. I will look through all these and see what works and if I need to blend them. I will get back to you all on here after to let you know the results.

Yeah, it would be just for fun. Basically to make your buddies laugh by making them (PC) say stuff they would not expect to be saying. Or to make NPCs say stuff to the PCs they normally would not say.

I guess one way this spell could be used to benefit the PC casting it is perhaps increase their bluff or to make a creature go off in a specific direction thinking he heard a noise off to the side when you are in stealth mode or invisible. Maybe script it so it makes the creature walk away from the PC? Just some ideas.

Right, custom, situation-specific scripting :slight_smile:

2 Likes

Hi Mannast,

I tried your script. It compiled but it does not work? I clicked on the NPC then in the chat bar I typed out words then hit enter to see if the words would come out of the NPC. It did not. Just out of the mouth of my PC. Am I doing something wrong?

i have attached the spell 2da, the spell, the tlk, and the spell icon…everything you need to make this spell. I zipped it here. So you can try it or anyone else here who wants to test it.

Once the scripting works I will release it to the vault.

Please feel free all of you to make any changes including the tlk file description…let me know.
ventriloquism spell.zip (58.8 KB)

If anyone has any suggestions with my upload (test it)…please let me know

The script I posted was for actions after you cast the spell. I will download what you put here and see what you have made. :slightly_smiling_face:
…
Edit - As I said, the script I wrote was a sample of how to grab chat and give it to a target - but it doesn’t define the target itself - that would be the spell. If I get a chance, I will try and put a possible version of that together, and then we shall see if we can make the target talk.

1 Like

Thanks…as I’ve said before…scripting is not my forte :slight_smile:

Well here are some simple versions of those scripts. The spell script has just the basics

//Sample Ventriloquism spell - Mannast Dec 2022
//- needs to have:
//Saving Throw added
//Invisible object added so caster can make a location speak
//Actual checks
#include "x0_i0_spells"
#include "x2_inc_spellhook"

void main()
{
    //--------------------------------------------------------------------------
    /*
      Spellcast Hook Code
      Added 2003-06-20 by Georg
      If you want to make changes to all spells,
      check x2_inc_spellhook.nss to find out more
    */
    //--------------------------------------------------------------------------
    if (!X2PreSpellCastCode())
    {
        return;
    }
    // End of Spell Cast Hook
    object    oTarget      = GetSpellTargetObject();
    location  lLocal       = GetSpellTargetLocation();
    int       nCasterLevel = GetCasterLevel(OBJECT_SELF);
    int nDelay = nCasterLevel*60;

if(oTarget==OBJECT_INVALID)
    {
    //Create an invisible object and make it the target
    }
SetLocalObject(OBJECT_SELF, "SPELL_TARGET", oTarget);
SetLocalInt(OBJECT_SELF, "SPELL_SPEAK", 1);
SendMessageToPC(OBJECT_SELF, "You can try to make your target say your words.  Type @ before what you would like them to say.");
DelayCommand(IntToFloat(nDelay), DeleteLocalObject(OBJECT_SELF, "SPELL_TARGET"));
DelayCommand(IntToFloat(nDelay), DeleteLocalInt(OBJECT_SELF, "SPELL_SPEAK"));
DelayCommand(IntToFloat(nDelay), SendMessageToPC(OBJECT_SELF, "Your Ventriloquism Spell has expired"));
}

And this is the sample module OnChat script. If you already have an OnChat script, copy the stuff that is not already there into the void main()

//Sample Ventriloquism spell OnChat script
//Put or call in Module OnChat script

void main()
{
    object oPC = GetPCChatSpeaker();
    int nVolume = GetPCChatVolume();
    int nSpeak= GetLocalInt(oPC, "SPELL_SPEAK");
    string sSaid = GetPCChatMessage();
    string sSpeak = sSaid;

    if (nVolume != TALKVOLUME_SILENT_SHOUT)
    {
        // eat leading whitespace
        while (GetStringLeft(sSaid, 1) == " ")
        {
            sSaid = GetStringRight(sSaid, GetStringLength(sSaid)-1);
        }

        string sLeadChar = GetStringLeft(sSaid, 1);
        string s2ndChar = GetStringRight(GetStringLeft(sSaid, 2), 1);
        if (sLeadChar == "@" && nSpeak!=0)//Preface what target should say
        {
        object oPCCopy = GetLocalObject(oPC, "SPELL_TARGET");
        AssignCommand(oPCCopy, SpeakString(sSpeak, TALKVOLUME_TALK));
        SetPCChatMessage("");
        }
    }
}

See if this stuff works. My usual caveat - I have not tested this, but won’t be able to until this evening at the earliest.

Hey thanks Mannest for doing this. It seems more complicated than I’d image it would be. Could you test it and create this “invisible object” the scripts calls for. A sample module with all this would help me a lot. I would have to see how you create this invisible object and your adding this other script to the module OnChat script.

The invisible object thing is if you happen to not click on an actual target - if you click on an npc or door or table… it should work. The invisible object things was just a thought if the PC clicked on the open floor or the wall of a tile… etc. Whipping up a sample module may take a few days, as RL is relatively intense.

Ok…so I will try it out without this invisible object. See what happens :slight_smile:

1 Like

Ok…I put the script above as the script called for: sp_ventriloquism as per defined on the spell 2da

Then I added the OnChat script section into my OnChat script on the module events. It compiled.

I then went in memorized the spell three times

  1. I cast the spell…targeted the NPC. Then typed in the chat box: @hello I’m george (did not work)
  2. I then cast the spell and tried again. I targeted the same NPC then typed in the chat box: @ hello I’m george (did not work)
  3. I then cast the spell again. Targeted the same NPC and typed in the chat box the @ symbol hit enter then retyped the same words above (did not work)

I’m thinking it needs that invisible item/placeable thingy.

Or Am I doing something wrong?

When you do cast the spell the words do show up saying to put the “@” symbol before typing in the words…so that works :slight_smile:

@Imtherealthing - I really wish I could help, but in this case all these funcions Mannast are using, are not available in NWN2, and I don’t know the NWN1 toolset that well to try and figure these things out. Like I said in my first post here, I would probably go about this in a whole different way.

1 Like

I will give it a go and let you know - the casting should work for a few rounds on one target - you should be getting text feedback when it is cast and when it expires.

Hi andgalf,

No worries bud. I’m just grateful you tried to help. :slight_smile:

You should convert over to NWN:EE…join us!!!..lol

Hi Mannast,

Thanks for looking into this. yeah I tried everything…still a no-go. I wish I knew how to script. I appreciate you doing this. All we need is the scripting and maybe some additional info on the tlk file description…and I will release this to the vault with credit to you. :slight_smile:

If you want to share here the test module you whipped up, I can look at it and see why it might not be working?