Fortunately, you are surrounded by people who do know NWScript, and can pass you the bits and pieces of code you need, along with explanations for how they work, wherefore you need never fear the wicked and vicious curse of the brackets. WHY RUN WHEN YOU CAN FLY, GOOD FELLOW!
- Setting up OnEnter events for floor triggers.
Draw a new generic floor trigger on the ground.
Create a new script in the floor trigger’s OnEnter event.
When any object enters the trigger, the code in this event will run. Because of this, you will need to add abort checks to ensure that the specified events only happen for player characters, and possibly only happen once per player character, or only once at all.
Within void main, declare an object, and define it as the entering object:
void main()
{
// We declare the object oPC, and define it as the entering object.
object oPC = GetEnteringObject();
// If the entering object is not a player chacter, abort the script at this point.
if (!GetIsPC(oPC))
return;
// If a local integer has been set on the floor trigger, unique to the entering object, abort the script at this point.
if (GetLocalInt(OBJECT_SELF, ObjectToString(oPC)))
return;
// Store the local integer for this entering object on the floor trigger, so that the trigger will not work next time.
SetLocalInt(OBJECT_SELF, ObjectToString(oPC), TRUE);
// Do stuff here. For example, speak a string.
AssignCommand(oPC, SpeakString("I am apparently a player character who is entering this trigger for the first time!"));
}
Mind, there are many ways to do “once only” checks, and “the best” way to do them varies. A lot of stuff that’s harmless in singleplayer modules can cause problems in multiplayer or PW ones.
You can pick and choose your favourites among the ways to present the conversation:
- Having the PC speak strings.
AssignCommand(oPC, SpeakString("I'm walking around and talking to myself!"));
You can also delay assigning the command a bit:
AssignCommand(oPC, SpeakString("I'm walking around and talking to myself!"));
DelayCommand(1.0, AssignCommand(oPC, SpeakString("Daa daa doo dee doo!")));
- Sending text messages to the PC.
SendMessageToPC(oPC, "I am monologuing internally because I can.");
- Having brief floating text strings appear over the PC and immediately fade away again.
FloatingTextStringOnCreature("You smell cookies. Mmmm!", oPC);
- Having the PC start a conversation with themselves.
// Clear the PC's action queue, aborting whatever they are currently doing.
// The TRUE parameter specifies that the PC should be taken out of combat state as well.
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionStartConversation(oPC, "thisisthenameoftheconversationtostart"));
- Having the PC start a conversation with a spawned-in "narrator" invisible object.
To do this, you need to create a blueprint for a placeable. The ResRef of the placeable blueprint will be used by CreateObject to spawn in the placeable.
// Here, we are spawning a placeable using the blueprint with the resref "narrator", at the current location of object oPC.
object oNarrator = CreateObject(OBJECT_TYPE_PLACEABLE, "narrator", GetLocation(oPC));
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionWait(0.5));
AssignCommand(oPC, ActionStartConversation(oNarrator, "narrator001"));
This is how an example OnEnter event script for a one-size-fits-all "When the PC enters this trigger for the first time, they should say something"-trigger could look, in it's entirety*:
void main()
{
object oPC = GetEnteringObject();
string sIdentifier = ObjectToString(oPC);
// Abort if the entering object is not a PC, or if the entering object has passed this trigger already.
if (!GetIsPC(oPC) || GetLocalInt(OBJECT_SELF, sIdentifier))
return;
// Store the entering object on the trigger, to be able to check whether it has already passed the trigger.
SetLocalInt(OBJECT_SELF, sIdentifier, TRUE);
// Cycle through local strings stored on the trigger...
int i;
string sSpeak = GetLocalString(OBJECT_SELF, "SPEAK_0");
while (sSpeak != "")
{
// ... and make the entering object speak them.
DelayCommand(IntToFloat(i), AssignCommand(oPC, SpeakString(sSpeak)));
sSpeak = GetLocalString(OBJECT_SELF, "SPEAK_"+IntToString(++i));
}
}
The above variant checks through local strings stored on the trigger under “SPEAK_0”, “SPEAK_1”, “SPEAK_2”, and so on, speaking them at a 1 second delay after one another.
*Disclaimer: Did not test beyond checking that everything compiles.
You can colour-tint text, too, by including the x3_inc_string library.
#include "x3_inc_string"
void main()
{
string sColouredString = StringToRGBString("Cake!", "700");
}
You’d make a PC speak coloured text like this:
AssignCommand(oPC, SpeakString(StringToRGBString("I can alter the COLOUR of my speech! That's pretty amazing, hey?", "717")));
Tarot made a colour catalogue here:
Colours and Codes for StringToRGBString() | The Neverwinter Vault