Difference between revisions of "How to Script a Mission"

From DSP Wiki
Jump to: navigation, search
Line 42: Line 42:
 
         elseif(chasingStatus == QUEST_ACCEPTED) then
 
         elseif(chasingStatus == QUEST_ACCEPTED) then
 
player:startEvent(0x0196); --  Add follow up cutscene
 
player:startEvent(0x0196); --  Add follow up cutscene
 
 
----> Windurst Mission 7-1 <----
 
----> Windurst Mission 7-1 <----
 
elseif(player:getCurrentMission(WINDURST) == THE_SIXTH_MINISTRY and player:getVar("MissionStatus") == 0) then
 
elseif(player:getCurrentMission(WINDURST) == THE_SIXTH_MINISTRY and player:getVar("MissionStatus") == 0) then
Line 48: Line 47:
 
         else
 
         else
 
player:startEvent(0x0172); -- Standard Conversation
 
player:startEvent(0x0172); -- Standard Conversation
 +
</pre>
 +
 +
 +
The code simplified:
 +
<pre>
 +
elseif        <--- if the above code isn't true then
 +
player:getCurrentMission(WINDURST) == THE_SIXTH_MINISTRY  <--- The player's Current Mission (in Windurst) is THE_SIXTH_MINISTRY
 +
and player:getVar("MissionStatus") == 0) <--- and "MissionStatus" is equal to 0 (they haven't progressed in the mission yet)
 +
then <--- then carry out the block of code til you see 'end' or another 'elseif' statement.
 
</pre>
 
</pre>
 
Notice how we not only check the player's current mission, we also check the ''variable'' '''"MissionStatus"'''.
 
Notice how we not only check the player's current mission, we also check the ''variable'' '''"MissionStatus"'''.
 
This is done so we know that the player has just received the mission and has not made any progress in it which is why the variable "MissionStatus" has a value of 0.
 
This is done so we know that the player has just received the mission and has not made any progress in it which is why the variable "MissionStatus" has a value of 0.
 +
The reason we've commented out "player:startEvent()" is because we don't know the correct EventID yet.
 
Okay we've got the correct logic/checks in there; now what?
 
Okay we've got the correct logic/checks in there; now what?
 
Now it's time to find the correct cutscene with the correct parameters (e.g. cutscenes that have items/keyitems/numbers/values returned as part of text).
 
Now it's time to find the correct cutscene with the correct parameters (e.g. cutscenes that have items/keyitems/numbers/values returned as part of text).
Line 75: Line 84:
  
  
'''Client-sided cutscene triggered:'''
+
'''Client-side cutscene triggered:'''
 
<pre>
 
<pre>
 
Tosuka-Porika: Ah, yes, I mustaru give you this.  
 
Tosuka-Porika: Ah, yes, I mustaru give you this.  
Line 106: Line 115:
 
player:startEvent(0x02cb,0,250); -- cutscene(0x02cb),idk what this parm does(0),keyitemparam(250) keyitem = OPTISTERY_RING
 
player:startEvent(0x02cb,0,250); -- cutscene(0x02cb),idk what this parm does(0),keyitemparam(250) keyitem = OPTISTERY_RING
 
</pre>
 
</pre>
 +
 +
Alright, time to see if this works!
 +
 +
'''SCRIPT:'''
 +
<pre>
 +
player:startEvent(0x02cb,0,250); -- cutscene, param1, keyitemid
 +
</pre>
 +
Looks good; we got the correct cutscene and params. Lets see if it displays correctly in-game (client sided).
 +
 +
'''Client-side cutscene triggered:'''
 +
<pre>
 +
Tosuka-Porika: Ah, yes, I mustaru give you this.
 +
You should be able to enter the Animastery using this ring.
 +
It is the Optistery Ring. Try your bestaru not to lose it.
 +
</pre>
 +
Success!

Revision as of 16:04, 18 October 2013

In this page you will learn how to script a mission from scratch.


Getting Started

This guide assumes you already have a basic understanding of writing quests, if not then I highly recommend reading BlueKirby0's guide: "How to Make a Quest". If you're too lazy to read over that then don't worry, i'll be going over most things in his guide (but in a lot less detail).


To keep things simple, let's start off with Windurst Mission 7-1 (The Sixth Ministry) as it covers most of what we need to go through.

After accepting the Mission, we must go to Tosuka-Porika in Windurst Waters for a cutscene, so go ahead open up his script (scripts/zones/Windurst_Waters/Tosuka-Porika.lua).

NOTE: I recommend using Notepad++ to open scripts as it has syntax highlighting and helps keep track of 'if' statements and their 'end's.

Scroll down to the onTrigger section and we see this:

function onTrigger(player,npc)

-- NOTE: I've cut out the lines not relevant to what we're doing or this alone would've taken up half the guide...

	if (player:getCurrentMission(COP) == THE_ROAD_FORKS and player:getVar("MEMORIES_OF_A_MAIDEN_Status")==10)then
		player:startEvent(0x036B);--COP event

-- NOTE: I've cut out the lines not relevant to what we're doing or this alone would've taken up half the guide...

	elseif(chasingStatus == QUEST_ACCEPTED and player:getVar("CHASING_TALES_TRACK_BOOK") > 0) then
		player:startEvent(0x019c);
	elseif(player:hasKeyItem(149) ==true) then
		player:startEvent(0x019c);
	elseif(chasingStatus == QUEST_ACCEPTED) then
		player:startEvent(0x0196); --  Add follow up cutscene
	else
		player:startEvent(0x0172); -- Standard Conversation
	end
	
end;

Now that we've got his script open, we need to add a check for Windurst Mission 7-1 before starting the cutscene to progress in the mission so let's add that check:

        elseif(chasingStatus == QUEST_ACCEPTED) then
		player:startEvent(0x0196); --  Add follow up cutscene
		----> Windurst Mission 7-1 <----
	elseif(player:getCurrentMission(WINDURST) == THE_SIXTH_MINISTRY and player:getVar("MissionStatus") == 0) then
		-- player:startEvent()
        else
		player:startEvent(0x0172); -- Standard Conversation


The code simplified:

elseif         <--- if the above code isn't true then
player:getCurrentMission(WINDURST) == THE_SIXTH_MINISTRY  <--- The player's Current Mission (in Windurst) is THE_SIXTH_MINISTRY 
and player:getVar("MissionStatus") == 0) <--- and "MissionStatus" is equal to 0 (they haven't progressed in the mission yet)
then <--- then carry out the block of code til you see 'end' or another 'elseif' statement.

Notice how we not only check the player's current mission, we also check the variable "MissionStatus". This is done so we know that the player has just received the mission and has not made any progress in it which is why the variable "MissionStatus" has a value of 0. The reason we've commented out "player:startEvent()" is because we don't know the correct EventID yet. Okay we've got the correct logic/checks in there; now what? Now it's time to find the correct cutscene with the correct parameters (e.g. cutscenes that have items/keyitems/numbers/values returned as part of text).

Finding the correct cutscene (with parameters)

Now we must find the correct cutscene for this mission. To do this you can find the mission on ffxiclopedia and scroll down to the spoiler and click [show].

SPOILER WARNING: Details about a quest, mission or other Final Fantasy XI in-game storyline follow. [show]

You then find the Event IDs for that NPC in that particular zone (in our case it's Windurst Waters Event IDs and the NPC is Tosuka-Porika and find the cutscene matching that dialog using the "@cs" command on a GM char e.g.

Note: Cutscenes linked to each other are usually have similar IDs e.g. @cs 830 @cs 831 @cs 832 are most likely related to the same mission/questline

@cs 830

Once you find the correct cutscene you must convert it from decimal to hexadecimal before using it for "player:startEvent( )".

Okay so now we've found the correct cutscene (0x02cb) but it's showing this:

SCRIPT:

player:startEvent(0x02cb);


Client-side cutscene triggered:

Tosuka-Porika: Ah, yes, I mustaru give you this. 
You should be able to enter the Animastery using this ring. 
It is the '      '. Try your bestaru not to lose it.


That doesn't look right!

This is because this cutscene requires a special parameter. In our case the parameter is the value of the keyitem Optistery Ring.

To add this we can either call the keyitems script at the top of the file like so:

require("scripts/globals/settings");
require("scripts/globals/titles");
require("scripts/globals/missions");
require("scripts/globals/quests");
require("scripts/zones/Windurst_Walls/TextIDs");
require("scripts/globals/keyitems"); --<----- require keyitems

After we require the keyitems script we can then add this:

player:startEvent(0x02cb,0,OPTISTERY_RING);

Or we can go into the keyitems.lua file, find the id of OPTISTERY_RING and add the following to player:startEvent

player:startEvent(0x02cb,0,250); -- cutscene(0x02cb),idk what this parm does(0),keyitemparam(250) keyitem = OPTISTERY_RING

Alright, time to see if this works!

SCRIPT:

player:startEvent(0x02cb,0,250); -- cutscene, param1, keyitemid

Looks good; we got the correct cutscene and params. Lets see if it displays correctly in-game (client sided).

Client-side cutscene triggered:

Tosuka-Porika: Ah, yes, I mustaru give you this. 
You should be able to enter the Animastery using this ring. 
It is the Optistery Ring. Try your bestaru not to lose it.

Success!