Jump to content

[LE] Running a script at a particular quest stage


Recommended Posts

Apologies if I'm asking a naive question, but I've looked all over and not found any kind of answer. I'm looking to run a very simple one-line piece of script code at a particular stage in one of the vanilla quests. What is the syntax to do so?

For reference, I want to remove protected status from the 5 or so Dark Brotherhood targets who are set to protected. I like setting up indirect kills such as frenzying the target so they end up killed by their own men, but protected status stops that from being possible. I figure (and correct me if I'm wrong) that the safest way to do that for gameplay and general compatibility with other mods would be to run a quick script to set protected status to false when the player is given the task to kill them, attached to that particular quest. My guess is that this means that any other mod which alters the base actor (and I already have one or two in my load order) won't conflict with it, and it'll continue to prevent them from dying an accidental death before the contract as Bethesda intended.

My script so far (attached to the contract quest) is very simple. I used

Event OnInit()
    MyActor.GetActorBase().SetProtected(false)
EndEvent

However I found that removed protected status from the NPC without having started the quest, and I assume that's down to the OnInit() Event just setting it to run as soon as the game is started. So, what is the best way to fire the SetProtected line at a particular quest stage?

Link to comment
Share on other sites

There is a way.

You could make a MagicEffect, that has the CK condition of GetStage [ Your quest ] == the stage. Then create a spell ability that implements this magic effect.

Then create a start-game-enabled quest, add a player alias to it (Unique Actor -> Player), and add your spell ability to the spell list of this alias.

Then attach your script to the MagicEffect, and you can your run code with in an OnEffectStart event.

 

What happens here is that when the quest you're watching for hits the desired stage, the magic effect condition will suddenly be true, it will get applied, and its OnEffectStart event executes.

 

This is the only way I know to execute code when a quest hits a stage, without editing the vanilla quest fragment itself.

Link to comment
Share on other sites

Thanks for the info, WhiteWolf. I may well give that a go. Probably a naive question, but is that sort of workaround way suitably efficient that if I ever release it into the world (admittedly as a noob to modding) I'm unlikely to get complaints of script bloat and similar?

 

I did try to look into the quest fragment stuff, and it did look promising, however as far as I know I need to use the GetActorBase() function to be able to set the target as protected, and that is a function in Actor and I couldn't find a way to add a alias of or reference to the target which the fragments would be able to use, and which extended Actor. That could well just be my naivete in all this modding, though.

 

Anyway, I'll give that a go and see if I can get it working that way.

Link to comment
Share on other sites

Regarding the fragment, does this code compile in the fragment?

Actor Property Actor1 Auto
Actor Property Actor2 Auto
Actor Property Actor3 Auto
Actor Property Actor4 Auto
Actor Property Actor5 Auto

Actor1.GetActorBase().SetProtected(false)
Actor2.GetActorBase().SetProtected(false)
Actor3.GetActorBase().SetProtected(false)
Actor4.GetActorBase().SetProtected(false)
Actor5.GetActorBase().SetProtected(false)

You should be able to fill properties with each actor using the property button below that window after it's compiled.

Link to comment
Share on other sites

Do not put properties manually into the fragment field in the CK. That won't even compile.

Use the Properties button instead to add properties. (or edit the entire generated script in the Scripts tab, but I don't recommend that if you're still new to this and are not sure what you are doing).

 

I think we may have misunderstood each other though.

 

If you're asking about how to run the code for setting the protection actors in general, then the easiest way is what Dromundas is telling, and editing the fragment itself directly.

In order for a script to access something, it must have it as a property. Add your Actors as properties using the Properties button on the fragment (again, NOT directly in the text, use the button), and then you can do this in the fragment:

Actor1.GetActorBase().SetProtected(false)
Actor2.GetActorBase().SetProtected(false)
Actor3.GetActorBase().SetProtected(false)
Actor4.GetActorBase().SetProtected(false)
Actor5.GetActorBase().SetProtected(false)

The drawback of this approach is that your plugin will now be editing the record of this quest. Meaning, it will be incompatible with any mod that tries to edit this quest in any way.

 

Since what you are doing is not strictly related to the quest itself, rather, you just need a "this quest hit that stage event", what I suggested is arguably a better approach. That way you are not editing the quest, instead, your code runs kinda simultaneously, in parallel with it.

Running your code on the actors is the same with it.

Add your Actors as properties to the MagicEffect script, and the OnEffectStart event should be the same code example as above.

 

 

Whichever approach you choose is up to you. Editing the fragment is much easier but is worse regarding compatibility with other mods. Making the magic effect is a but harder but it's compatible with everything.

Link to comment
Share on other sites

I had no idea. Adding properties to dialogue fragments like that does indeed work, so it's interesting that's not the case with quest fragments.

The magic effect would be worth the setup if this mod is going to be public so it always works as intended. But wouldn't a quest fragment only be incompatible with changes to that quest fragment?

Link to comment
Share on other sites

If you open up the entire source of a quest script, you'll see that under the hood a "fragment" is in fact hidden function. Example (excerpt from the quest script of DB06):

 

;BEGIN FRAGMENT Fragment_10
Function Fragment_10()
;BEGIN AUTOCAST TYPE DB06Script
Quest __temp = self as Quest
DB06Script kmyQuest = __temp as DB06Script
;END AUTOCAST
;BEGIN CODE
;Sanctuary Setup
DBSanc_CiceroMovesIn_Enable.Disable()
DBSanc_CiceroMovesIn_Disable.Enable()
DBSanc_CiceroMovesOut_Enable.Enable()
DBSanc_CiceroMovesOut_Disable.Disable()

SetObjectiveCompleted (30)
Utility.Wait(5)
Stop()
;END CODE
EndFunction
;END FRAGMENT

If you add a property into the fragment field, it'd put it into the body of this function, which is not exactly the correct place, properties should be toplevel, meaning, outside any function. That's what the properties button does, if you check, it appends properties to the very end of the script, outside the functions.

 

 

This is the same reason why editing a fragment makes the whole quest incompatible with other mods editing other fragments. Editing a fragment means you're editing the underlying quest script. That's an entire file, and both mods have a version of it, each editing a different part of the file, true, but the entire file conflicts nonetheless. (Unless you merge the edits in a patch.)

Link to comment
Share on other sites

So patching the QF_DB06_0001EA55 script would only conflict with changes to quest stage fragments then. That's not that bad or hard to patch for conflicts. But I like your idea better. I built my standalone frameworks for this very reason.

So another question, due to the conditions, the ability you're describing, although applied already by an alias, can't apply its magic effect until the conditions are met? Does this use some internal loop then?

Link to comment
Share on other sites

  • Recently Browsing   0 members

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