Shargast_PRC8/_module/Chapter 2/nss/zdlg_include_i.nss
Jaysyn904 66a0a3e043 Initial commit
Initial commit.
2024-08-03 14:13:18 -04:00

527 lines
17 KiB
Plaintext

/**
* $Id: zdlg_include_i.nss,v 1.2 2005/08/07 04:38:30 pspeed Exp $
*
* Include file for using the Z-Dialog runtime conversation
* system.
*
* This system allows a user to define conversation trees at
* runtime and handle the selections programmatically. Really
* useful for menu systems without script explosion.
*
* Copyright (c) 2004 Paul Speed - BSD licensed.
* NWN Tools - http://nwntools.sf.net/
*/
#include "pg_lists_i"
// Constants defined for dialog events
const int DLG_INIT = 0; // new dialog is started
const int DLG_PAGE_INIT = 1; // a new page is started
const int DLG_SELECTION = 2; // item is selected
const int DLG_ABORT = 3; // dialog was aborted
const int DLG_END = 4; // dialog ended normally
const string DLG_CURRENT_HANDLER = "currentDialog";
const string DLG_HANDLER = "dialog";
const string DLG_PROMPT = "zdlgPrompt";
const string DLG_RESPONSE_LIST = "zdlgResponseList";
const string DLG_RESPONSE_LIST_HOLDER = "zdlgResponseHolder";
const string DLG_EVENT_TYPE = "zdlgEventType";
const string DLG_EVENT_SELECTION = "zdlgEventSelection";
const string DLG_PAGE_ID = "zdlgPageId";
const string DLG_ITEM = "zdlgItem";
const string DLG_ITEM_CONVERSER = "zdlgConverser";
const string DLG_STATE = "zdlgState";
const string DLG_START_ENTRY = "zdlgStartEntry";
const string DLG_HAS_PREV = "zdlgHasPrevious";
const string DLG_HAS_NEXT = "zdlgHasNext";
const string DLG_HAS_END = "zdlgHasEnd";
// Some state constants that the zdlg_page_init check
// can use to determine current conversation state.
const int DLG_STATE_INIT = 0;
const int DLG_STATE_RUNNING = 1;
const int DLG_STATE_ENDED = -1;
// The base token for the dialog inserts. +0 is the
// prompt. +1 - +13 is the item text. These values
// must match the .dlg file exactly.
const int DLG_BASE_TOKEN = 4200;
// Returns the current PC speaker for this dialog.
// This has some enhanced features to work around bioware
// limitations with item dialogs.
object GetPcDlgSpeaker();
// Sets the new current dialog handler script for the current conversation.
// This allows on the fly conversation changes and linking. This must
// be called within a conversation related event.
void SetCurrentDlgHandlerScript( string script );
// Returns the current dialog handler script for the current conversation.
string GetCurrentDlgHandlerScript();
// Returns the current conversation's default dialog handler script if
// it has one defined. This is used when there is otherwise
// not a current handler script set.
string GetDefaultDlgHandlerScript( object oNPC = OBJECT_SELF );
// Sets the prompt that will be displayed in the dialog
// when talking to the current speaker.
void SetDlgPrompt( string prompt );
// Returns the current prompt that will be displayed in the
// dialog when talking to the current speaker.
string GetDlgPrompt();
// Set to TRUE if the end dialog selection should be shown
// on every page. FALSE if not.
void SetShowEndSelection( int flag );
// Returns TRUE if the end dialog selection should be shown
// on every page. FALSE if not.
int GetShowEndSelection();
// Sets the list of responses that will be displayed in the
// dialog when talking to the current speaker.
void SetDlgResponseList( string listId, object oListHolder );
// Returns the list id for the list of responses that will be
// displayed in the dialog when talking to the current speaker.
string GetDlgResponseList();
// Returns the dialog type of event that caused the handler
// script to be executed.
int GetDlgEventType();
// Returns the selected item in a DLG_SELECTION event.
int GetDlgSelection();
// Sets a page string that the handler scripts can use to track
// progress through the conversation. This is really just a
// convenience function that tacks a local var onto the PC dlg
// speaker. It has the added benefit of getting auto-cleaned
// with the dialog clean-up.
void SetDlgPageString( string page );
// Returns a page string that the handler scripts can use to track
// progress through the conversation.
string GetDlgPageString();
// Sets a page integer that the handler scripts can use to track
// progress through the conversation. This is really just a
// convenience function that tacks a local var onto the PC dlg
// speaker. It has the added benefit of getting auto-cleaned
// with the dialog clean-up.
void SetDlgPageInt( int page );
// Returns a page integer that the handler scripts can use to track
// progress through the conversation.
int GetDlgPageInt();
// Called to initiate a conversation programmatically between
// the dialog source and the object to converse with. If
// dlgHandler is "" then the object's default script will be used.
void StartDlg( object oPC, object oObjectToConverseWith, string dlgHandler = "", int bPrivate = FALSE, int bPlayHello = TRUE, int bZoom = TRUE );
// Ends the current conversation and will fire the DLG_END event.
void EndDlg();
// Returns the current PC speaker for this dialog.
// This has some enhanced features to work around bioware
// limitations with item dialogs.
object GetPcDlgSpeaker()
{
object oPC = GetPCSpeaker();
if( oPC == OBJECT_INVALID )
{
// See if we're an item and if we're connected to a PC already.
// Note: GetItemActivator won't work in multiplayer because other
// players will be trouncing on its state.
oPC = GetLocalObject( OBJECT_SELF, DLG_ITEM_CONVERSER );
}
if( oPC == OBJECT_INVALID )
PrintString( "WARNING: Unable to retrieve a PC speaker." );
return( oPC );
}
// Sets the new current dialog handler script for the current conversation.
// This allows on the fly conversation changes and linking. This must
// be called within a conversation related event.
void SetCurrentDlgHandlerScript( string script )
{
SetLocalString( GetPcDlgSpeaker(), DLG_CURRENT_HANDLER, script );
}
// Returns the current dialog handler script for the current conversation.
string GetCurrentDlgHandlerScript()
{
return( GetLocalString( GetPcDlgSpeaker(), DLG_CURRENT_HANDLER ) );
}
// Returns the current conversation's default dialog handler script if
// it has one defined. This is used when there is otherwise
// not a current handler script set.
string GetDefaultDlgHandlerScript( object oNPC = OBJECT_SELF )
{
return( GetLocalString( oNPC, DLG_HANDLER ) );
}
// Sets the prompt that will be displayed in the dialog
// when talking to the current speaker.
void SetDlgPrompt( string prompt )
{
SetLocalString( GetPcDlgSpeaker(), DLG_PROMPT, prompt );
}
// Returns the current prompt that will be displayed in the
// dialog when talking to the current speaker.
string GetDlgPrompt()
{
return( GetLocalString( GetPcDlgSpeaker(), DLG_PROMPT ) );
}
// Set to TRUE if the end dialog selection should be shown
// on every page. FALSE if not.
void SetShowEndSelection( int flag )
{
SetLocalInt( GetPcDlgSpeaker(), DLG_HAS_END, flag );
}
// Returns TRUE if the end dialog selection should be shown
// on every page. FALSE if not.
int GetShowEndSelection()
{
return( GetLocalInt( GetPcDlgSpeaker(), DLG_HAS_END ) );
}
// Sets the list of responses that will be displayed in the
// dialog when talking to the current speaker.
void SetDlgResponseList( string listId, object oListHolder )
{
object oSpeaker = GetPcDlgSpeaker();
SetLocalObject( oSpeaker, DLG_RESPONSE_LIST_HOLDER, oListHolder );
SetLocalString( oSpeaker, DLG_RESPONSE_LIST, listId );
//DeleteLocalInt( oSpeaker, DLG_HAS_PREV );
//DeleteLocalInt( oSpeaker, DLG_HAS_NEXT );
//DeleteLocalInt( oSpeaker, DLG_START_ENTRY );
}
// Returns the list id for the list of responses that will be
// displayed in the dialog when talking to the current speaker.
string GetDlgResponseList()
{
return( GetLocalString( GetPcDlgSpeaker(), DLG_RESPONSE_LIST ) );
}
// Returns the dialog type of event that caused the handler
// script to be executed.
int GetDlgEventType()
{
return( GetLocalInt( GetPcDlgSpeaker(), DLG_EVENT_TYPE ) );
}
// Returns the selected item in a DLG_SELECTION event.
int GetDlgSelection()
{
return( GetLocalInt( GetPcDlgSpeaker(), DLG_EVENT_SELECTION ) );
}
// Sets a page string that the scripts can use to track
// progress through the conversation.
void SetDlgPageString( string page )
{
object oSpeaker = GetPcDlgSpeaker();
SetLocalString( oSpeaker, DLG_PAGE_ID, page );
DeleteLocalInt( oSpeaker, DLG_HAS_PREV );
DeleteLocalInt( oSpeaker, DLG_HAS_NEXT );
DeleteLocalInt( oSpeaker, DLG_START_ENTRY );
}
// Returns a page string that the scripts can use to track
// progress through the conversation.
string GetDlgPageString()
{
return( GetLocalString( GetPcDlgSpeaker(), DLG_PAGE_ID ) );
}
// Sets a page string that the scripts can use to track
// progress through the conversation.
void SetDlgPageInt( int page )
{
SetLocalInt( GetPcDlgSpeaker(), DLG_PAGE_ID, page );
//DeleteLocalInt( GetPcDlgSpeaker(), DLG_HAS_PREV );
//DeleteLocalInt( GetPcDlgSpeaker(), DLG_HAS_NEXT );
//DeleteLocalInt( GetPcDlgSpeaker(), DLG_START_ENTRY );
}
// Returns a page string that the scripts can use to track
// progress through the conversation.
int GetDlgPageInt()
{
return( GetLocalInt( GetPcDlgSpeaker(), DLG_PAGE_ID ) );
}
// Called to initiate a conversation programmatically between
// the dialog source and the object to converse with. If
// dlgHandler is "" then the object's default script will be used.
void StartDlg( object oPC, object oObjectToConverseWith, string dlgHandler = "",
int bPrivate = FALSE, int bPlayHello = TRUE, int bZoom = TRUE )
{
// Setup the conversation
if( dlgHandler != "" )
SetLocalString( oPC, DLG_CURRENT_HANDLER, dlgHandler );
if( GetObjectType( oObjectToConverseWith ) == OBJECT_TYPE_ITEM )
{
// We presume that only one player can talk to an item at
// a time... we could check, but we don't.
SetLocalObject( oObjectToConverseWith, DLG_ITEM_CONVERSER, oPC );
// We can't actually talk to items so we fudge it.
SetLocalObject( oPC, DLG_ITEM, oObjectToConverseWith );
oObjectToConverseWith = oPC;
}
string dlg = "zdlg_converse";
if( !bZoom )
dlg = "zdlg_converse_nz";
AssignCommand( oObjectToConverseWith,
ActionStartConversation( oPC, dlg, bPrivate, bPlayHello ) );
}
// Ends the current conversation and will fire the DLG_END event.
void EndDlg()
{
object oSpeaker = GetPcDlgSpeaker();
SetLocalInt( oSpeaker, DLG_STATE, DLG_STATE_ENDED );
}
// Returns the number of responses that will be displayed
// in the dialog when talking to the specified speaker.
// The speaker can be specified for looping optimization
// so that the functions don't have to retrieve it every time.
int GetDlgResponseCount( object oSpeaker )
{
object oHolder = GetLocalObject( oSpeaker, DLG_RESPONSE_LIST_HOLDER );
string listId = GetLocalString( oSpeaker, DLG_RESPONSE_LIST );
return( GetElementCount( listId, oHolder ) );
}
// Returns the response string for the specified entry.
// The speaker can be specified for looping optimization
// so that the functions don't have to retrieve it every time.
string GetDlgResponse( int num, object oSpeaker )
{
object oHolder = GetLocalObject( oSpeaker, DLG_RESPONSE_LIST_HOLDER );
string listId = GetLocalString( oSpeaker, DLG_RESPONSE_LIST );
return( GetStringElement( num, listId, oHolder ) );
}
// Sets up the previous/next buttons
void _SetDlgPreviousNext( object oSpeaker, int hasPrevious, int hasNext )
{
SetLocalInt( oSpeaker, DLG_HAS_PREV, hasPrevious );
SetLocalInt( oSpeaker, DLG_HAS_NEXT, hasNext );
}
// Returns true if the "previous" entry is turned on in the
// response list
int _HasDlgPrevious( object oSpeaker )
{
return( GetLocalInt( oSpeaker, DLG_HAS_PREV ) );
}
// Returns true if the "next" entry is turned on in the
// response list
int _HasDlgNext( object oSpeaker )
{
return( GetLocalInt( oSpeaker, DLG_HAS_NEXT ) );
}
// Returns true if the "end" entry is turned on in the
// response list
int _HasDlgEnd( object oSpeaker )
{
return( GetLocalInt( oSpeaker, DLG_HAS_END ) );
}
// Sets the starting entry for when a response list is
// broken into multiple pages.
void _SetDlgFirstResponse( object oSpeaker, int start )
{
SetLocalInt( oSpeaker, DLG_START_ENTRY, start );
}
// Returns the starting entry for when a response list is
// broken into multiple pages.
int _GetDlgFirstResponse( object oSpeaker )
{
return( GetLocalInt( oSpeaker, DLG_START_ENTRY ) );
}
// Sets the token for the response string and returns true
// if there is a valid response entry for the specified num.
int _SetupDlgResponse( int num, object oSpeaker )
{
int hasNext = _HasDlgNext( oSpeaker );
int hasPrev = _HasDlgPrevious( oSpeaker );
int hasEnd = _HasDlgEnd( oSpeaker );
if( (hasNext || hasPrev || hasEnd) && num >= 10 )
{
if( hasNext && num == 10 )
{
SetCustomToken( DLG_BASE_TOKEN + 11, "Next" );
return( TRUE );
}
if( hasPrev && num == 11 )
{
SetCustomToken( DLG_BASE_TOKEN + 12, "Previous" );
return( TRUE );
}
if( hasEnd && num == 12 )
{
SetCustomToken( DLG_BASE_TOKEN + 13, "End" );
return( TRUE );
}
return( FALSE );
}
int i = _GetDlgFirstResponse( oSpeaker ) + num;
int count = GetDlgResponseCount( oSpeaker );
if( i < count )
{
string response = GetDlgResponse( i, oSpeaker );
SetCustomToken( DLG_BASE_TOKEN + num + 1, response );
return( TRUE );
}
return( FALSE );
}
// Called to clean-up the current conversation related
// resources.
void _CleanupDlg( object oSpeaker )
{
// See if the PC was associated with an item
object oItem = GetLocalObject( oSpeaker, DLG_ITEM );
if( oItem != OBJECT_INVALID )
{
DeleteLocalObject( oItem, DLG_ITEM_CONVERSER );
}
DeleteLocalInt( oSpeaker, DLG_STATE );
DeleteLocalObject( oSpeaker, DLG_RESPONSE_LIST_HOLDER );
DeleteLocalString( oSpeaker, DLG_RESPONSE_LIST );
DeleteLocalString( oSpeaker, DLG_PROMPT );
DeleteLocalString( oSpeaker, DLG_CURRENT_HANDLER );
DeleteLocalInt( oSpeaker, DLG_PAGE_ID );
DeleteLocalString( oSpeaker, DLG_PAGE_ID );
DeleteLocalObject( oSpeaker, DLG_ITEM );
DeleteLocalInt( oSpeaker, DLG_HAS_PREV );
DeleteLocalInt( oSpeaker, DLG_HAS_NEXT );
DeleteLocalInt( oSpeaker, DLG_HAS_END );
DeleteLocalInt( oSpeaker, DLG_START_ENTRY );
}
// Sends the specified dialog event to the specified NPC
// using the current script handler. The selection parameter
// is used for select events. The speaker is provided for
// event specific paramaters to be stored onto.
void _SendDlgEvent( object oSpeaker, int dlgEvent, int selection = -1, object oNPC = OBJECT_SELF )
{
string dlg = GetCurrentDlgHandlerScript();
if( oNPC == oSpeaker )
oNPC = GetLocalObject( oSpeaker, DLG_ITEM );
SetLocalInt( oSpeaker, DLG_EVENT_TYPE, dlgEvent );
SetLocalInt( oSpeaker, DLG_EVENT_SELECTION, selection );
ExecuteScript( dlg, oNPC );
DeleteLocalInt( oSpeaker, DLG_EVENT_TYPE );
DeleteLocalInt( oSpeaker, DLG_EVENT_SELECTION );
}
void _DoDlgSelection( object oSpeaker, int selection, object oNPC = OBJECT_SELF )
{
// Check to see if this is one or our internal events
int first = _GetDlgFirstResponse( oSpeaker );
switch( selection )
{
case 10:
if( _HasDlgNext( oSpeaker ) )
{
// Next page
_SetDlgFirstResponse( oSpeaker, first + 10 );
return;
}
break;
case 11:
if( _HasDlgPrevious( oSpeaker ) )
{
// Previous page
_SetDlgFirstResponse( oSpeaker, first - 10 );
return;
}
break;
case 12:
if( _HasDlgEnd( oSpeaker ) )
{
// End dialog
EndDlg();
return;
}
break;
}
selection += first;
_SendDlgEvent( oSpeaker, DLG_SELECTION, selection, oNPC );
}
// Returns the current conversation state.
int _GetDlgState( object oSpeaker )
{
return( GetLocalInt( oSpeaker, DLG_STATE ) );
}
// Called by the dialog internals to initialize the page
// and possibly the conversation
void _InitializePage( object oSpeaker, object oNPC = OBJECT_SELF )
{
int state = GetLocalInt( oSpeaker, DLG_STATE );
string dlg = GetCurrentDlgHandlerScript();
if( oNPC == oSpeaker )
oNPC = GetLocalObject( oSpeaker, DLG_ITEM );
// See if the NPC has a dialog file defined
if( dlg == "" )
{
// Try to see if they have a default defined
dlg = GetDefaultDlgHandlerScript( oNPC );
SetCurrentDlgHandlerScript( dlg );
state = 0;
}
// If we aren't initialized
if( state == DLG_STATE_INIT )
{
// Then we'll send the conversation init event
_SendDlgEvent( oSpeaker, DLG_INIT, -1, oNPC );
SetLocalInt( oSpeaker, DLG_STATE, DLG_STATE_RUNNING );
}
// Send the page initialization event
_SendDlgEvent( oSpeaker, DLG_PAGE_INIT, -1, oNPC );
}
/*
//I keep this here to uncomment when compiling to test for
//errors that can't be found otherwise. Just ignore it.
void main()
{
}*/