Part Two: Writing a Simple Quest
Part Three: create foe; "pc at" condition; when x and y; journal
Part Four: Dungeons, hours of the day, multiple "killed" conditions
Part Five: Placing and Delivering Items
Part Six: hide npc; add/drop npc face; yes/no prompt; gold range x to y
Requirements: Text editor, Daggerfall Unity
Part One: Reading the Quest File
We will begin with the basic points, so if the reader is already acquainted with programming principles, you are free to scroll down until you see new things
In spite of being composed by .txt files, Daggerfall quests use a scripting language. This means it must begin at the beginning of the file and logically connect one element to another to produce a meaningful effect or series of effects. The language Daggerfall uses to put together a quest is simple but efficient.
There are three primary elements to a Daggerfall quest: definitions, conditions, and actions.
The Preamble consists of the first major section of the quest file. Take one sample Fighters Guild quest: (download it here if you prefer seeing it in your text editor)
Code: Select all
-- Fighters Guild
-- Min Rep: 35
Quest: FGDFU001
DisplayName: Much at Stake
-- Message panels
QRC:
QuestorOffer: [1000]
<ce> We've got a job for someone experienced like you,
<ce> %pcf, but I'm not gonna blame you for turning
<ce> it down. It involves one vampire and no sunlight.
<ce> You think you can fix that kind of problem?
<ce> There's _reward_ gold in it for you.
RefuseQuest: [1001]
<ce> I'll look for someone else then.
AcceptQuest: [1002]
<ce> So here's the deal. You're headed to
<ce> __vampres_. We don't know how the thing got into
<ce> _vampres_ or how long it's planning on
<ce> staying, but we've gotta kill it before we find out.
<ce> I'm giving you =timer_ days before I send for backup
<ce> from a temple or something. Good luck, %pcf.
QuestFail: [1003]
<ce> Scared of vampires, %pcf? Get a spine.
QuestComplete: [1004]
<ce> Excellent work, %pcf. This is why
<ce> we count on you. Have your gold.
RumorsDuringQuest: [1005]
Did you hear about the vampire that showed up in __vampres_? I can't sleep anymore.
Message: 1020
<ce> "No!" The vampire shrieks
<ce> before crumpling to the floor.
Message: 1030
%qdt:
The Fighters Guild of
___questgiver_ has sent me to
__vampres_ to slay a vampire
in _vampres_. I've got to
to be back in =timer_ days
or they'll call for the temple.
QBN:
Item _reward_ gold
Person _questgiver_ group Questor male
Place _vampres_ remote house1
Clock _timer_ 00:00 0 flag 17 range 0 2
Foe _vamp_ is Vampire
-- Quest start-up:
start timer _timer_
log 1030 step 0
place foe _vamp_ at _vampres_
_pcgetsgold_ task:
when _qgclicked_ and _slain_
give pc _reward_
end quest
_slain_ task:
killed 1 _vamp_ saying 1020
_qgclicked_ task:
clicked npc _questgiver_
_timer_ task:
end quest
_clearclick_ task:
when _qgclicked_ and not _slain_
clear _qgclicked_ _clearclick_
Without definitions, the quest will not function. Let's see first the definitions for the quest named above.
Code: Select all
-- Fighters Guild
-- Min Rep: 35
Code: Select all
Quest: FGDFU001
DisplayName: Much at Stake
Code: Select all
-- Message panels
QRC:
Code: Select all
QuestorOffer: [1000]
Code: Select all
RefuseQuest: [1001]
Code: Select all
AcceptQuest: [1002]
Code: Select all
QuestFail: [1003]
Code: Select all
QuestComplete: [1004]
Code: Select all
RumorsDuringQuest: [1005]
RumorsDuringQuest: [1005]
RumorsPostfailure: [1006]
RumorsPostsuccess: [1007]
QuestorPostsuccess: [1008]
QuestorPostfailure: [1009]
Code: Select all
Message: 1020
Message: 1020
Message: 1048
Message: 1055
Message: 1071
Message: 1090
For order's sake I always make the number rise as I go down, but I do not know whether a mixed order would have any impact on quest execution.
Code: Select all
Message: 1030
%qdt:
Code: Select all
QBN:
Code: Select all
Item _reward_ gold
The "gold" definition, when given no other parameters, automatically calculates to gold coins of approximately "your level x 100" value in the game. In this case we're just going to let that be.
Code: Select all
Person _questgiver_ group Questor male
The "group" parameter places the person into one of Daggerfall's set groups. The "group" trait itself is not very relevant yet, nor is "male," but having a "questor" is vital to end this quest.
Always include this definition for the questgiver if you're going to return to interact with him/her in some way.
Code: Select all
Place _vampres_ remote house1
"Remote" means it's some location not in the same town but in the same region, like Daenia or Abibon-Gora. Use "local" instead to look for that location type in the same geographical location you're now in. There's also a "permanent" option, which refers to certain fixed places in Daggerfall like Shedungent, Scourg Barrow, and Wayrest Castle, to name a few.
"house1" means that Daggerfall is told to look for some house within the subset "house1" (I don't know what the house1 set is but it looks for houses), and then define it as the place known as _vampres_. You can consult the quest element topic to see what other options exist beyond house1.
Not all regions or cities have all quest locations; for example, Betony has no witch coven, so attempting to define a quest in Betony using a remote witch coven would prevent the quest from setting up. Likewise, defining a "local bank" in a town that doesn't have a bank will just mean the quest refuses to run in that city.
Code: Select all
Clock _timer_ 00:00 0 flag 17 range 0 2
The whole "00:00 0 flag 17 range 0 2" mess is the ordinary way of calculating a time limit automatically, based on travel time to the quest location and back. Do not use this method if your quest doesn't require any fast travel.
Instead of "00:00 0 flag 17 range 0 2," you can replace it with "1.00:00," which will give you 1 day, zero hours, and zero minutes. Or "0.11:37," which will give you eleven hours and thirty-seven minutes to complete the quest.
If a timer runs out, that alone doesn't accomplish anything. You'll need to define a task further below that says what happens when time is up.
All times refer to in-game days, hours, and minutes.
Code: Select all
Foe _vamp_ is Vampire
Foe _vamp_ is 2 Vampire
Foe _killer_ is Barbarian
Foe _jayH_ is 3 Imp
When defining a foe as multiple enemies, never use the plural form of the enemy's name.
Code: Select all
-- Quest start-up:
Everything that happens in this paragraph is executed immediately after you accept a quest and move beyond the acceptance text.
Code: Select all
start timer _timer_
The "start timer" command tells that timer we defined above to begin. Most quests have a timer, and pairing the "Clock _timer_ 00:00 0 flag 17 range 0 2" and "start timer _timer_" commands is a quick way to resolve this in most cases.
You may think some quests don't need a timer, but it's a good idea to put one in all ordinary quests, even if it's like three months long. If something goes wrong, such as the quest enemy or item disappearing, and the quest becomes impossible to complete, there needs to be some way for the quest to terminate on its own. Otherwise it'll stay around in the journal until the sun goes cold, which is a bother.
Code: Select all
log 1030 step 0
The "step 0" doesn't matter for this quest. I don't know what happens if you remove it, as I've always kept it on. The step system determines where in the journal to put each entry in a single quest. Thus, if I for some reason order,
log 1014 step 3
log 1030 step 0
log 1035 step 2
log 1021 step 1
In the journal the quest messages will appear in this order:
1030
1021
1035
1014
If you for some reason assign the same step number to two messages, the first will be overwritten.
You can't use more than 10 steps in a single quest, which are 0 to 9.
Steps among different quests do not interfere with each other.
Code: Select all
place foe _vamp_ at _vampres_
The "place foe" command puts the defined enemy into the defined location at some random quest marker within it. Once you enter the defined location, the defined enemy will be there, waiting for you.
If you attempt to use the "place foe" command in some location with no valid quest markers, the quest will refuse to set up.
Code: Select all
_pcgetsgold_ task:
Code: Select all
when _qgclicked_ and _slain_
Code: Select all
give pc _reward_
"give pc" is an action that opens the inventory screen and offers you the chance to accept a defined item.
Code: Select all
end quest
As you can tell the "pcgetsgold" task is out of place, but this was the very first quest I wrote.
Code: Select all
_slain_ task:
Code: Select all
killed 1 _vamp_ saying 1020
Tasks activated in this manner remain activated during the entire quest. If you go up, you'll see what significance this has for the quest overall:
_pcgetsgold_ task:
when _qgclicked_ and _slain_
give pc _reward_
end quest
So once _slain_ is activated, we just need to activate _qgclicked_, and then _pcgetsgold_ will execute its action: giving a reward and ending the quest.
Coming back to the "killed" command, attaching a "saying 1020" to the end of it means the game will display message 1020 once the _vamp_ is killed. Not all actions support the "saying ####" parameter, but this one does.
When using the "killed" condition, define the number of enemies that must be slain, no matter what. Even if you define _vamp_ to mean 10 vampires, you must still define the "killed" action as 10 _vamp_ if you want every one to be killed, even though the game should presume you meant 10 to begin with.
Code: Select all
_qgclicked_ task:
clicked npc _questgiver_
"clicked npc" can function on any defined person as a condition. This works similarly to how "killed" is a condition, not an action.
Code: Select all
_timer_ task:
Code: Select all
end quest
All timers inherently create a task of their own name. This convention must be followed for any timer to have any effect.
Code: Select all
_clearclick_ task:
when _qgclicked_ and not _slain_
clear _qgclicked_ _clearclick_
That is our quest file dissection completed! In the upcoming posts, we'll create a quest file step by step, and then run it in Daggerfall Unity.