Magic Mouth Spell (RESOLVED)

Hi Everyone,

I tried to find a Magic Mouth Spell on the vault, but could not find one. I found this one in the link below but it doesn’t use the CEP Magic Mouth placeables:

https://neverwintervault.org/project/nwn1/script/magic-mouth-spell

SO…

I want to create the 2nd Level Magic Mouth Spell. I have some idea on how to do it mix-matching currently existing spells and scripts. I have the base outline.

Going to use the Create Tattoo Spell I have (post it later here I picked up off the vault). Which allows you to pull up a conversation to cast a spell. From the conversation you can have preset comments you want the magic mouth you spawn/place (placeable) to say upon either touching it once it is spawned or by “OnHeartBeat”??? not sure which is better to interact with the Magic Mouth. I would think once someone comes close to it that it would activate and say its bit… I.E.

Choices:

  1. Hold here. Wait for us
  2. Go Back!
  3. Don’t mess with us!
  4. Trouble up ahead!
  5. Watch for Traps!
    6)…etc

As many choices as you want or somehow a PC can type in the Chat Bar what he wants the Magic Mouth to say (assign it the comments). If that is possible.

The spell outline below I took from the Ambient Object Controller if you are familiar with it. The concept of the spell structure I think can be done from here…right? I want to use the scripts associated with the Ambient Object Controller to adjust the degrees to face the mouth…would be nice also to adjust the location too. That sort of is done on the link above on that Magic Mouth Spell I put the link above to. Download the module sample and look at the script in the toolset.

   /                                                                         \
MAGIC MOUTH SPELL BASED ON THIS:

                         << Legend of the Red Dragon ReVisited >>

    Author:
        Dom Queron, dom(at)gulbsoft(dot)de, http://www.gulbsoft.de

    Description:
        Generic Ambient Placeable OnUsed Script
        Holds several OnUse Scripts in order to cut down the number of
        scripts in the module.

    version:
        $v1.0 00-00-00

    module information:
         http://gulbsoft.de/phpBB2x/g_viewcat.php?t=225


   \_________________________________________________________________________/

*/



void main()
{

    string sTag = GetTag(OBJECT_SELF);

     //Magic Mouth Types
    if (sTag == "curved_mouth" || sTag =="flatwall_mouth" || sTag == "floor_mouth")
    {

    //Curved Magic Mouth
    else if (sTag == "curved_mouth")
    {

          }

    }
    // Flat Wall Magic Mouth
    else if (sTag == "flatwall_mouth")


  }
    // Flat Wall Magic Mouth
    else if (sTag == "floor_mouth")
    {

        return;
    }

  }

Is this sort of workable?

Here is the Create Magic Tattoo Spell I got off the vault a long time ago. I like how when you cast the spell a conversation pops up to choose from a list. I know you can’t cast the spell in combat, but you don’t cast Magic Mouth in Combat…so it’s perfect:

include "spinc_common"

//
// Get the number of tatoo effects currently on the target.
//
int GetTatooCount(object oTarget, int nSpellID)
{
	// Loop through all of the effects on the target, counting
	// the number of them that have this spell ID.
	int nTatoos = 0;
	effect eEffect = GetFirstEffect(oTarget);
	while (GetIsEffectValid(eEffect))
	{
		if (nSpellID == GetEffectSpellId(eEffect)) nTatoos++;
		eEffect = GetNextEffect(oTarget);
	}
		
	return nTatoos;
}


void main()
{
	// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
	if (!X2PreSpellCastCode()) return;

	SPSetSchool(SPELL_SCHOOL_CONJURATION);
	object oTarget = GetSpellTargetObject();

	// The real scribe tatoo spell is the next spell in the 2da file after us, so
	// get it's spell ID.
	int nTatooSpellID = GetSpellId() + 1;
	
	if (GetIsPC(OBJECT_SELF))
	{
		// A creature is only allowed 3 tatoos, check the number they have to make
		// sure we have room to add another.
		int nTatoo = GetTatooCount(oTarget, nTatooSpellID);
		if (nTatoo >= 3)
		{
			// Let the caster know they cannot add another tatoo to the target.
			SendMessageToPC(OBJECT_SELF, GetName(oTarget) + " already has 3 tatoos.");
		}
		else
		{
			// Raise the spell cast event.
			SPRaiseSpellCastAt(oTarget, FALSE);

			// Save the ID of the tatoo spell (so the conversation scripts can cast it),
			// and save the metamagic and target.  Then invoke the conversation to
			// let the caster pick what tatoo to scribe.
			SetLocalInt(OBJECT_SELF, "SP_CREATETATOO_LEVEL", SPGetCasterLevel());
			SetLocalInt(OBJECT_SELF, "SP_CREATETATOO_SPELLID", nTatooSpellID);
			SetLocalInt(OBJECT_SELF, "SP_CREATETATOO_METAMAGIC", SPGetMetaMagic());
			SetLocalObject(OBJECT_SELF, "SP_CREATETATOO_TARGET", oTarget);
			ActionStartConversation(OBJECT_SELF, "sp_createtatoo", FALSE, FALSE);
		}
	}
	
	SPSetSchool();
}

To me…the concept I use from this is just casting a spell that brings up the conversation that you can choose the type of Magic Mouth you want…i.e. the Curved Magic Mouth, The Floor Magic Mouth, or the Wall Magic Mouth.

Hope all this makes sense.

Don’t judge me…lol…I’m no scripter…but maybe this is how to set up the script?


void main()
{
ActionStartConversation(OBJECT_SELF, "magicmouthspell", FALSE, FALSE);
    string sTag = GetTag(OBJECT_SELF);

     //Magic Mouth Types
    if (sTag == "curved_mouth" || sTag =="flatwall_mouth" || sTag == "floor_mouth")
    {
/////In here the choices to pick the comments

    1) Hold here. Wait for us
    2) Go Back!
    3) Don’t mess with us!
    4) Trouble up ahead!
    5) Watch for Traps!
    6)…etc

    //Curved Magic Mouth
    else if (sTag == "curved_mouth")
    {

          }
////same here the same choices above
    }
    // Flat Wall Magic Mouth
    else if (sTag == "flatwall_mouth")
////same here the same choices above

  }
    // Flat Wall Magic Mouth
    else if (sTag == "floor_mouth")
    {
////same here the same choices above
        return;
    }

  }

When you do an “if” statment you need a “{” after the paranthesis end, then the line of code, then a “}”.
Therefore this code you posted look rather odd:

/                                                                         \
MAGIC MOUTH SPELL BASED ON THIS:

                         << Legend of the Red Dragon ReVisited >>

    Author:
        Dom Queron, dom(at)gulbsoft(dot)de, http://www.gulbsoft.de

    Description:
        Generic Ambient Placeable OnUsed Script
        Holds several OnUse Scripts in order to cut down the number of
        scripts in the module.

    version:
        $v1.0 00-00-00

    module information:
         http://gulbsoft.de/phpBB2x/g_viewcat.php?t=225


   \_________________________________________________________________________/

*/



void main()
{

    string sTag = GetTag(OBJECT_SELF);

     //Magic Mouth Types
    if (sTag == "curved_mouth" || sTag =="flatwall_mouth" || sTag == "floor_mouth")
    {

    //Curved Magic Mouth
    else if (sTag == "curved_mouth")
    {

          }

    }
    // Flat Wall Magic Mouth
    else if (sTag == "flatwall_mouth")


  }
    // Flat Wall Magic Mouth
    else if (sTag == "floor_mouth")
    {

        return;
    }

  }

It should probably look a bit more like this:

/*                                                                        \
MAGIC MOUTH SPELL BASED ON THIS:

                         << Legend of the Red Dragon ReVisited >>

    Author:
        Dom Queron, dom(at)gulbsoft(dot)de, http://www.gulbsoft.de

    Description:
        Generic Ambient Placeable OnUsed Script
        Holds several OnUse Scripts in order to cut down the number of
        scripts in the module.

    version:
        $v1.0 00-00-00

    module information:
         http://gulbsoft.de/phpBB2x/g_viewcat.php?t=225


   \_________________________________________________________________________/

*/



void main()
{

    string sTag = GetTag(OBJECT_SELF);

     //Magic Mouth Types
    if (sTag == "curved_mouth" || sTag =="flatwall_mouth" || sTag == "floor_mouth")
    {

		//code here

	}
    //Curved Magic Mouth
    else if (sTag == "curved_mouth")
    {

         //code here 

    }
    // Flat Wall Magic Mouth
    else if (sTag == "flatwall_mouth")
	{

		//code here

	}
    // Flat Wall Magic Mouth
    else if (sTag == "floor_mouth")
    {
        return;
    }

 }

You posted:

else if (sTag == "curved_mouth")
    {

          }

    }

and that won’t do. Again, I hope you can see it?

You need it to be like this instead:

else if (sTag == "curved_mouth")
{

    
}

Another thing. When you include another script inside of a script, like in your case:

it needs to look like this for it to work:

#include "spinc_common"

Thanks again andgalf,

Sigh…I at least got the outline right?..lol…

This is how I would like to script it if I could…

1) When I cast the spell a conversation menu appears
2) You choose which mouth type appears
3) once the mouth type is selected to choose from a list of comments you want the magic mouth to say:
Choices:

1) Hold here. Wait for us
2) Go Back!
3) Don’t mess with us!
4) Trouble up ahead!
5) Watch for Traps!
6)…etc

4) So then I need the script to spawn the CEP magic mouth placeable where it is cast
5) Then either the PC interacts with it to get the message or preferably it is activated upon a heartbeat script as the PC approaches it (ideally).

How would a script start so that when you cast the spell…a conversation menu starts up?

Closes spell I could find that does that is the spell I posted here of the “Create Magic Tattoo”

Well, as you know I don’t work with NWN, but here are some guesses:

1) When I cast the spell a conversation menu appears

You can do that through the function ActionStartConversation, which you already did in your script. So I guess you could keep that.

Then, again just guessing since, as usual, you have quite demanding tasks with your scripts, and it gets complicated fast.

Maybe do something like (just adding to your attempt at your script):

/*                                                                        \
MAGIC MOUTH SPELL BASED ON THIS:

                         << Legend of the Red Dragon ReVisited >>

    Author:
        Dom Queron, dom(at)gulbsoft(dot)de, http://www.gulbsoft.de

    Description:
        Generic Ambient Placeable OnUsed Script
        Holds several OnUse Scripts in order to cut down the number of
        scripts in the module.

    version:
        $v1.0 00-00-00

    module information:
         http://gulbsoft.de/phpBB2x/g_viewcat.php?t=225


   \_________________________________________________________________________/

*/



void main()
{

    string sTag = GetTag(OBJECT_SELF);
	
	object 	oTarget = GetWaypointByTag("waypointtag");
	location lTarget = GetLocation(oTarget);

 
    //Curved Magic Mouth
    if (sTag == "curved_mouth")
    {

		object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "mouthtag2", lTarget);

    }
    // Flat Wall Magic Mouth
    else if (sTag == "flatwall_mouth")
	{

		object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "mouthtag3", lTarget);

	}
    // Flat Wall Magic Mouth
    else if (sTag == "floor_mouth")
    {
 
		object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "mouthtag4", lTarget);
    }

 }

Now, I have to go sleep. It’s after midnight here where I live…

Ok thanks bud :wink:

Have a good sleep my friend :slight_smile:

I’ll test it from here

Updated former post

Arrgh. Need to update post again. One moment.

EDIT: There. The first “if” statment made no sense.

1 Like

ok thanks

You will have to fill in the blanks. Again, this is so complicated. I wish you just wanted help with one script and not a whole sequence of stuff that needs doing.

No worries bud…I appreciate all you contribute…it is a start

A bit of advice before I go: Use Lilac’s Script Generator to get the basic scripts of what you need doing first. It would save so much time. I actually still use it when I can’t quite remember a specific thing. It speeds things up really well.

I’ve tried using it…but still not good at it…

In your script I don’t see where it starts the conversation?

Precisely. First you need the script that fires the conversation. Then inside the conversation (I think) you apply this script here. Like I said, you need to fill in the blanks.

Good night! I’ll check in tomorrow evening and see what you’ve managed to do.

1 Like

Ugh…I think this is getting closer… I took another spell where I create a placeable and used that small bit of script to put in each section for each type of Magic Mouth. I do use the correct CEP tag for each mouth though down below…lol

/*                                                                        \
MAGIC MOUTH SPELL

*/



void main()
{
    ActionStartConversation(OBJECT_SELF, "magicmouthspell", FALSE, FALSE);
    string sTag = GetTag(OBJECT_SELF);


    object  oTarget = GetWaypointByTag("waypointtag");
    location lTarget = GetLocation(oTarget);


    //Curved Magic Mouth
    if (sTag == "curved_mouth")
    {
        effect eVis = EffectVisualEffect(293);
        object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "ZEP_MAGICMTH004", GetSpellTargetLocation(), TRUE);
        DelayCommand(0.5f, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OM));
        SendMessageToPC(OBJECT_SELF, "You have cast the Magic Mouth spell.");
        SendMessageToAllDMs(GetName(OBJECT_SELF) + " the Magic Mouth spell.");

    }
    // Flat Wall Magic Mouth
    else if (sTag == "flatwall_mouth")
    {

        effect eVis = EffectVisualEffect(293);
        object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "ZEP_MAGICMTH006", GetSpellTargetLocation(), TRUE);
        DelayCommand(0.5f, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OM));
        SendMessageToPC(OBJECT_SELF, "You have cast the Magic Mouth spell.");
        SendMessageToAllDMs(GetName(OBJECT_SELF) + " the Magic Mouth spell.");

    }
    // Flat Floor Magic Mouth
    else if (sTag == "floor_mouth")
    {

        effect eVis = EffectVisualEffect(293);
        object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "ZEP_MAGICMTH008", GetSpellTargetLocation(), TRUE);
        DelayCommand(0.5f, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OM));
        SendMessageToPC(OBJECT_SELF, "You have cast the Magic Mouth spell.");
        SendMessageToAllDMs(GetName(OBJECT_SELF) + " the Magic Mouth spell.");
    }

 }

But I get this error…

Maybe I need to first start the conversation first on casting…

void main()
{
    ActionStartConversation(OBJECT_SELF, "magicmouthspell", FALSE, FALSE);
    string sTag = GetTag(OBJECT_SELF);
  }
}

then have it spawn one of the three options of the mouth??

Then from the chosen option have it give a list of what it will say?

Ugh…don’t know how to do this…but I feel I’m getting closer