Page 1 of 1

Northern San d'Oria NPC Script: Pagisalis

Posted: Tue Aug 28, 2012 8:43 am
by Cerenth
Hello,

I am a newbie to programming, but I thought I'd try my hand at trying to script an NPC for DS.

My script has been tested on a private server and works as intended.

I'm eager to hear any feedback and tips on it.

Code: Select all

----------------------------------------------------------------------
-- Quest: Undying Flames
-- Area: San d'Oria
-- Quest ID: 26
-- Quest NPC: Pagisalis
-- Starts: Undying Flames
-- Involved in: Enveloped in Darkness
-- @zone 231
-- @pos 138 6 131
----------------------------------------------------------------------
package.loaded["scripts/zones/Northern_San_dOria/TextIDs"] = nil;
----------------------------------------------------------------------

require("scripts/globals/settings");
require("scripts/globals/titles");
require("scripts/globals/keyitems");
require("scripts/globals/shop");
require("scripts/globals/quests");
require("scripts/zones/Northern_San_dOria/TextIDs");

----------------------------------------------------------------------
--OnTrade Action
----------------------------------------------------------------------

function onTrade(player,npc,trade)
-- Npc used in AF quest
	if(player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS) == 3) then
		count = trade:getItemCount();
		VelvetCloth = trade:hasItemQty(828,1);
		if(VelvetCloth == true and count == 1) then
			player:startevent(0x0025);--start RDM AF feet CS
		end
	end
--Now script this quest
	if(player:getQuestStatus(SANDORIA,UNDYING_FLAMES) == QUEST_ACCEPTED) then
		count = trade:getItemCount();
		Beeswax = trade:hasItemQty(913,2);
		if(Beeswax == true and count == 2) then
			if(player:getFreeSlotsCount() > 0) then
				player:tradeComplete();
				player:startEvent(0x0233);--quest complete text
			else
				player:messageSpecial(ITEM_CANNOT_BE_OBTAINED,13211);
			end
		else
			player:startEvent(0x0234);--npc responding that trade items are wrong
		end
	end
end;

-----------------------------------------------------------------------
--onTrigger Action
-----------------------------------------------------------------------

function onTrigger(player,npc)

	UndyingFlames = player:getQuestStatus(SANDORIA,UNDYING_FLAMES);
	EnvelopedInDarkness = player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS);
--Clicking on npc before and after trading in enveloped in darkness 
	-- if(EnvelopedInDarkness = 2 or 3) then -- I wish it worked this easily ;_; It needs more text
	if(EnvelopedInDarkness == 2 or EnvelopedInDarkness == 3) then -- = is setting a variable, == is checking if it matches a value
		player:startEvent(0x0030);--quest text for instructing player
	elseif(EnvelopedInDarkness >= 4) then
		player:startEvent(0x003A);--text after trade for EiD has been made
--clicking on npc without undying flames active
	elseif(UndyingFlames == 0) then
		player:startEvent(0x0232);--event for starting quest
	elseif(UndyingFlames == 1) then
		player:startEvent(0x0235);--event for talking to npc with quest accepted
	elseif(UndyingFlames == 2) then
		player:startEvent(0x0236);--changed text for talking after the quest is complete
	end
end
	
----------------------------------------------------------------------
--onEventFinish
----------------------------------------------------------------------

function onEventFinish(player,csid,option)
	UndyingFlames = player:getQuestStatus(SANDORIA,UNDYING_FLAMES);
	EnvelopedInDarkness = player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS);
--Quest progression for Enveloped in Darkness
	if(csid == 0x0030) then
		player:setVar("QuestEnvelopedInDarknessVar",3);
	elseif(csid == 0x0025) then
		player:setVar("QuestEnvelopedInDarknessVar",4)
		player:addItem(14093);--give player RDM feet
		player:messageSpecial(ITEM_OBTAINED,14093)
--Quest progression for Undying Flames
	elseif(csid == 0x0232 and option == 0) then
		player:setVar("QuestUndyingFlamesVar", 1);
		player:addQuest(SANDORIA,UNDYING_FLAMES);
	elseif(csid == 0x0233) then
		player:addFame(SANDORIA,SAN_FAME*30);
		player:addItem(13211);
		player:messageSpecial(ITEM_OBTAINED,13211);
		player:setTitle(FAITH_LIKE_A_CANDLE);
		player:completeQuest(SANDORIA,UNDYING_FLAMES);
	end
end
This script handles the quest "Undying Flames" in it's entirety, and already has support for Pagisalis' other quest, Enveloped in Darkness, the RDM AF feet quest.

Here is the file for easy download.
Pagisalis.rar
(1.26 KiB) Downloaded 269 times
Here's hoping to many more successful codes!

Re: Northern San d'Oria NPC Script: Pagisalis

Posted: Tue Aug 28, 2012 8:40 pm
by whasf
Hi there and thank you for the script!

A few things:

Don't be afraid to combine logic, remember eventually Darkstar will have thousands of players on it, try to make your code as tight and light on resources as possible:

Code: Select all

function onTrade(player,npc,trade)
   if (player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS)== (what's 3??) and trade:hasItemQty(828,1) and trade:getItemCount()==1) then
 --- you forgot this:
       player:tradeComplete();
        player:startEvent(0x0025);
   end
   elseif {...}
Quests only have status of 0,1,2... so I don't know what you are testing for there.
That's all I can see right now, I'm kind of tired..

thanks! :)

Re: Northern San d'Oria NPC Script: Pagisalis

Posted: Wed Aug 29, 2012 3:43 am
by Cerenth
Hi,
Thank you for the feedback.

The part with player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS) == 3 is taken from http://dspt.freeforums.org/how-to-track ... s-t40.html. It is part of a quest that requires a specific order of npcs, so I used variables other than 0, 1 and 2 to track which npcs the player has spoken to.

And I certainly derped by missing the trade complete command. Thanks for pointing it out. It's my first time with lua and I'm always looking for feedback on ways I can improve.

Here is the updated code:

Code: Select all

----------------------------------------------------------------------
-- Quest: Undying Flames
-- Area: San d'Oria
-- Quest ID: 26
-- Quest NPC: Pagisalis
-- Starts: Undying Flames
-- Involved in: Enveloped in Darkness
-- @zone 231
-- @pos 138 6 131
----------------------------------------------------------------------
package.loaded["scripts/zones/Northern_San_dOria/TextIDs"] = nil;
----------------------------------------------------------------------

require("scripts/globals/settings");
require("scripts/globals/titles");
require("scripts/globals/keyitems");
require("scripts/globals/shop");
require("scripts/globals/quests");
require("scripts/zones/Northern_San_dOria/TextIDs");

----------------------------------------------------------------------
--OnTrade Action
----------------------------------------------------------------------

function onTrade(player,npc,trade)
-- Npc used in AF quest
	if(player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS) == 3 and (trade:getItemCount() == 1) and trade:hasItemQty(828,1)) then
			player:tradeComplete();
			player:startevent(0x0025);--start RDM AF feet CS
		end
	end
--Now script this quest
	if(player:getQuestStatus(SANDORIA,UNDYING_FLAMES) == QUEST_ACCEPTED) then
		count = trade:getItemCount();
		Beeswax = trade:hasItemQty(913,2);
		if(Beeswax == true and count == 2) then
			if(player:getFreeSlotsCount() > 0) then
				player:tradeComplete();
				player:startEvent(0x0233);--quest complete text
			else
				player:messageSpecial(ITEM_CANNOT_BE_OBTAINED,13211);
			end
		else
			player:startEvent(0x0234);--npc responding that trade items are wrong
		end
	end
end;

-----------------------------------------------------------------------
--onTrigger Action
-----------------------------------------------------------------------

function onTrigger(player,npc)

	UndyingFlames = player:getQuestStatus(SANDORIA,UNDYING_FLAMES);
	EnvelopedInDarkness = player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS);
--Clicking on npc before and after trading in enveloped in darkness 
	-- if(EnvelopedInDarkness = 2 or 3) then -- I wish it worked this easily ;_; It needs more text
	if(EnvelopedInDarkness == 2 or EnvelopedInDarkness == 3) then -- = is setting a variable, == is checking if it matches a value
		player:startEvent(0x0030);--quest text for instructing player
	elseif(EnvelopedInDarkness >= 4) then
		player:startEvent(0x003A);--text after trade for EiD has been made
--clicking on npc without undying flames active
	elseif(UndyingFlames == 0) then
		player:startEvent(0x0232);--event for starting quest
	elseif(UndyingFlames == 1) then
		player:startEvent(0x0235);--event for talking to npc with quest accepted
	elseif(UndyingFlames == 2) then
		player:startEvent(0x0236);--changed text for talking after the quest is complete
	end
end
	
----------------------------------------------------------------------
--onEventFinish
----------------------------------------------------------------------

function onEventFinish(player,csid,option)
	UndyingFlames = player:getQuestStatus(SANDORIA,UNDYING_FLAMES);
	EnvelopedInDarkness = player:getQuestStatus(SANDORIA,ENVELOPED_IN_DARKNESS);
--Quest progression for Enveloped in Darkness
	if(csid == 0x0030) then
		player:setVar("QuestEnvelopedInDarknessVar",3);
	elseif(csid == 0x0025) then
		player:setVar("QuestEnvelopedInDarknessVar",4)
		player:addItem(14093);--give player RDM feet
		player:messageSpecial(ITEM_OBTAINED,14093)
--Quest progression for Undying Flames
	elseif(csid == 0x0232 and option == 0) then
		player:setVar("QuestUndyingFlamesVar", 1);
		player:addQuest(SANDORIA,UNDYING_FLAMES);
	elseif(csid == 0x0233) then
		player:addFame(SANDORIA,SAN_FAME*30);
		player:addItem(13211);
		player:messageSpecial(ITEM_OBTAINED,13211);
		player:setTitle(FAITH_LIKE_A_CANDLE);
		player:completeQuest(SANDORIA,UNDYING_FLAMES);
	end
end
And again, the .lua file in a rar for download:

This walkthrough isn't perfect, I don't have time to be spec

Posted: Wed Aug 29, 2012 8:01 am
by codiddle
I'm new also to programming and lua, but I'll go ahead and tell you that your file should be in .patch format.

What you do is (if you used TortoiseSVN) create a new folder, and download the latest revision to it by using SVN Checkout. So that you have the cleanest set of files you can possibly have.

Drop your editted files back where they belong. Including anything in the database you may have changed. If you use Navicat, to save anything you added to the DB (as in, you input the coordinates of a npc that was not already there), you simply right-click the table Dump SQL.

Then, right click the folder you just created and find TortoiseSVN, scroll down to the bottom and click "Create Patch" it'll prompt you about which files you wanted have in your patch, select whatever you added to the fresh, new, clean revision.

Then it prompts you to name your patch as a .diff or .patch file, this website has only let me use .patch but I have seen someone upload a .diff file too. So, yah that's about it.

Re: Northern San d'Oria NPC Script: Pagisalis

Posted: Thu Aug 30, 2012 3:02 am
by Cerenth
Ah, ok. I can't make a patch file right now since the computer I built my server on is currently in pieces because I was upgrading it. I'll make the file as soon as I can and upload it to this thread.

Thanks for the tip!

Re: Northern San d'Oria NPC Script: Pagisalis

Posted: Sat Sep 15, 2012 4:19 am
by bluekirby0
Instead of trying to abuse the Quest Status (which should only ever be 0 1 or 2), you should be using setVar and getVar to create a quest-specific variable tied to the quest. Remember once it is no longer needed to setVar to 0, please, so the unneeded entries are removed from the database.

Honestly if that script does work as-is then we have some bigger issues to work out, because the quest status shouldn't always be equal to a variable of the same name.

Re: Northern San d'Oria NPC Script: Pagisalis

Posted: Sat Sep 15, 2012 3:20 pm
by Metalfiiish
My first response would be don't build scripts based off npc but rather the quest. Why ? because it doesn't make sense to add in partial bits of a quest on the npc without knowing how the quest plays out and what variables are needed and what changes occur during different time of the quest. So build scripts by following a quest and update all npcs that the quest touches, keeping in mind that your additions must not break other functions that the npc has built in its script.

With that said the quest looked pretty solid in terms of a read through for Undying flames, however, the enveloped in darkness requires a lot of work and I will mess with that now. For now I only made slight changes to that but will send you back the entire script once I fix enveloped in darkness.

Re: Northern San d'Oria NPC Script: Pagisalis

Posted: Wed Sep 19, 2012 5:19 am
by Metalfiiish
so it's aparent that you were trying to add in the enveloped in darkness quest. It is completely off as you made it as you are trying to use the quest status as a variable.

getQuestStatus() returns 3 values :
0 ,1 and 2
There is a file that maps these to named variables:
0 = QUEST_AVAILABLE
1 = QUEST_ACCEPTED
2 = QUEST_COMPLETED

Now as you can see it is hard to tell what state the quest is in if it is in active and an event changes. For these we use variables that we set on the player (in a database table).

Code: Select all

This is done by using the setVar() and getVar() commands. Example:

player:setVar("SpecificVariableName",1);  --sets the variable
questVariable = player:getVar("SpecificVariableName"); -- grabs the variable

if (questVariable == 1) then
        player:setVar("SpecificVariableName",2); --updates the variable