LUA Quest Information

Discussions on development of both the EQ2Emulator LUA Script Engine and Script specifications

Moderator: Team Members

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

LUA Quest Information

Post by LethalEncounter » Sun Aug 03, 2008 11:48 am

I have completed the initial revision of quests and it will be hitting the public SVN server tomorrow. The system as it is right now works pretty good, but I haven't had a chance to add in certain things that I need to add like saving player progress and such. I'll be adding those shortly, but the system is in a working state so I can release what I have done so far.
Database Tables:

Code: Select all

quests
id, lua_script
This table serves as an index to the quest system.  To create a new quest, you must add it to this table.  NOTE: Unlike the previous LUA scripts, you must specify the path to the script as well.  If the script is called KillCrabs.lua in the Quests directory, you would need to put Quests\KillCrabs.lua in the lua_script field.  This is as design so that you can organize quests however you want.
character_quests
id, char_id, quest_id, completed_date
This table holds both current and completed quests.  Quests that have not been completed yet will have a null in the completed_date field.
character_quest_progress
id, char_id, quest_id, step_id, progress
This table is used to keep track of character quest progress.
I decided to put the conversation stuff in SpawnScripts rather than the database as it was getting very complicated very fast. First, I have included an example of the Spawn Script that is used to control the conversation with the NPC. The script below is called Murrar Shar.lua in the SpawnScript directory:

Code: Select all

function spawn(NPC)
	ProvidesQuest(NPC, 1)
end
function hailed(NPC, Spawn)
	FaceTarget(NPC, Spawn)
	conversation = CreateConversation()
	if HasQuest(Spawn, 1) then
		AddConversationOption(conversation, "No problem")
		StartConversation(conversation, NPC, Spawn, "Hello again " .. GetName(Spawn) .. ".  Thank you for accepting my task.")	
	else 
		if HasCompletedQuest(Spawn, 1) then
			AddConversationOption(conversation, "Anytime")
			StartConversation(conversation, NPC, Spawn, "Hello again " .. GetName(Spawn) .. ".  Thank you for killing those crabs.")	
		else
			AddConversationOption(conversation, "Why can't you kill them?", "KillThemYourself")
			AddConversationOption(conversation, "Why should I help you?", "WhyHelpYou")
			StartConversation(conversation, NPC, Spawn, "Greetings " .. GetName(Spawn) .. "!  Thank you for coming.  Could you please kill some of the crabs on the shore for me?  I haven't liked them ever since I was pinched as a child.")
		end
	end
end
function KillThemYourself(NPC, Spawn)
	conversation = CreateConversation()	
	AddConversationOption(conversation, "A dragon?  Right.... Anyways, I want a good pair of leggings for this favor.", "GiveMeQuest")
	AddConversationOption(conversation, "I'll need 12 bottles of Rum, 3 pints of Ale, and 12 gold pieces.  I'm not risking my life for nothing!", "TooGreedy")
	StartConversation(conversation, NPC, Spawn, "I could kill them myself, but my sword was recently damaged while I was battling a dragon.")
end
function TooGreedy(NPC, Spawn)
	conversation = CreateConversation()
	AddConversationOption(conversation, "Have Fun.")	
	StartConversation(conversation, NPC, Spawn, "Forget it, you are too greedy.  I'll get another adventurer to do it for me.")
	Emote(NPC, " makes a rude gesture at you.", Spawn)
end
function GiveMeQuest(NPC, Spawn)
	OfferQuest(NPC, Spawn, 1)
	conversation = CreateConversation()
	AddConversationOption(conversation, "Bye")
	StartConversation(conversation, NPC, Spawn, "Well you drive a hard bargain, but very well.  I agree to your terms.")
end
function WhyHelpYou(NPC, Spawn)
	conversation = CreateConversation()
	AddConversationOption(conversation, "Give me some coins and a some of those leggings the merchant is selling.", "GiveMeQuest")
	AddConversationOption(conversation, "Hmm, how much do you have?  I don't know if you have enough to pay me what I want...", "TooGreedy")
	StartConversation(conversation, NPC, Spawn, "I will pay you if you are that greedy...")
end
I have tried to make these as simple as possible while still providing the flexibility necessary. Additional information:

Code: Select all

ProvidesQuest(NPC, Quest ID) - Tells the system that this NPC offers the quest so that it will check the spells prereqs and if it passes, will display the quest icon over the NPC's head.
conversation = CreateConversation() - Used to create a new Conversation.  This is necessary before you can  them.
AddConversationOption(Conversation, Text option, Function) - The given function is called when the user selects this text option.
StartConversation(Conversation, NPC, Spawn, Text) - This initiates the conversation and displays what the NPC says (text) and the options that were added using the AddConversationOption function.
OfferQuest(NPC, Spawn, Quest ID) - Offers the quest to the Spawn (Player).
Below is the actual Quest file(called KillCrabs.lua in the Quests directory):

Code: Select all

--[[
	This is the EQ2Emu example LUA Quest.
	These functions are shared, so don't save any character data in them.
	If you have any questions be sure to read the Quest Functions.txt in the Quests directory or the wiki site location on the eq2emulator.net website.
--]]
function Init(Quest)
	RegisterQuest(Quest, "Kill Crabs", "Hallmark", "Queen's Colony", 1, "Murrar Shar is deathly afraid of crabs and wants you to kill some of them for him.")
	AddQuestRewardItem(Quest, 1001)
	
	AddQuestRewardCoin(Quest, 78)
	SetQuestRewardExp(Quest, 200)
	SetQuestPrereqLevel(Quest, 1)
		
	AddQuestStepKill(Quest, 1, "Kill 5 of the crabs on the nearby shore", 5, "Kill Crabs for Murrar Shar", 28, 546, 568, 569)
	AddQuestStepCompleteAction(Quest, 1, "KilledAllCrabs")
	SetCompletedDescription(Quest, "This is the description that is displayed when the quest is completed and shown in the completed quest list.")
end
function Accepted(Quest, QuestGiver, Player)
	if QuestGiver ~= nil then
		if GetDistance(Player, QuestGiver) < 30 then
			FaceTarget(QuestGiver, Player)
			Say(QuestGiver, "Thank you for accepting this task " .. GetName(Player) .. ".  Please return to me when you have completed it.")
			Emote(QuestGiver, " thanks you warmly.", Player)
		end
	end
end
function Declined(Quest, QuestGiver, Player)
	if QuestGiver ~= nil then
		if GetDistance(Player, QuestGiver) < 30 then
			FaceTarget(QuestGiver, Player)
			Say(QuestGiver, "If you change your mind " .. GetName(Player) .. ", you know where to find me.")
			Emote(QuestGiver, " glares at you.", Player)
		end
	end
end
function KilledAllCrabs(Quest, QuestGiver, Player)
	UpdateQuestStepDescription(Quest, 1, "I killed the crabs as Murrar requested.")
	AddQuestStepChat(Quest, 2, "I need to speak with Murrar Shar to obtain my reward.", "", 547)
	AddQuestStepCompleteAction(Quest, 2, "Completed")
end
function Completed(Quest, QuestGiver, Player)
	UpdateQuestStepDescription(Quest, 1, "I spoke to Murrar Shar")
	UpdateQuestDescription(Quest, "I killed some of the crabs on the beach for Murrar Shar.")
	GiveQuestReward(Quest, Player)
end
The contents of Quest Functions.txt:

Code: Select all

The following LUA functions are used in creating/using Quests:
Note that the first parameter is ALWAYS Quest.  See KillCrabs.lua for a working example of these functions.
REQUIRED FUNCTIONS (placed in an init() function):
RegisterQuest(Quest, Quest Name, Quest Type, Quest Zone, Quest level, Description)
Optional Functions (mainly used in init() function):
SetQuestPrereqLevel(Quest, Level) 
NOTE: Level required to be given the quest
		
AddQuestPrereqQuest(Quest, Quest ID) 
NOTE: Quest that must be completed before this quest can be given
AddQuestPrereqItem(Quest, Item ID, Quantity)
NOTE: Quantity is optional and defaults to 1
Item that the player must have to get the quest
AddQuestPrereqFaction(Quest, Faction ID, Faction Amount Lower, Faction Amount Upper) 
NOTE: not currently used but here for when it is completed
Quest is offered when the character's faction is between the Faction Amount Lower and Faction Amount Upper (if Faction Amount Upper is used, otherwise faction is >= Faction Amount Lower)
AddQuestRewardItem(Quest, Item ID, Quantity)
NOTE: Quantity is optional and defaults to 1
	
AddQuestRewardCoin(Quest, Copper, Silver, Gold, Plat) 
NOTE: all parameters but copper are optional
AddQuestRewardFaction(Quest, Faction ID, Amount) 
NOTE: not currently used but here for when it is completed
SetQuestRewardStatus(Quest, Amount) 
NOTE: not currently used but here for when it is completed
SetQuestRewardComment(Quest, Text)
SetQuestRewardExp(Quest, Amount)
AddQuestStepKill(Quest, Step ID, Description, Quantity, TaskGroupText, NPC ID(s)) 
NOTE: ID is a unique number that you want to use for this step.  It is used later to track player progress. Each quest can use whichever IDs you want as long as the ID is not repeated in the same quest.
TaskGroupText is optional, but if used this Quest Step will be a bullet underneath the TaskGroup created with the TaskGroupText.  
If you dont want to use TaskGroupText use an empty string in the field (ie "")
You can have multiple bullets under the same TaskGroup by using the same TaskGroupText in multiple addQuestStepKill function calls.
AddQuestStepChat(Quest, Step ID, Description, TaskGroupText, NPC ID(s)) 
	
AddQuestStepObtainItem(Quest, Step ID, Description, Quantity, TaskGroupText, Item ID(s))
AddQuestStepLocation(Quest, Step ID, Description, X, Y, Z, MaxVariation, TaskGroupText)
NOTE: MaxVariation is the distance the player can be from the location and still get credit
AddQuestStepCompleteAction(Quest, Step ID, Function Name)
NOTE: LUA Function that is called when this step is completed.
SetCompletedDescription(Quest, Description)
NOTE: Description that is used after a quest has been completed.
UpdateQuestStepDescription(Quest, Step ID, Description)
function Accepted(Quest, QuestGiver, Player)
NOTE: This function is called when a player accepts the quest
function Declined(Quest, QuestGiver, Player)
NOTE: This function is called when a player declines the quest
Screenshots of this quest in action:
http://eq2emulator.net/ScreenShots/QuestSystem1.jpg
http://eq2emulator.net/ScreenShots/QuestSystem2.jpg
http://eq2emulator.net/ScreenShots/QuestSystem3.jpg
http://eq2emulator.net/ScreenShots/QuestSystem4.jpg
http://eq2emulator.net/ScreenShots/QuestSystem5.jpg
http://eq2emulator.net/ScreenShots/QuestSystem6.jpg
http://eq2emulator.net/ScreenShots/QuestSystem7.jpg
http://eq2emulator.net/ScreenShots/QuestSystem8.jpg
http://eq2emulator.net/ScreenShots/QuestSystem9.jpg
If you have any questions let me know.

User avatar
Zcoretri
Team Member
Posts: 1642
Joined: Fri Jul 27, 2007 12:55 pm
Location: SoCal

Post by Zcoretri » Sun Aug 03, 2008 11:57 am

OMFG! very nice LE. Can't wait to play with this :D

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Post by LethalEncounter » Sun Aug 03, 2008 12:09 pm

Right now the quests are linear (you have to add in a step to talk to the quest giver if you want them to complete the quest there). I plan on adding a LUA function that will be called automatically when a quest is completed instead of the way it is handled now. Other than that there are a few bugs I am working on. If you have any suggestions please let me know.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: LUA Quest Information

Post by John Adams » Sun Aug 03, 2008 12:13 pm

LethalEncounter wrote:If you have any questions let me know.
Silly, silly man... you're just askin for it now!
Wow this is an exciting step in our progress. There is so much work to do now outside the source code, we'll be busy for months. :D
Thank you again for your efforts.

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Re: LUA Quest Information

Post by LethalEncounter » Sun Aug 03, 2008 12:31 pm

John Adams wrote:
LethalEncounter wrote:If you have any questions let me know.
Silly, silly man... you're just askin for it now!
Wow this is an exciting step in our progress. There is so much work to do now outside the source code, we'll be busy for months. :D
Thank you again for your efforts.
heh, bring it on! I think I have explained every aspect of the system so I don't anticipate any easy questions :P
BTW I went ahead and uploaded it to the public SVN server (as well as uploaded a new compiled .exe).

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Post by John Adams » Sun Aug 03, 2008 12:43 pm

Hell, I already updated and am testing it! The only thing I see off right now is the private SVN compile wants opcodes.
Opcode OP_QuestReward is missing from opcode configuration.
But the dialog with Murrar Shar had my laughing my ass off. That's awesome.
Murrar Shar makes a rude gesture at you.

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Post by LethalEncounter » Sun Aug 03, 2008 12:47 pm

Oops, update now. I added the new opcodes to the wrong table.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Post by John Adams » Sun Aug 03, 2008 12:55 pm

I might have missed a step, so I am re-tracing just to be sure... but after accepting the quest, I see nothing in the character_quests or progress tables. I'll check it out again, and once this one works I'll set it up on my public server for others. :)
I needed a diversion from the editors anyway! (AD&D <-- yes!)

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Post by LethalEncounter » Sun Aug 03, 2008 12:57 pm

Read the first couple of sentences in the very first post :P
I am currently working on saving the progress. I haven't gotten it completed yet, but I figured I would release what I had so that you guys can help me find other problems or design issues.

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Post by LethalEncounter » Sun Aug 03, 2008 12:59 pm

Oh and before you ask, /reload quests does NOT currently work. That one is going to been tricky to do since all character quests will have to be reloaded as well.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Post by John Adams » Sun Aug 03, 2008 1:12 pm

Haha see? Ok, I will shut the hell up then. :)
But hey, the conversation branching looks awesome!

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Post by LethalEncounter » Sun Aug 03, 2008 1:21 pm

You should have seen it before I switched over to LUA scripting. I had it in the database in two separate tables and it was utterly confusing as to what was going on. The lua scripting of those should make it relatively simple.

User avatar
Zcoretri
Team Member
Posts: 1642
Joined: Fri Jul 27, 2007 12:55 pm
Location: SoCal

Post by Zcoretri » Sun Aug 03, 2008 4:07 pm

John Adams wrote:... but after accepting the quest, I see nothing in the character_quests...
Is the quest at-least supposed to be in your journal after accepting it? or is that not in yet (your screenies show the quest is in the quest journal) or did you hard code that for display purposes.

LethalEncounter
Team: Zombie
Posts: 2717
Joined: Wed Jul 25, 2007 10:10 pm

Post by LethalEncounter » Sun Aug 03, 2008 5:22 pm

It should be in your quest journal. What client version are you using? The opcodes might be incorrect for your version. I only tested with the latest version.

User avatar
Zcoretri
Team Member
Posts: 1642
Joined: Fri Jul 27, 2007 12:55 pm
Location: SoCal

Post by Zcoretri » Sun Aug 03, 2008 5:48 pm

5016L is the version I tried with. I get this in the world console.
Unhandled command: q_accept_pending_quest
EDIT: OK, tried with 4412 and I get initial quest dialog, but then nothing after selecting either of the 2 choices.

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests