Jump to content

A Question Answered: Completing a quest objective when player levels u


KingGsterUK

Recommended Posts

This was supposed to be a legitimate question to anyone out there with scripting experience but nearing the end of writing this lengthy post, after fleshing out my scenario to all of you and proof-reading what I'd written, I finally figured it out. The mistake is laughable and certain parts may also trigger peoples humor, that and this might actually be of some use to people who may encounter the same problems as me - is why I'm submitting a question, with an answer all by the same guy without edits.

 

That seems so weird but without further ado, the original post:

 

Hi all.

 

I'm working on a practice mod to learn the basics of quests, dialogue and scripting. I have a quest, that so far, gives the player 2 objectives to complete at the end of some dialogue with an NPC. The objectives are like prerequisites (Obviously) :blink: for the next stage. But they're a bit... Weird. Well, one is.

#1

 

Objective Index | Display Text   | TargetRef                 | Conditions   |
____________________________________________________________________________
0               | Own 5000 Gold  | ThePropositionAliasPlayer | No Condition |
1               | Gain a level   | ThePropositionAliasPlayer | No Condition |

 

 

I've never seen an objective in game that instructs you to "gain a level" and I'm struggling to find a way to complete "Objective Index 1" on a level-up event. I have an "NPC", a "quest", some "stages", some "objectives", some "dialogue", an "alias" pointing to the player and a "quest script".

 

If I could write the script I needed in English, it would look something like this:

#2

 

When the Player levels up
    Check if we are on Stage 20 of QuestTheProposition
        Check if we haven't already completed Objective 1 of QuestTheProposition
        Complete Objective 1 of QuestTheProposition

 

 

Even if I converted that into code it wouldn't work and would look something like this:

#3

 

Scriptname ThePropositionScript extends Quest
{Controls The Proposition questline}

Quest Property ThePropQuest Auto ;This points to ThePropositionQuest
Int ThePropStage

event OnStoryIncreaseLevel(int newLevel)
ThePropStage = ThePropQuest.GetCurrentStageID()
    if ThePropStage == 10
    ThePropQuest.SetObjectiveCompleted(1)
    endIf
endEvent

I get no errors compiling the above code. It doesn't work because it's not getting the event sent by story manager. That's understandable because I haven't told story manager to start this quest on level up and "I don't want it to start an already running quest up". Understandable, understandable. :huh:

 

So I created a new "Silent" quest, QuestThePropLevelEvent, selected the "Increase Level" Event and added a new Branch/Quest to Story Manager, pointed it to the new quest and set some conditions.

 

I then made a new script to go with the "Silent quest", with just this in it:

#4

 

Scriptname ThePropLevelScript extends Quest  
{Confirms level up}


Event OnStoryIncreaseLevel(Int newLevel)
Debug.MessageBox("Level Up")
endEvent

 

 

Bingo. I get the Message Box popping up, confirming the level up and had a :dance: type of moment!

I thought, great, all I need to do now is set the stage of the other quest from here.

 

<--- The True Moment Of Eureka and the point where I answered my own question

 

I was going to ask "HOW THE HELL DO I CHANGE THE PROPERTY IN MY MAIN QUEST's SCRIPT FROM INSIDE THE SILENT QUEST's SCRIPT!!?? all friendly like.

 

The thing is I don't need to change the property of my "Main quests script", that property shouldn't even be there, because that quest isn't receiving the event from Story Manager. Deleting everything in the "Main quest's script" and putting it all in the "Silent quest's script" should do what I am trying to do.

 

To actually finish off what needs to be done to get this to work is:

1) Copy/delete the code from ThePropositionScript

2) Paste it into ThePropLevelScript

3) Point the property towards "QuestTheProposition"

4) Save everything and try it out in game

 

And Kaboom! Everything works! Happy G :woot:

 

Note:

Checking whether the player had 5000 gold in their inventory was quite simple to figure out from the creation kit reference pages. Whether I'm doing it the most efficient way, is not likely but it's working. For anyone that wants to implement an objective similar to "Objective Index 0" in the above table, can do so like this in the #6 spoiler tags and anyone else interested in code or wanting to optimize it can read it too:

#6

 

A rough guide to completing a quest objective when the player has a certain amount of gold, using scripts.

1) Create a quest

1.1) Create some quest stages

1.2) Create a quest objective

1.3) Create some dialogue in the quest for an NPC quest giver

1.4) Copy and paste this into the script "Fragment" section of the dialogue window, when your NPC has said all he needs to say and says "goodbye":

GetOwningQuest().SetStage(10) ;Adjust the value 10 to your particular quest stage or delete this line entirely
GetOwningQuest().SetObjectiveDisplayed(0) ;Adjust the value 0 to your Objective Index Number

1.5) Read the comments in the code and adjust the values accordingly

 

2) Create a new quest alias

3) Give it a unique name

4) Put a tick in these boxes: "Allow reuse in quest", "Allow disabled". (not certain whether it's actually necessary but mine has)

5) Highlight "Unique actor" and from the drop-down box select "Player"

6) Click on "Add" (script section to the right)

7) Click on "[NEW SCRIPT]"

8 ) Give the script a unique name

9) Make sure it extends ReferenceAlias and click OK

10) Right click your script from the "ReferenceAlias" window and select "Edit Source"

11) In the "top box", "under all the text" that's currently in there, on a "new line" copy and paste this:

Actor Property mySelf Auto

12) Click file, save, then close.

13) Click on your script again from the "ReferenceAlias" window, and click on properties.

14) Click on the "mySelf" Property

15) Click "Edit Value"

16) From the "Cell" drop-down box, select "(any)"

17) From the "Reference" drop-down box, select "PlayerRef ('Player')"

18) Click OK

19) Right Click your script again and click "Edit Source" again

20) Copy and paste this into your script:

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, \
ObjectReference akSourceContainer)
    if GetOwningQuest().GetStage() == 10 ;Adjust the value 10 to your quest stage
        if !GetOwningQuest().IsObjectiveCompleted(0) ;Adjust the value 0 to your ojective index number
            if mySelf.GetGoldAmount() >= 5000 ;Adjust the >= operator and the value 5000 to match your quest objective display text
            GetOwningQuest().SetObjectiveCompleted(0) ;Adjust the value 0 to your ojective index number
            endIf
        endIf
    endIf
endEvent

21) Read the notes in the code( whatever comes after ; ) and adjust the values to suit your needs

 

Now when we are in game and the quest which owns our new alias is running, when we add something to our inventory a script fires up and checks whether all the criteria in the if statements are true. If true, our quest objective will complete.

 

But what if we already have 5000 gold when we first get the objective, I hear you say. Yes, indeed, the script won't fire because nothing's been added to our inventory.

 

I haven't implemented it yet, and to tell you the truth, I've only just realized but I'm sure for cases like that, where we may have completed the criteria already, we could check at the same time as we issued the objective.

 

I mainly include this guide for those that stumble upon it from forum searches and places like google. I hope it helps somebody.

 

 

 

 

Note To Everybody Else Troubleshooting Code:

Take some time to think about your code logically, even better from someone else's perspective. - Try and explain it, do a step-by-step, does it make sense? Can I make it more efficient? Do i even need to do it like this? - Things like that.

 

Thank you to those who read this and Happy Modding :thumbsup:

Edited by KingGsterUK
Link to comment
Share on other sites

To answer your original question, that is "HOW THE HELL DO I CHANGE THE PROPERTY IN MY MAIN QUEST's SCRIPT FROM INSIDE THE SILENT QUEST's SCRIPT!!??" You can actually do that fairly simply once you know how. Imagine quest one is titled Quest1. You could probably guess quest 2 would be titled Quest2. Follow the same scheme for the scripts and variables.

ScriptName QuestScript1 Extends Quest

Int Property Variable1 Auto

Event OnInit()
RegisterForUpdate(1.0)
EndEvent

Event OnUpdate()
DoSomethingWithVariable1
EndEvent
ScriptName QuestScript2 Extends Quest

QuestScript1 Property Quest1 Auto

Event SomeEvent()
 (Quest1 as QuestScript1).Variable1 = 3
EndEvent

The first script will continually update and it'll be working with an empty variable. When the second script's event runs, it'll set the first script's variable to 3 so it'll now be using that value. Most important bits are

  • When declaring the property for the quest (or some other type or property), the type gets replaced with the script, the property name can be anything (it's just a normal property).
  • When calling the other script to get its functions or properties, you must put "(PropertyName as ScriptName).Property\Function". Putting it in parentheses and using as will combine them into a single unit so the following calls work correctly.
  • I believe the "extends" section in the script you're calling is what defines the property type. By that I mean Script1 extends Quest. That means the Quest1 property in QuestScript2 will actually be a property of type "quest" just like if you'd typed "Quest Property Quest1 Auto". If you're getting mismatch errors, that might be the problem.

It can be used on objects and actors as well. No matter the type, just make sure to fill the property like normal.

Edited by Xander9009
Link to comment
Share on other sites

Hi,

 

Thank you for your above post. Would you mind posting your final version of the "silent quest" that you did for objective 1? Additionally, did you release the mod? I'd love to be able to open it up in the creation kit and look at the quest, or if you could take a screenshot of your quest stages in the creation kit, that would be really nice.

 

I've been working on a new race for about a year now. So far I've fumbled through papyrus enough to make several scripts that extend magic effects, but since I've never even made a quest, I don't know where to start. What I think I'm needing is to make a quest, with a script, that will add and remove "racial power" spells, as the player reaches various levels.

 

Here's my attempt to rework your script for my needs. It compiles, but I still don't know how to setup it's quest stages or what is needed to make those stages correlate to various player levels.

 

 

 

Scriptname yyyDhaerrowLevelUpController extends Quest
{will hopefully eventually be used to level up racial powers by removing the current tier of spell or power and then adding the next higher tier of a spell or power}

Event OnStoryIncreaseLevel(int NewLevel)

Debug.Trace("Something just reached level " + NewLevel)

Int TheQuestStage
Actor target = Game.GetPlayer()
TheQuestStage = yyyLevelUpTracker.GetCurrentStageID()

if TheQuestStage == 10

yyyLevelUpTracker.SetObjectiveCompleted(1)
target.removespell(FaerieFire0) ; used to remove the first tier of the starting power Faerie Fire
target.addspell(FaerieFire1) ; used to add the second power tier of Faerie Fire

endIf

EndEvent

Quest Property yyyLevelUpTracker Auto ; this points to "yyyLevelUpTracker" quest

Spell Property FaerieFire0 Auto
Spell Property FaerieFire1 Auto

 

 

 

On a side note, how to I make the script verify if the player is the person who is leveling up? Doesn't that need to be done so that the quest stages wouldn't advance when something like a follower levels up?

 

Thank you in advance for any help that anyone might be williing to offer!

Edited by SkyrimModHunter
Link to comment
Share on other sites

You'll have to wait for KingGsterUK for the rest, but I can answer the last question. No, you don't need to do anything special. NPCs don't level up. Even if their level changes, it's only changing, not "levelling up". AT least, that should be the case.

Link to comment
Share on other sites

  • 2 weeks later...

@SkyrimModHunter - My apologies for not being around over Christmas time and not noticing your trouble sooner, I've recently had an Infinity Engine addiction, hence my absence. (Oh how I wish that modding scene was as active as this one :sad: ) I hope posting this information can still be of some use to you.

 

------------------------------------------------------------------------------------------------------------------------------

 

What you need:

Main quest - Has stages, objectives, aliases and dialogue

Silent quest - Doesn't have any of the above, it's just a shell with a script attached to it

Add your silent quest to story manager, so it will receive events from story manager

 

 

First off, my main quest has a "blank script", nothing in it other than the script name. It doesn't need one at all but I'm not deleting it because I may still use it, for something.

 

 

Secondly, this is the script that is attached to the "Silent Quest".

Scriptname ThePropLevelScript extends Quest  
{Completes an objective in another quest on level up.}


Quest Property ThePropQuest Auto ;This points to ThePropositionQuest (your main quest)
Int ThePropStage ;declare an integer variable


event OnStoryIncreaseLevel(int newLevel) ;Recieve event from StoryManager, integer variable unused
ThePropStage = ThePropQuest.GetCurrentStageID() ;Our declared variable is now the current stage of the main quest at the time of this event
    if ThePropStage == 10 ;This is checking if we are on the correct stage
    ThePropQuest.SetObjectiveCompleted(1) ;If we are, do this
        if ThePropQuest.IsObjectiveCompleted(0) ;Check if we've also completed the other objectives while we are at it
        ThePropQuest.SetStage(20) ;If we have, advance the stage on to the next
        ThePropQuest.SetObjectiveDisplayed(10) ;Also advance the objective displayed
        endIf
    endIf
endEvent

Thirdly, if you'd still like to pull the mod apart yourself, I've included it here, attached to this post. It's not really a mod, and doesn't deserve to have a full release. It was just the beginning of an overly ambitious project that aimed to allow the player and an NPC to build a central marketplace in Solitude, from planning and hiring to building and managing. A place where the player could place bulk orders for crafting supplies, botanical supplies, cooking supplies as well as hire staff, manufacture and sell products. It was meant to be a business mod that would be unrivaled with real-time building, new animations for carrying and laboring and constructing, Horse and cart deliveries and much more. My imagination is getting carried away again, I think I'll leave it there.

 

TheBusinessPartner.rar contains TheBusinessPartner.esp ONLY - I can guarantee it's saftey

 

Happy modding :)

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...