Skip to main content

Multi-objective quests - How to make?

Submitted by SBB64 on

I am looking at starting in on the Temple guild series of quests and I have immediately hit into the same issue I tried to skip over for the Cult. Namely, how do you trigger multiple objectives without using stages?

What I mean is that if Koal Cave shrine is stage 30 and Ghostgate shrine is stage 50, what do I do when the player goes straight to Ghostgate and skips over Koal Cave? Once you set a stage value, you can't go back and lower it.

Another issue to this is tracking individuals who are attached to a quest. For the cult, you have a quest to collect 5 bottles of brandy. You can talk to each of the Balmora innkeepers and maybe get 1 bottle each. But how do you track who did and who didn't give you a bottle? There are stages in TES3 for each one but in TES5, you can't do it the same way, since you can't lower a stage number. Are there local variables that I can set on a person that I am not seeing in the game? Something to say "if this person gives the player something, check this box or set this flag" so the NPC never does it again.

The immediate answer is to make small quests for each person. Ugh. Anyone have a better solution or can think of something in Skyrim that I can copy from? I can't think of a quest like this. Thanks.

Karma: 0 (0 votes)
Last edited by grumpycat on 8 Dec 2013 - 19:05.

I think if you setStage() to a lower stageNumber maybe the journal doesn't get updated, but maybe internally the stage is marked. So you could use getStageDone() instead of getStage() in your conditions ?

Since the NPC are unique, you can add a conditional script on them, add a conditional property to note that you have already interacted with them and then use GetScriptVariable in your conditions...

does that help ?

Karma: 0 (0 votes)

Not much info on the link to GetScriptVariable.

I'll have to look at getstagedone but I think it gives me the same problem. If you have 7 places to visit in any order, how do you track which ones the player has been to? I've already noticed that Morroblivion's version doesn't work on this quest. I've always had to use the console to set the final stages.

I guess maybe check to see if other objectives have been completed? Objectives aren't tied to a stage, so maybe that works. I need to test that idea. However, I didn't want to clog up the journal with objectives if I didn't have to.

Karma: 0 (0 votes)

I would say you need a script assigned to the quest (like the faction advancement script) like this:

* three locations to visit in any order

* each time a location is visited, a script assigned to that location (maybe a invisible box trigger thing with ontriggerenter, or something the player activates with onactivate) sets the appropriate variable in the quest script:

Event OnActivate(ObjectReference akActionRef)
  visitedlocation1 == 1
EndEvent

Or however that is supposed to work.  You get the idea?

* the script would have three variables, one for each location.  each time the script updates (RegisterForUpdate or something), it would check to see if all of the variables == 1 :

if ( visitedlocation1 == 1 && visitedlocation2 == 1 && visitedlocation3 == 1 )
    quest.setstage(50)
endif

 

something like that anyway...

Karma: 0 (0 votes)

No RegisterForUpdate please, the biggest grief of Skyrim's modding (and saved games corruption). Find some other means.

Karma: 0 (0 votes)

OK well then do it with

* three global variables or script variables

* then use the onactivate script at each of the three locations to both
* * set its own variable
* * complete the objective for that location
* * do the check to see if all have been done yet and if so, set the stage.

The script on each item at each location would be:

Event OnActivate(ObjectReference akActionRef)
    ;set the global variable for this location
    visitedlocation1 = 1

    ;complete the objective
    setobjectivecompleted(21)

    ;check to see if all the locations have been visited yet
    if ( visitedlocation1 == 1 && visitedlocation2 == 1 && visitedlocation3 == 1 )
        quest.setstage(50)
    endif

EndEvent

Karma: 0 (0 votes)

Thermador -- To check when the player enters a location, I'd consider placing a marker with an OnLoad() event, which will trigger when the player enters the cell. (Assuming it's an interior cell.)

SBB64

I am looking at starting in on the Temple guild series of quests and I have immediately hit into the same issue I tried to skip over for the Cult. Namely, how do you trigger multiple objectives without using stages?

What I mean is that if Koal Cave shrine is stage 30 and Ghostgate shrine is stage 50, what do I do when the player goes straight to Ghostgate and skips over Koal Cave? Once you set a stage value, you can't go back and lower it.

Another issue to this is tracking individuals who are attached to a quest. For the cult, you have a quest to collect 5 bottles of brandy. You can talk to each of the Balmora innkeepers and maybe get 1 bottle each. But how do you track who did and who didn't give you a bottle? There are stages in TES3 for each one but in TES5, you can't do it the same way, since you can't lower a stage number. Are there local variables that I can set on a person that I am not seeing in the game? Something to say "if this person gives the player something, check this box or set this flag" so the NPC never does it again.

The immediate answer is to make small quests for each person. Ugh. Anyone have a better solution or can think of something in Skyrim that I can copy from? I can't think of a quest like this. Thanks.

Is this true? You can't set stages down? I could have sworn you could, but that GetStage() would always return the highest stage you've completed. If you want to see if a specific stage has been completed, you can use GetStageDone().

If you can't set stages to a lower number (which really, you ought to be able to, because otherwise how would the "Allow repeated stages" flag even work?), you could add a script fragment to the dialogue where you retrieve the brandy. It'd get messy, but something like...

 

; Objective 15 is get brandy from this person
GetOwningQuest().setObjectiveCompleted(15, 1)

; Check to see if the other objectives are completed
If (GetOwningQuest().getObjectiveCompleted(16,1) && .... ) ; And so on...
  GetOwningQuest().SetStage(20)
EndIf

 

Of course, if it's possible to fail, then you also have to check fail conditions, and... aye aye aye. But really, are you absolutely certain you can't SetStage() to a lower stage than the current stage?

Karma: 0 (0 votes)

SBB64

But how do you track who did and who didn't give you a bottle? There are stages in TES3 for each one but in TES5, you can't do it the same way, since you can't lower a stage number. Are there local variables that I can set on a person that I am not seeing in the game? Something to say "if this person gives the player something, check this box or set this flag" so the NPC never does it again.

I haven't been working with this part of quests much lately, but assuming you can set a stage backwards, I think the function you're looking for is GetStageDone(). GetStage() will always return the most highest completed stage; GetStageDone() will tell you if a specific stage has been completed.

Karma: 0 (0 votes)

GetStageDone may well me the answer I need. I know at the command line you can't step back a stage, even the UESP warns you of that. But it doesn't mention using that command. So at least now I have a couple of options to try. That is more than I had 2 days ago. Thanks everyone.

Karma: 0 (0 votes)

Actually, Mooncat is right you don't even need variables - you can use "IsObjectiveCompleted":

Event OnActivate(ObjectReference akActionRef)
;or you could use OnTriggerEnter or OnLoad or whatever

    ;complete the objective
    setobjectivecompleted(21)

    ;check to see if all the locations have been visited yet
    if ( Quest.IsObjectiveCompleted(21) == 1 && Quest.IsObjectiveCompleted(22) == 1 && Quest.IsObjectiveCompleted(23) == 1 )
        quest.setstage(50)
    endif

EndEvent

 

Karma: 0 (0 votes)