Jump to content

Complete quest objective on death


WIGWAM

Recommended Posts

I want to make a quest where you have to kill four targets, each with their own objective.

 

I want it so that the targets can be killed in any order and once all four are killed then the quest moves to the next stage.

 

To do this I decided to put a script on each of the targets so that when they die it would update the objectives.

 

The script i have doesn't currently work and I'm not sure whats wrong with the script.

 

If someone could have a look over the script or suggest an alternative that would be great.

Scriptname [scriptname] extends ObjectReference

Event OnDeath()
    		SetObjectiveCompleted [questname] (30)
		if IsObjectiveCompleted [questname] (40) == True && IsObjectiveCompleted [questname] (50) == True && IsObjectiveCompleted [questname] (60) == True
		SetStage [questname] (70)
		SetObjectiveDisplayed [questname] (70)
	Endif
EndEvent
Link to comment
Share on other sites

Well, the first issue is that you're using the console command line syntax which is not papyrus code. You'll want to read some papyrus primers and tutorials to understand how papyrus code is written.

 

Review the OnDeath event from the wiki https://www.creationkit.com/fallout4/index.php?title=OnDeath_-_Actor

You might also review the OnDying event https://www.creationkit.com/fallout4/index.php?title=OnDying_-_Actor. I forget why it was suggested to use that instead, but most Bethesda scripts do.

 

It would probably be better to put the script on Reference Aliases on the quest. And depending on how you want to handle it, probably just use a counter to increment each time one of your flagging actors is killed, then when counter reaches max set stage to progress.

 

If you have Nukaworld you can look at the DLC4RaiderKickout quest and see how Bethesda handles it. Slightly different than I example below.

 

Your script would be something like

Scriptname MultiAliasOnDeathProgressionScript extends ReferenceAlias
 
int Property thisActorObjective Auto Const Mandatory
int Property finalStage Auto Const Mandatory
GlobalVariable Property myBossDeathCounter Auto Const Mandatory
 
Event OnDying(Actor akKiller)
    Quest myQuest = GetOwningQuest()
    myQuest.SetObjectiveCompleted(thisActorObjective)
    myBossDeathCounter.SetValue(myBossDeathCounter.GetValue() + 1)
    if myBossDeathCounter.GetValue() >= 4 ; set this 4 to whatever the count of your watched actors is. Or you could use an int property or another global variable.
        myQuest.SetStage(70)
        myQuest.SetObjectiveDisplayed(70) ; this line could/should be moved to the actual stage instead.
    endif
EndEvent
Edited by BigAndFlabby
Link to comment
Share on other sites

Thanks, this works perfectly. Wouldn't have been able to make the quest I wanted without it.

 

You can probably guess I just make up the scripting as I go along.

 

I just have a couple of questions.

 

The "finalStage" property isn't used at any point within the script, should the line be:

myQuest.SetStage(finalStage)

Also if you had the line at the start:

int Property myQuest Auto Const Mandatory

Would you then be able to just change the quest it applies to by setting the constant without having to change every line of the script that it appears on?

 

The script works fine without these changes I'm just trying to get my head around scripting.

 

Thanks again.

Link to comment
Share on other sites

Thanks, this works perfectly. Wouldn't have been able to make the quest I wanted without it.

 

You can probably guess I just make up the scripting as I go along.

 

I just have a couple of questions.

 

The "finalStage" property isn't used at any point within the script, should the line be:

myQuest.SetStage(finalStage)

Also if you had the line at the start:

int Property myQuest Auto Const Mandatory

Would you then be able to just change the quest it applies to by setting the constant without having to change every line of the script that it appears on?

 

The script works fine without these changes I'm just trying to get my head around scripting.

 

Thanks again.

 

Ah yeah sorry. The SetStage(70) could be as you said SetStage(finalStage). Personally I would move the SetObjectiveDisplayed right after it into the stage that was just set. It makes more sense to be there to me. That way if you re-use the script on other aliases you don't need to worry about setting the objective in the script, just in the accompanying stage which may be unique to each quest.

 

The myQuest is deliberately a function local variable. It's only there for convenience so instead of calling GetOwningQuest() every time I wanted to reference the quest I just use myQuest. The point of doing it that way is that it will automatically get the quest that this reference alias is on. So you never have to explicitly tell it. If you wanted to reference a different quest however, then you would need to point to another quest using a property. You would define that like this

Quest Property myOtherQuest Auto Const Mandatory

The Mandatory just means that it will show up red in the CK properties. I don't think CK actually enforces saying you must fill it. It might show up in the warning log, but I've never failed to fill one out to find out. More on that can be found here https://www.creationkit.com/fallout4/index.php?title=Flag_Reference

Edited by BigAndFlabby
Link to comment
Share on other sites

Hey guys, thanks so much for this thread. I have been following it because I knew I would probably need something like this while making my current quest.
I did use it today and it works perfectly.

 

One extra line I added is to reset the Global to 0 once the final stage has been set, I am planning to reuse the same script later and it will avoid creating a new Global each time I want to use the script

    if myBossDeathCounter.GetValue() >= AmountofBossestoKill
       myQuest.SetStage(FinalStage)
       myBossDeathCounter.SetValue(0)
    Endif 

One extra line I added is to reset the Global to 0 once the final stage has been set, if you are planning to reuse the same script later and avoid creating a new Global each time

Link to comment
Share on other sites

Hey guys, thanks so much for this thread. I have been following it because I knew I would probably need something like this while making my current quest.

I did use it today and it works perfectly.

 

One extra line I added is to reset the Global to 0 once the final stage has been set, I am planning to reuse the same script later and it will avoid creating a new Global each time I want to use the script

    if myBossDeathCounter.GetValue() >= AmountofBossestoKill
       myQuest.SetStage(FinalStage)
       myBossDeathCounter.SetValue(0)
    Endif 

One extra line I added is to reset the Global to 0 once the final stage has been set, if you are planning to reuse the same script later and avoid creating a new Global each time

 

You should be able to use the same script on multiple quests without any problem. You just need to assign the proper global to the property.

 

Unless you're absolutely sure that the 2 quests you'll be running will never run at the same time, using the same global again can be problematic. It's generally better practice to use a global per quest or such. The amount of plugin space and memory it uses is negligible for a second global.

Link to comment
Share on other sites

  • 2 years later...

Very sorry to revive a 3 year old thread, but I'm using this script and having trouble with it :(

Right now for testing, I'm only using 2 enemies.

I made a new global variable, and set the script on each enemy to point to that variable, but it doesn't seem like killing the enemies is affecting it at all.

Killing both enemies is supposed to move the stage forward, but nothing happens.

Everything up to that point works just fine though.

here's what my version of the script looks like


Scriptname KillCountScript extends ReferenceAlias

Int Property QuestObjective Auto

Int Property QuestStage Auto

GlobalVariable Property KillCountProperty Auto

Event OnDying(Actor akKiller)
Quest myQuest = GetOwningQuest()
myQuest.SetObjectiveCompleted(10)
KillCountProperty.SetValue(KillCountProperty.GetValue() + 1)

if KillCountProperty.GetValue() >= 2
myQuest.SetStage(20)
endif

EndEvent

; Killing this actor completes obj 10, add +1 to the KillCountProperty, and if the value meets the requirement-sets the stage to 20, completing the quest.

 

 

 

 

Have any idea why this isn't working? It seems like it should work just fine. But then again I don't know very much about scripting. Any help is much appreciated.

Link to comment
Share on other sites

Have you set the NPC's up as a Reference Alias in the quest you are using? Because for this script you need to set that up and attach it to the reference alias, rather than directly to the NPC.

 

You can also change the line to

myQuest.SetObjectiveCompleted(ActorObjective)

Where "Actor Objective" is and integer variable. Then you can use the same script on both NPCs but have a different objective for each.

Link to comment
Share on other sites

Since this has been necro'd already, something I should have noticed and pointed out long ago.

 

Make the global update thread safe.

KillCountProperty.SetValue(KillCountProperty.GetValue() + 1)

Should be written

KillCountProperty.Mod(1)

This will ensure that during the modification operation there's no chance that the script may be suspended and the global modified by someone else first.

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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