265 lines
11 KiB
Plaintext
265 lines
11 KiB
Plaintext
//:://////////////////////////////////////////////
|
|
//:: Conversation Charactor Creator
|
|
//:: prc_ccc.nss
|
|
//:://////////////////////////////////////////////
|
|
/** @file
|
|
Long description
|
|
|
|
|
|
@author Primogenitor, modified by fluffyamoeba
|
|
@date Created - 2006.09.18
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:://////////////////////////////////////////////
|
|
|
|
// includes
|
|
|
|
#include "ccc_inc_convo"
|
|
#include "prc_inc_spells"
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Constant defintions + functions */
|
|
//////////////////////////////////////////////////
|
|
|
|
// see includes
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Main function */
|
|
//////////////////////////////////////////////////
|
|
|
|
void main()
|
|
{
|
|
object oPC = GetPCSpeaker();
|
|
int bBoot; // used by this script to mark if the PC should be booted
|
|
|
|
if(!GetIsObjectValid(oPC)) // if no valid speaker, then not part of the convo
|
|
{
|
|
// no valid speaker so need to get the PC properly this time
|
|
oPC = GetEnteringObject();
|
|
//oPC = GetLastUsedBy();
|
|
// if called for a NPC, DM or the switch isn't enabled
|
|
if(!GetIsPC(oPC) || GetIsDM(oPC) || !GetPRCSwitch(PRC_CONVOCC_ENABLE))
|
|
return;
|
|
|
|
// check letoscript is setup correctly
|
|
// if letoscript can't find the bic, the convoCC won't work.
|
|
// will boot the PC later if they should go through the convoCC but can't
|
|
// otherwise ignore
|
|
bBoot = DoLetoscriptTest(oPC);
|
|
|
|
// encryption stuff
|
|
/* TODO proper comment */
|
|
string sEncrypt;
|
|
sEncrypt= Encrypt(oPC);
|
|
|
|
// reset
|
|
DeleteLocalString(oPC, "CONVOCC_ENTER_BOOT_MESSAGE");
|
|
int nPCStatus = CONVOCC_ENTER_BOOT_PC;
|
|
if(GetPRCSwitch(PRC_CONVOCC_CUSTOM_ENTER_SCRIPT)) // custom entry script stuff here
|
|
{
|
|
DeleteLocalInt(oPC,"CONVOCC_LAST_STATUS");
|
|
/**
|
|
* The custom script must:
|
|
* - be called "ccc_custom_enter"
|
|
* - set the local int "CONVOCC_LAST_STATUS" on the PC (OBJECT_SELF)
|
|
* - include prc_ccc_const (for the constants the local int can be set to)
|
|
* otherwise the PC will always be booted
|
|
*
|
|
* possible values for CONVOCC_LAST_STATUS:
|
|
* CONVOCC_ENTER_BOOT_PC (causes the PC to get kicked)
|
|
* CONVOCC_ENTER_NEW_PC (causes the PC to go through the convoCC)
|
|
* CONVOCC_ENTER_RETURNING_PC (causes the PC to skip the convoCC)
|
|
*/
|
|
ExecuteScript("ccc_custom_enter", oPC);
|
|
nPCStatus = GetLocalInt(oPC,"CONVOCC_LAST_STATUS");
|
|
DeleteLocalInt(oPC,"CONVOCC_LAST_STATUS");
|
|
}
|
|
else // default handling of whether to send PCs through the convoCC
|
|
{
|
|
// if a new character...
|
|
if((GetPRCSwitch(PRC_CONVOCC_USE_XP_FOR_NEW_CHAR) && GetXP(oPC) == 0)
|
|
|| (!GetPRCSwitch(PRC_CONVOCC_USE_XP_FOR_NEW_CHAR) && GetTag(oPC) != sEncrypt))
|
|
{
|
|
nPCStatus = CONVOCC_ENTER_NEW_PC;
|
|
}
|
|
else // returning PC
|
|
{
|
|
nPCStatus = CONVOCC_ENTER_RETURNING_PC;
|
|
}
|
|
}
|
|
if (DEBUG) { DoDebug("**** nPCStatus: "+ IntToString(nPCStatus));}
|
|
/* Now to deal with some special cases that always override the custom script
|
|
* These only apply if the PC was supposed to be going through the convoCC, ie.
|
|
* where nPCStatus == CONVOCC_ENTER_NEW_PC.
|
|
*/
|
|
if(nPCStatus == CONVOCC_ENTER_NEW_PC)
|
|
{
|
|
if(bBoot) // if singleplayer or letoscript not set up correctly
|
|
nPCStatus = CONVOCC_ENTER_BOOT_PC;
|
|
else if (GetIsObjectValid(GetLocalObject(GetModule(), "ccc_active_pc"))) // next see if someone has already started the convo
|
|
{
|
|
nPCStatus = CONVOCC_ENTER_BOOT_PC;
|
|
SetLocalString(oPC, "CONVOCC_ENTER_BOOT_MESSAGE",
|
|
"The conversation Character Creator is in use, please try later.");
|
|
}
|
|
}
|
|
if (DEBUG) { DoDebug("**** nPCStatus: "+ IntToString(nPCStatus));}
|
|
// end of decision making
|
|
|
|
/* kick the PC */
|
|
if (nPCStatus == CONVOCC_ENTER_BOOT_PC)
|
|
{
|
|
CheckAndBootNicely(oPC);
|
|
return;
|
|
}
|
|
/* new character */
|
|
else if (nPCStatus == CONVOCC_ENTER_NEW_PC)
|
|
{
|
|
// now reserve the conversation slot - only one at a time
|
|
SetLocalObject(GetModule(), "ccc_active_pc", oPC);
|
|
// remove equipped items and clear out inventory
|
|
DoStripPC(oPC);
|
|
//rest them so that they loose cutscene invisible
|
|
//from previous logons
|
|
ForceRest(oPC);
|
|
//Take their Gold
|
|
AssignCommand(oPC,TakeGoldFromCreature(GetGold(oPC),oPC,TRUE));
|
|
//DISABLE FOR DEBUGGING
|
|
if (!DEBUG)
|
|
{
|
|
// start the cutscene
|
|
// off for debugging to see the debug text in the client
|
|
SetCutsceneMode(oPC, TRUE);
|
|
}
|
|
SetCameraMode(oPC, CAMERA_MODE_TOP_DOWN);
|
|
//make sure the PC stays put
|
|
effect eParal = EffectCutsceneImmobilize();
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eParal, oPC, 9999.9);
|
|
//start the ConvoCC conversation
|
|
DelayCommand(10.0, StartDynamicConversation("prc_ccc_main", oPC, FALSE, FALSE, TRUE));
|
|
// sets up the cutscene to the point in the convo at which the player logged out
|
|
DelayCommand(11.0, DoCutscene(oPC, TRUE));
|
|
// mark that stage 1 of the cutscene is set up
|
|
SetLocalInt(oPC, "CutsceneStage", 1);
|
|
SetExecutedScriptReturnValue(X2_EXECUTE_SCRIPT_END);
|
|
}
|
|
/* returning character */
|
|
else if (nPCStatus == CONVOCC_ENTER_RETURNING_PC)
|
|
{
|
|
// if using XP or your own script for new characters, this sets returning characters' tags
|
|
// to encrypted then you can turn off using XP after all characters have logged on.
|
|
if((GetPRCSwitch(PRC_CONVOCC_USE_XP_FOR_NEW_CHAR) || GetPRCSwitch(PRC_CONVOCC_CUSTOM_ENTER_SCRIPT))
|
|
&& GetTag(oPC) != sEncrypt
|
|
&& GetXP(oPC) > 0)
|
|
{
|
|
string sScript = LetoSet("Tag", sEncrypt, "string");
|
|
SetLocalString(oPC, "LetoScript", GetLocalString(oPC, "LetoScript")+sScript);
|
|
}
|
|
SetExecutedScriptReturnValue(X2_EXECUTE_SCRIPT_CONTINUE);
|
|
}
|
|
else /* ooops - should never get here */
|
|
{
|
|
if (DEBUG) { DoDebug("Error: invalid value for var nPCStatus");}
|
|
// kick just in case
|
|
SetLocalString(oPC, "CONVOCC_ENTER_BOOT_MESSAGE", "Error:I'm confused.");
|
|
CheckAndBootNicely(oPC);
|
|
return;
|
|
}
|
|
}
|
|
else // in convo
|
|
{
|
|
/* dynamic convo from here*/
|
|
// double check it's a PC
|
|
if(!GetIsPC(oPC) || GetIsDM(oPC) || !GetPRCSwitch(PRC_CONVOCC_ENABLE))
|
|
return;
|
|
// The stage is used to determine the active conversation node.
|
|
// 0 is the entry node.
|
|
int nStage = GetStage(oPC);
|
|
/* Get the value of the local variable set by the conversation script calling
|
|
* this script. Values:
|
|
* DYNCONV_ABORTED Conversation aborted
|
|
* DYNCONV_EXITED Conversation exited via the exit node
|
|
* DYNCONV_SETUP_STAGE System's reply turn
|
|
* 0 The script was called by prc_onenter
|
|
* Other The user made a choice
|
|
*/
|
|
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
|
|
|
|
if(DEBUG) DoDebug("prc_ccc running.\n"
|
|
+ "oPC = " + DebugObject2Str(oPC) + "\n"
|
|
+ "nValue = " + IntToString(nValue)
|
|
);
|
|
|
|
// Check which of the conversation scripts called the scripts
|
|
if(nValue == 0) // All of them set the DynConv_Var to non-zero value, so something is wrong -> abort
|
|
return;
|
|
|
|
if(nValue == DYNCONV_SETUP_STAGE)
|
|
{
|
|
// Check if this stage is marked as already set up
|
|
// This stops list duplication when scrolling
|
|
if(!GetIsStageSetUp(nStage, oPC))
|
|
{
|
|
// variable named nStage determines the current conversation node
|
|
// this function sets up the text displayed and the response options
|
|
// for the current conversation node
|
|
if(DEBUG)
|
|
{
|
|
DoDebug("prc_ccc: Stage was not already set up");
|
|
DoDebug("Pass to DoHeaderAndChoices(): " + IntToString(nStage));
|
|
}
|
|
// SpawnScriptDebugger();
|
|
DoHeaderAndChoices(nStage);
|
|
if(DEBUG) DoDebug("DoHeaderAndChoices() finished");
|
|
}
|
|
|
|
// Do token setup
|
|
SetupTokens();
|
|
if(DEBUG) ExecuteScript("prc_ccc_debug", oPC);
|
|
}
|
|
// End of conversation cleanup
|
|
else if(nValue == DYNCONV_EXITED)
|
|
{
|
|
if(DEBUG) DoDebug("prc_ccc: Conversation exited");
|
|
// cleanup is done in prc_ccc_make_pc
|
|
// deletes local variables used to create the character
|
|
}
|
|
// Abort conversation cleanup.
|
|
// NOTE: This section is only run when the conversation is aborted
|
|
// while aborting is allowed. When it isn't, the dynconvo infrastructure
|
|
// handles restoring the conversation in a transparent manner
|
|
else if(nValue == DYNCONV_ABORTED)
|
|
{
|
|
// shouldn't reach this stage as aborting isn't allowed
|
|
AssignCommand(oPC, DelayCommand(1.0, CheckAndBoot(oPC)));
|
|
}
|
|
// Handle PC responses
|
|
else
|
|
{
|
|
// variable named nChoice is the value of the player's choice as stored when building the choice list
|
|
// variable named nStage determines the current conversation node
|
|
int nChoice = GetChoice(oPC);
|
|
|
|
// check if the second stage of the cutscene needs setting up
|
|
// note: this is an *ugly hack*
|
|
// basically, if the player has made a choice, we know the area has fully loaded
|
|
// so we can set up the camera facing here
|
|
if (GetLocalInt(oPC, "CutsceneStage") == 1)
|
|
{
|
|
// do the camera stuff
|
|
DoRotatingCamera(oPC);
|
|
// mark that stage 2 of the cutscene is set up
|
|
SetLocalInt(oPC, "CutsceneStage", 2);
|
|
}
|
|
|
|
// get nStage back so SetStage() actually changes the stage
|
|
if(DEBUG) DoDebug("nStage before HandleChoice: " + IntToString(nStage));
|
|
nStage = HandleChoice(nStage, nChoice);
|
|
if(DEBUG) DoDebug("nStage after HandleChoice: " + IntToString(nStage));
|
|
|
|
// Store the stage value. If it has been changed, this clears out the choices
|
|
SetStage(nStage, oPC);
|
|
}
|
|
}
|
|
}
|