Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /////
- //Setting up the prereq checks
- /////
- integer Prereqs = FALSE;
- string PrereqIncoming;
- string PrereqsNone = "No Prereqs Needed";
- string PrereqMessage = "Please show you meet the prerequisites for this quest.";
- /////
- //Setting Up The Quest Objective channels and Listeners
- /////
- integer chanBase;
- string questChanString;
- list questChanList;
- integer questChan;
- integer questChanOffset;
- integer listen_quest;
- /////
- //Setting Up The XP Giver
- /////
- integer objectchanoffset = -1234555; //The number to offset the object channel by
- integer objectchan; //The object channel this object sends to and receives from
- integer listen_object; //The object channel's listener
- string StatItem = "Stat Item, "; //Message to HUD: This is a Stat Aletering message
- string Stat; //Message to HUD: The stat to alter
- string StatAmt; //Message to HUD: The amount to alter the stat by
- key TouchingAvatar; //The UUID of the avatar touching this object
- key ThisObject; //They UUID of this object, in case it's needed
- /////
- //Setting up the Difficulty Checker
- /////
- string DiffCheck = "Difficulty Check"; //Message to HUD: This is a Difficulty Check message
- integer DiffNum; //Message to HUD: The difficulty number
- string DCStat; //Message to HUD: the stat to use for the Difficulty Roll
- string MakeRoll = "Make Roll";
- /////
- //Setting up the Menu Variables
- /////
- list menuButtons; //The list containing the menu buttons
- string Yes = "Yes, Reset"; //The yes button
- string No = "No, Reset"; //The no button
- list menuResetOptions = [Yes, No]; //The menu buttons for the Quest Reset Options
- integer menuChan; //The menu channel
- integer listen_menu; //The listener
- string menuText; //The menu text
- /////
- //The Notecard Reading Setup
- /////
- string notecardName = "Dialog"; //The name of the notecard
- integer notecardLine; //The line of the notecard being referenced for the notecard reading
- key notecardQueryID; //Identifier for the dataserver event
- key notecardKey; //Store the notecard's key, so we don't read it again by accident.
- integer Results = 64; //The number of search results to return
- list DiagOptions; //The Dialog Options List
- string Start = "#Start"; //The start of the dialog chain
- string End = "#End"; //The end of the dialog chain
- string DiagComp = "Dialog Complete"; //Dialog Complete Caption
- string ItemReward = "#Item"; //The LineID called ItemReward
- string NoReward = "No Reward"; //What to put if the "item reward" is nothing, and instead just used to alter stats
- string NextNotecard = "#NextNotecard"; //The LineID called NextNotecard
- string LineID; //The line ID
- string Caption; //The line Caption
- integer numOptions; //The Number of Options
- string Options; //The Options
- string NextID; //The next set of line IDs
- list NextIDList; //The list of the next line IDs
- integer index; //The index of the menu button chosen
- string FindID; //The next ID to find
- integer LineNumber; //The line number of the next ID
- string OptionString; //The dialog options in string format
- list OptionList; //The dialog options in list format
- string QuestName = "#QuestName"; //The name of the Quest or Chain of Quests
- string QuestNameData; //For tracking purposes, this variable is associated with the name of the Quest
- //The original intent is to take down the line number so that the NPC remembers where the Player left off
- //I might still use this, so keeping it
- string QuestObjective = "#QuestObjective"; //The Objective of the Quest
- string QuestComplete = "Quest Objective Complete"; //The status of the Quest Objective: the Quest is complete
- string QuestFailed = "Quest Obbective Failed"; //The status of the Quest is Failed
- string Objective; //The Quest Objective received from the Quest Item
- integer ObjectiveNumber; //The Objective Number value the Quest Item is worth
- string QuestPassFail; //The notice from the Quest Item whether reaching 0 in Current Count is a Pass or Fail
- integer QuestStartingNumber; //In case of quest failure, the script can retrieve the Quest Starting Number to reset the quest status
- string QuestPasses = "Pass"; //The message from the Quest Item letting the Quest Controller know Current Count reaching 0 is a Pass
- string QuestFails = "Fail"; //The message from the Quest Item letting the Quest Controller know Current Count reaching 0 is a Fail
- string QuestID; //The Quest Objective taken from the LineID; just separated out the # in front of it
- integer QuestIDNum = -999; //This identifies the line that has the Quest Objective in the LineID
- string QuestUpdate1 = "Your progress in Quest Objective "; //The message to update progress
- string QuestUpdate2 = " is: "; //The second part of the message to update progress
- string QuestUpdate3 = " is now complete!"; //Informing the Player the Quest Objective is now complete
- string QuestUpdate4 = " has failed.";
- string TaskReminder; //The task reminder message the NPC gives when the Player hasn't completed the task
- string CompleteQuestOption = "Complete Quest"; //The Options Label to look for when processing the Quest Objectives
- /////
- //Misc Variables
- /////
- string Greeting; //The greeting the NPC object gives the Player
- string Congrats; //The congratulations message the NPC object gives the Player upong completing the quest
- string NextQuest; //The message informming the Player that the NPC object needs to be touched again due to a new line in the quest
- string ResetQuest = "Would you like to replay this adventure?";
- string QuestResetMessage = "Reset Quest";
- string PlayerQuestSpot;
- /////
- //Channel Setup - Unique Channel for the RP System
- /////
- integer Key2Chan(key ID)
- {
- return 0x80000000 | (integer)("0x"+(string)ID);
- }
- /////
- //Read Notecard
- /////
- ReadNotecard()
- {
- if (llGetInventoryKey(notecardName) == NULL_KEY) //Check if the notecard exists in inventory and has been saved since it's creation (newly created notecards that are yet to be saved are assigned NULL_KEY).
- {
- llOwnerSay( "Notecard '" + notecardName + "' is missing, unwritten, or not full permission."); //Notify user.
- return; //Don't do anything else.
- }
- else if (llGetInventoryKey(notecardName) == notecardKey) //This notecard has already been read - call to read was made in error, so don't do anything. (Notecards are assigned a new key each time they are saved.)
- {
- return;
- }
- llOwnerSay("Began reading notecard: " + notecardName); //Notify user that read has started.
- llLinksetDataReset(); //Clear the Linkset Data
- notecardLine = 0; //Make sure notecardLine starts at 0
- notecardQueryID = llGetNotecardLine(notecardName, notecardLine); //Get the notecard line
- }
- /////
- //Linkset Data Dump
- /////
- lsdDump()
- {
- integer item; //The Linkset Data Key Number (The Data Key is the name of the Data; The Data Key Value is the string value assigned to that Data Name; Basically, "What does this name represent?")
- integer items = llLinksetDataCountKeys(); //The number of unique Data Keys in the Linkset Data
- for (item = 0; item < items; item++) //For each Data Key, do the following
- {
- string k = llDumpList2String(llLinksetDataListKeys(item,1),","); //Make the Linkset Data Key into a string
- string v = llLinksetDataRead(k); //Read the Linkset Data Key's Value
- llOwnerSay((string)["Dump (", 1+item, "/", items, ") >> ", k, "=", v]); //Say in chat the Linkset Data Name and its Value
- }
- }
- /////
- //Get Stat's Value - Integer
- /////
- integer get(string stat)
- {
- return (integer)llLinksetDataRead(stat); //Get the Value of the Linkset Data Key and return it as an integer (The Data Key is the name of the Data; The Data Key Value is the string value assigned to that Data Name; Basically, "What does this name represent?")
- }
- /////
- //Get Stat's Value - String
- /////
- string getstring(string stat)
- {
- return llLinksetDataRead(stat); //Get the Value of the Linkset Data Key and return it as a string (The Data Key is the name of the Data; The Data Key Value is the string value assigned to that Data Name; Basically, "What does this name represent?")
- }
- /////
- //Set Stat's Value - Integer
- /////
- set(string stat, integer value)
- {
- llLinksetDataWrite(stat, (string)value); //Write the new value in for the Linkset Data Key; here, the expected data is an integer (The Data Key is the name of the Data; The Data Key Value is the string value assigned to that Data Name; Basically, "What does this name represent?")
- }
- /////
- //Set Stat's Value - String
- /////
- setstring(string stat, string value)
- {
- llLinksetDataWrite(stat, value); //Write the new value in for the Linkset Data Key; here, the expected data is already a string (The Data Key is the name of the Data; The Data Key Value is the string value assigned to that Data Name; Basically, "What does this name represent?")
- }
- /////
- //Item Collection Counter
- /////
- ItemCollection(string questObjective, integer Count, string PassFail) //The two values are the name of the Quest Objective and how mych to reduce the total Quest Count Number by
- {
- integer CurrentCount = (integer)llLinksetDataRead(questObjective); //Get the current count of the Quest Objective from the LinksetData
- CurrentCount -= Count; //Subtract the Count from the Current Count
- set(questObjective, CurrentCount); //Set the Current Count to the Quest Objective
- if (CurrentCount > 0) //When the Current Count is greater than zero, display the message
- {
- llSay (0, QuestUpdate1 + questObjective + QuestUpdate2 + (string)CurrentCount);
- }
- else //When the Current Count is 0 or less, set to zero then display the messages
- {
- CurrentCount = 0;
- llSay (0, QuestUpdate1 + questObjective + QuestUpdate2 + (string)CurrentCount);
- if (PassFail == QuestPasses)
- {
- setstring(questObjective, QuestComplete); //We're marking the Quest Objective as complete
- llSay (0, questObjective + QuestUpdate3);
- }
- else
- {
- setstring(questObjective, QuestFailed); //We're marking the Quest Objective as failed
- llSay (0, questObjective + QuestUpdate4);
- }
- }
- }
- /////
- //The Branching Dialog Function
- /////
- list FindingDiagOptions (string messagereceived)
- {
- NextIDList = llParseString2List(NextID, [","], [""]); //Make the string of next IDs into a list we can work with
- index = llListFindList(menuButtons, [messagereceived]); //The index is set to be the index of the menu button selected
- //The message is the menu button the Player selected
- if (!~index) //The index = -1 when the menuButtons = "Make Roll"; here, we're looking for the Pass/Fail message
- {
- index = llListFindList(NextIDList, [messagereceived]); //Adjusting for the Pass/Fail message to get the proper index
- }
- FindID = llList2String(NextIDList, index); //The NextID list is the same length as the Options List and should have one to one correspondence with that list
- //The exception is the "Make Roll" lines in the notecard, as they only have "Make Roll" in the Options List, while the NextID List has two items: Pass and Fail
- DiagOptions = llFindNotecardTextSync( notecardName, FindID, 0, Results, [] ); //Search the notecard for the text of the Next ID
- return DiagOptions; //Return the DiagOptions list
- }
- TheBranchingDialogFunction()
- {
- //Find where the NextID is being used as the LineID
- integer find;
- integer found = llGetListLength(DiagOptions);
- integer line;
- for (find = 0; find < found; find += 3) //stride of 3
- //So, DiagOptions is a list consisting of row, column, length for each instance of the string found
- //So, we want to search the list in groups of three
- {
- if (llList2Integer(DiagOptions, 1+find) == 0) //When we find the entry saying the column is at 0 (the beginning of the line), we've found the line we're looking for
- {
- line = llList2Integer(DiagOptions, find); //The index of the position of the desired column position in the DiagOptions List
- }
- }
- OptionString = llGetNotecardLineSync(notecardName,line); //Go to the line in the notecard where the NextID is the LineID
- //These are the new set of Dialog Options (not to be confused with DiagOptions)
- //This is a string, at first
- OptionList = llParseString2List(OptionString, ["|"], [""]); //The Dialog Options are parsed into a list, with "|" as the separator
- LineID = llList2String(OptionList, 0); //The Line ID is the first item in this list
- Caption = llList2String(OptionList, 1); //The Dialog Caption is the second item on this list
- numOptions = llList2Integer(OptionList, 2); //The number of options is the third item on this lsit
- Options = llList2String(OptionList, 3); //The actual options are the fourth item on this list
- NextID = llList2String(OptionList, 4); //The set of next IDs are the fifth item on this list
- menuButtons = llParseString2List(Options, [","], [""]); //The Options are parsed into a list used for the Dialog Menu Buttons
- setTask(TouchingAvatar, notecardName, LineID); //Recording where the Player is at in the dialog
- }
- /////
- //Tracking Player Progress in the Dialog
- /////
- string questID (key Player, string Quest) //Player = Touching Avatar's UUID, Quest = Notecard Player is on
- {
- key Creator = llGetInventoryCreator(notecardName);
- return llList2CSV([Player, Creator, Quest]);
- }
- string getQuest (key Player)
- {
- return llLinksetDataRead(Player);
- }
- integer setQuest (key Player, string Quest)
- {
- return llLinksetDataWrite(Player, Quest);
- }
- string getTask (key Player, string Quest)
- {
- return llLinksetDataRead(questID(Player, Quest));
- }
- integer setTask(key Player, string Quest, string Place) //Place = LineID that Player is on
- {
- return llLinksetDataWrite(questID(Player, Quest), Place);
- }
- /////
- //The Main Script
- /////
- default
- {
- //If the inventory or owner changes, reset the script
- changed(integer change)
- {
- if (change & (CHANGED_INVENTORY | CHANGED_OWNER))
- {
- llResetScript();
- }
- }
- //The initial setup
- state_entry()
- {
- chanBase = Key2Chan(llGetOwner());
- ReadNotecard();
- //llGetNumberOfNotecardLines(notecardName); //Put the notecard into the cache
- PrereqIncoming = llGetNotecardLineSync(notecardName, 0); //The Expected Prereq Quest to have completed
- menuText = llGetNotecardLineSync(notecardName, 1); //The menu text is the first line of the notecard
- Greeting = llGetNotecardLineSync(notecardName, 2); //The greeting is the second line of the notecard
- Congrats = llGetNotecardLineSync(notecardName, 3); //The congratulatory message is the third line of the notecard
- NextQuest = llGetNotecardLineSync(notecardName, 4); //The next quest notice is the fourth line of the notecard
- TaskReminder = llGetNotecardLineSync(notecardName, 5); //The text used to remind the player of the quest objective
- questChanString = llGetNotecardLineSync(notecardName, 6); //Getting the line in the notecard with the quest channel offset
- questChanList = llParseString2List(questChanString, ["|"], [""]); //Setting up the string as a list to get the channel offset
- questChanOffset = llList2Integer(questChanList, 0); //Extracting the channel offset from the list
- menuChan = (integer)(llFrand(999999.0) * -1); // This just comes up with some big random negative number to use as the channel for the menu to work on
- objectchan = chanBase + objectchanoffset; //Setting up the object channel
- questChan = chanBase + questChanOffset; //Setting the quest item channel
- llListenRemove(listen_menu); //Removing the listener
- llListenRemove(listen_object); //Removing the listener
- llListenRemove(listen_quest); //Removing the listener
- listen_menu = llListen(menuChan,"","",""); //The Menu Listener
- listen_object = llListen(objectchan,"","",""); //The Object Channel Listener
- listen_quest = llListen(questChan,"","","");
- ThisObject = llGetKey(); //Getting the key of the NPC object, just in case
- llSay(0, Greeting); //The greeting to the Player
- }
- //The Branching Dialog
- listen(integer channel, string name, key target, string message)
- {
- if (channel == menuChan) //Listen for activity on the menu channel
- {
- if (message == Yes || message == No)
- {
- if (message == Yes)
- {
- llRegionSay(objectchan, llList2CSV([QuestResetMessage, QuestNameData]));
- llResetScript();
- }
- }
- else
- {
- FindingDiagOptions(message); //Use the message received to find the DiagOptions List
- TheBranchingDialogFunction(); //Go to the main Branching Dialog Function
- PlayerQuestSpot = getTask(TouchingAvatar, notecardName);
- if (PlayerQuestSpot == LineID)
- {
- if (Options == MakeRoll) //MakeRoll and its associated string are a fixed command that the player needs to use in their notecard when writing difficulty checks
- //When the Options is MakeRoll, then we need to send out the DC data to the HUD
- {
- DiffNum = numOptions; //Here, the numOptions slot is being used to declare the Difficulty Number the Player needs to meet
- DCStat = message; //Here, the message should be set to the skill the Player chose to use for the DC
- llRegionSayTo(TouchingAvatar, objectchan, llList2CSV([DiffCheck, DiffNum, DCStat, NextID, menuChan])); //Speak to the touching avatar's HUD
- //We're giving the HUD the expected DC message
- }
- else if (LineID == ItemReward) //Here, ItemReward and its associated string are a fixed command that the player needs to use in order to give the player an item and Fate Points (TSOAT's version of XP)
- {
- if (Caption != NoReward)
- {
- llGiveInventory(TouchingAvatar, Caption); //Here, the Caption in this line identifies the object to be delivered to the Player
- }
- Stat = Options + ", ";
- StatAmt = (string)numOptions + ", "; //Here, the numOptions is acting as the Fate Points number, or XP in generic RPG terms
- llRegionSayTo(TouchingAvatar, objectchan, (StatItem + Stat + StatAmt + (string)ThisObject)); //Speak to the touching avatar's HUD
- //We're giving the HUD the expected Alter Stats message
- llSleep(1.0); //Sleep for a moment to give the Player time to receive the item
- llSay(0, Congrats); //Deliver the congratulations message
- Caption = DiagComp; //Set the Caption the the DiagComp message so the script knows we've come to the end of the dialog chain
- }
- else if (Caption == DiagComp) //If we've come to the end of the dialog chain, congratulate the player
- {
- llSay(0, Congrats);
- }
- else if (LineID == NextNotecard) //Here, NextNotecard and its associated string are a fixed command that the player needs to use in order to switch to the next notecard in the inventory; this can be useful for complex storylines, etc.
- {
- notecardName = NextID; //Here, the NextID is the name of the notecard we're switching to
- llGetNumberOfNotecardLines(notecardName); //Put the notecard into the cache
- llSay(0, NextQuest); //Inform the Player to touch the NPC to switch to the next part of the Quest
- }
- else if (numOptions == QuestIDNum)
- {
- list ParsedLineID = llParseString2List(LineID, ["#"],[""]);
- QuestID = llList2String(ParsedLineID, 0);
- llSay(0, Caption);
- llDialog(TouchingAvatar,menuText,menuButtons,menuChan);
- }
- else if (Options == CompleteQuestOption)
- {
- string CompletionCheck = llLinksetDataRead(Objective);
- if (CompletionCheck == QuestComplete)
- {
- NextIDList = llParseString2List(NextID, [","], [""]); //Make the string of next IDs into a list we can work with
- message = llList2String(NextIDList, 1);
- FindingDiagOptions(message); //Use the message received to find the DiagOptions List
- TheBranchingDialogFunction(); //Go to the main Branching Dialog Function
- }
- else if (CompletionCheck == QuestFailed)
- {
- set(QuestID, QuestStartingNumber);
- NextIDList = llParseString2List(NextID, [","], [""]); //Make the string of next IDs into a list we can work with
- message = llList2String(NextIDList, 2);
- FindingDiagOptions(message); //Use the message received to find the DiagOptions List
- TheBranchingDialogFunction(); //Go to the main Branching Dialog Function
- }
- else
- {
- llSay (0, TaskReminder + " ::: " + QuestID + " ::: " + (string)get(QuestID));
- NextIDList = llParseString2List(NextID, [","], [""]); //Make the string of next IDs into a list we can work with
- message = llList2String(NextIDList, 0);
- FindingDiagOptions(message); //Use the message received to find the DiagOptions List
- TheBranchingDialogFunction(); //Go to the main Branching Dialog Function
- }
- }
- else //Otherwise, start the next set of dialog in the chain
- {
- llSay(0, Caption);
- llDialog(TouchingAvatar,menuText,menuButtons,menuChan);
- }
- }
- else
- {
- FindingDiagOptions(PlayerQuestSpot); //Use the message received to find the DiagOptions List
- TheBranchingDialogFunction(); //Go to the main Branching Dialog Function
- }
- }
- }
- if (channel == questChan) //Listen for messages from Quest Objects
- {
- list ItemMessage = llCSV2List(message); //Parsing the message into a list
- Objective = llList2String(ItemMessage, 0); //The first datum in the list is the quest objective
- ObjectiveNumber = llList2Integer(ItemMessage, 1); //The second datum in the list is the number to decrease the Current Count by
- QuestPassFail = llList2String(ItemMessage, 2); //The third datum in the list is whether or not the quest passes or fails upon reaching Current Count 0
- QuestStartingNumber = llList2Integer(ItemMessage, 3); //The fourth datum in the list is the Starting Number of the Quest Objective, in case it gets lost due to Quest Failure
- ItemCollection(Objective, ObjectiveNumber, QuestPassFail); //Go to the Item Collection function in order to figure out Player's Progress
- }
- if (channel == objectchan)
- {
- if (message == PrereqIncoming)
- {
- Prereqs = TRUE;
- }
- else
- {
- list ResetMessageList = llCSV2List(message);
- string ResetMessageMain = llList2String(ResetMessageList, 0);
- string NameOfQuest = llList2String(ResetMessageList, 1);
- if (ResetMessageMain == QuestResetMessage)
- {
- if (NameOfQuest == QuestNameData)
- {
- llResetScript();
- }
- }
- }
- }
- }
- //Starting the NPC dialog
- touch_start(integer total_number)
- {
- TouchingAvatar = llDetectedKey(0); //Getting the key of the avatar that touches the NPC object
- setTask(TouchingAvatar, notecardName, LineID);
- if (Caption == DiagComp) //If the dialog comes to the Dialog completion message, display the congrats message
- {
- llSay(0, Congrats + " " + ResetQuest);
- llDialog(TouchingAvatar,menuText,menuResetOptions,menuChan);
- }
- else if (Prereqs == TRUE || PrereqIncoming == PrereqsNone)
- {
- llSay(0, Caption); //Display the next Dialog Caption
- llDialog(TouchingAvatar,menuText,menuButtons,menuChan); //Open up the dialog menu
- }
- else
- {
- llSay(0, PrereqMessage);
- }
- }
- //Starting the Dialog Chain
- dataserver(key i, string n)
- {
- if (i == notecardQueryID)
- {
- while (n != EOF && n != NAK) // Is this the end of file (EOF), or a call without cache (NAK)? (Or just data?) If not, do the following
- {
- list input = llParseString2List(n, ["|"], [""]); //Make the notecard line into a list, with the "|" as the separator
- string Type = llList2String(input, 0); //The first datum in the list identifies the Type of item it is; we're looking for quest name or quest objective
- string Name = llList2String(input, 1); //The second datum in the list identifies the name of the quest or quest objective
- string Number = llList2String(input, 2); //The third datum in the list is the number of items that need to be collected for the quest objective; for the quest name, it could be the number it is in the quest chain
- if (Type == QuestName || Type == QuestObjective) //If the Type is either the quest name or the quest objective, then write the data to LinksetData
- {
- llLinksetDataWrite(Name,Number);
- if (Type == QuestName)
- {
- QuestNameData = Name;
- }
- }
- n = llGetNotecardLineSync(notecardName, ++notecardLine); // message = new data, or NAK. NAK means quit the while and go slow. We want to slow down if it's a call without a cache
- }
- if (n == NAK) // We got a line, but its not cached, ask for next line slow way.
- {
- i = llGetNotecardLine(notecardName, notecardLine); // ask for next line, not sync
- }
- if (n == EOF) // Card is finished loading
- {
- i = "read"; // just for checking later
- llOwnerSay("Notecard read"); //Announce the notecard was read
- lsdDump(); //Dump the LinksetData into OwnerSay chat to make sure we got it
- llOwnerSay(QuestNameData); //Confirm the name of the quest
- }
- }
- DiagOptions = llFindNotecardTextSync( notecardName, Start, 0, Results, [] ); //Find the text in the notecard that starts the dialog chain
- TheBranchingDialogFunction(); //Use the Branching Dialog Function to do the rest
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement