Difference between revisions of "Scripting AddItem Holotape Using OnMenuOpenCloseEvent"

From the Fallout4 CreationKit Wiki
Jump to navigation Jump to search
imported>0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
m (minor corrections and formatting)
imported>0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
(Reformatted and updated tutorial for clarity and better instructions, and corrected egregious persistence error)
 
Line 1: Line 1:
= Overview =
This tutorial is designed to teach the reader to add a [[Quest]] item, in this case a [[Holotape]], to the player inventory when the player opens the [[Menu|PipboyMenu]].


There are several ways to do this. This is but one example.
'''The reader will learn:'''
* How to set up a simple, "dummy" Quest
* How to create a [[Reference Alias]]
* How to fill that Reference Alias with a quest script
= The Quest =
The quest will need to be enabled at start, will have two stages, and will contain a reference alias with a Specific Reference Fill Type. It is not designed to show up in the player menu so it will not have a Type, Location, or a Quest Group. The script is designed to stop the quest after which time the object can be dropped by the player.


This will add a persistent quest item, in this case a holotape, to the player inventory when the player opens the PipboyMenu.
First, let's create the quest.
* In the [[Object Window]], navigate to Character > Quests
* On any of the quests on the right panel, Right Click > New
* Give the quest a unique Editor ID (EDID) and a name.  


There are several ways to do this. This is but one example.
For purposes of this tutorial, we've named it <code>OLT_HolotapeOnOpenCloseMenuQuest</code>. Because it is a "dummy" Quest that will not show in the player inventory and will only run "behind the scenes," you can give a brief description of what the quest does for your eyes only.
 
The quest we are creating will be set to Start Game Enabled, and we only want the quest to run once so [[OnInit_-_ScriptObject|OnInit]] will not fire twice.


== Quest Set up ==
* Check the boxes for Start Enabled, Run Once, and Warn on Alias Failure
The quest will need to be enabled at start, will have two stages, and will contain a reference alias with a Specific Reference Fill Type.
* Leave the priority at 0. While the quest has a Reference Alias, it does not have dialogue, so dialogue and AI package overrides to vanilla NPCs should not be an issue.


'''Creation:'''
* Create a quest that is Start Enabled, Run Once. For easy reference later, fill in Object Window Filter with your NameSpace. You'll be able to easily go to Character > Quests > YourNameSpace to find your new quest.
[[File:Ck_1.PNG]]
[[File:Ck_1.PNG]]
* Create two stages - 10 and 20.


* Fill in a namespace under Object Window Filter so that you can easily find it in the [[Script Object]]s panel of the Object Window.
<blockquote>[[File:InDepth_Nerd.png|left|140px]]
'''Note:'''
* The Quest form only gives a few tabs when first creating a quest. You'll need to save it after initial creation in order to fully edit it.
* For easy reference later, make use of the Object Window Filter. You'll be able to easily go to Character > Quests > YourNamespace to find your new quest.
* If you do not have your Warnings visible in case of Alias fill failure, navigate to View > Warnings. Setting a [[Layout]] color for the warnings window for <code><CURRENT></Code> warnings, will allow you to easily find the warning and double click on it. Most warnings will pop up the form where the warning is located.
* If "Start Game Enabled" is not also flagged to "Run Once," the OnInit() Event will fire twice.
</blockquote>
We're done with the initial set up of our quest.
* Click "Ok" to save and close the quest to refresh it.


== Quest Stages ==
== Quest Stages ==
'''Stage 10:'''[[File:Ck_2.PNG|thumb|Fig. 2: Quest Stage 10]]
Now let's set up the quest stages. There are two: Stage 10 and Stage 20.
* Check Run on Start.  
 
* New Entry
* Return to the new Quest. All tabs available for quest creation are now shown.
* Navigate to the Quest Stages tab
 
The first stage is set up to run on start with a simple [[Debug_Script|Debug]] trace for [[Enable_Debug_Logging|Papyrus Logging]].
 
'''Stage 10:'''
* Check the box for "Run on Start".  
* On the left panel Right Click > New to add a new index.
* Fill in the index number with "10".
* On the stage items panel Right Click > New to add the new entry to the stage index.
* Add designer notes, such as "Start Up".
* Add designer notes, such as "Start Up".
* Add the following papyrus fragment:
* Add the following papyrus fragment:


== Stage 10 Papyrus Fragment ==
=== Stage 10 Papyrus Fragment ===
The [[Quest_Stage_Fragments|Quest Stage Fragment]] for this quest is as follows:
<source lang="papyrus">
<source lang="papyrus">


Line 27: Line 64:


</source>
</source>
This is just a simple trace. It isn't necessary but it's useful if something goes south.
[[File:Ck_2.PNG]]
 
* Click compile
* Click "OK" to save and close the Quest to save the new fragment.
 
'''Renaming the fragment'''
 
For organizational purposes and efficient asset tracking for both the mod author and end-user, we're going to rename the fragment with our mod's unique namespace. Namespaces are subfolders within the data folder where the fragment will be output by the editor.
 
* Return to your quest.
* Navigate to Quest Stages and click on the Advanced tab.
* click Rename Script.
* For tutorial purposes, rename the script to <code>QF_OLT_HolotapeOnOpenCloseMenuScript</code> and the Namespace to <code>OLT:Example:Fragments:Quests</code>.
* Click Papyrus Fragment tab and click "Compile."
* Click "Ok" to save and exit the Quest tab to refresh the script fragment.
 


<blockquote>[[File:InDepth_Nerd.png|left|85px]]
'''Note'''


'''Stage 20:'''[[File:Ck_3.PNG|thumb|Fig. 3: Quest Stage 20]]
* You will not have to do any renaming for the next fragment. Everything will be set up for data entry.
* New Entry
* If you want the quest item to remain persistent, do not add stage 20.
* Add designer notes, such as shut down.
</blockquote>
* Check complete quest
 
 
'''Stage 20:'''
* On the left panel Right Click > New to add a new index.  
* Fill in the index number with "20".
* On the stage items panel Right Click > New to add the new entry to the stage index.
* Add designer notes, such as "Shut down".
* Check the box for "Complete Quest".
* Add the following papyrus fragment:
* Add the following papyrus fragment:


== Stage 20 Papyrus Fragment ==
=== Stage 20 Papyrus Fragment ===
<source lang="papyrus">
<source lang="papyrus">
debug.trace(self + "stage 20 - shutting down")
debug.trace(self + "stage 20 - shutting down")
Line 45: Line 106:
</source>
</source>
This will complete the quest once the Quest script has run its functions.
This will complete the quest once the Quest script has run its functions.
* Click "Compile".
* Click "Ok" to save quest and new fragment number.
[[File:Ck_3.PNG]]




== Reference Alias ==  
== Reference Alias ==  
[[File:Ck_4.PNG|thumb|Fig. 1: Reference Alias]]
Now let's set up the persistent reference.
* Quests tab: Create a Reference Alias. For purposes of this example, the name of the alias is <code>SettingsHolotape</code>.  
* Return to your quest and navigate to the Quest Aliases tab
* Create a Reference Alias by Right Click > New Reference Alias. For purposes of this example, the name of the alias is <code>SettingsHolotape</code>.  
* Fill type: Specific Reference (none).  
* Fill type: Specific Reference (none).  
* Check: Optional, Quest Object, Reserves Reference, Allow Reuse in Quest, Allow Disabled
* Check: Optional, Quest Object, Reserves Reference, Allow Reuse in Quest, Allow Disabled
* Click "Ok" to save and exit the Reference Alias window and "Ok" on the quest to save and refresh the quest.


[[File:Ck_4.PNG]]


== Quest Script ==
= The Quest Script =
On the Scripts tab, attach a new script:[[File:Ck_5.PNG|thumb|Fig. 4: Quest Script Properties]]
* Open the quest and Navigate to the Scripts Tab.
* Click "Add" to attach a new script to the quest.
* Select <nowiki>[New Script]</nowiki> and Click "Ok."
* Give your script a new name and add it to your mod's Namespace.
* Copy and paste the following code (rename "YourNameSpace" to the Namespace of your mod):


<source lang="papyrus">
<source lang="papyrus">
Line 100: Line 174:
;Add the holotape
;Add the holotape
TryToAddSettingsHolotape()
TryToAddSettingsHolotape()
;comment this section out if you wish the holotape to remain a persistent quest item


; we done
; we done
                  SetStage(StageToSet)
            SetStage(StageToSet)
endif
        endif
endif
endif


Line 113: Line 189:
Alias_SettingsHolotape.ForceRefTo(TapeRef)
Alias_SettingsHolotape.ForceRefTo(TapeRef)


        ;count the amount of actual tapes instead of the ref
    ;count the amount of actual tapes instead of the ref
int currentCount = PlayerRef.GetItemCount(HolotapeRef)
int currentCount = PlayerRef.GetItemCount(HolotapeRef)
Line 125: Line 201:


</source>
</source>
If you do not want a pop-up indicating the player has received the holotape, change <code>PlayerRef.AddItem(TapeRef, maxHolotapeCount, false)</code> to <code> PlayerRef.AddItem(TapeRef, maxHolotapeCount, true)</code>. See [[AddItem_-_ObjectReference]].


== Usage ==
* Compile your script by clicking Ctrl + S.
 
 
= Usage =
*This is specifically for compatibility with mods that skip the prologue but should also work during debug if coc'ing directly from main menu with default character.
*This is specifically for compatibility with mods that skip the prologue but should also work during debug if coc'ing directly from main menu with default character.
= Customization =
* If you do not want a pop-up indicating the player has received the holotape, change <code>PlayerRef.AddItem(TapeRef, maxHolotapeCount, false)</code> to <code> PlayerRef.AddItem(TapeRef, maxHolotapeCount, true)</code>. See [[AddItem_-_ObjectReference]].
* If you want the quest item to remain persistent and cannot be dropped and lost by the player, comment out <code>SetStage(StageToSet)</code> and do not create stage 20.


== See Also ==
== See Also ==

Latest revision as of 13:12, 3 June 2020

Overview[edit | edit source]

This tutorial is designed to teach the reader to add a Quest item, in this case a Holotape, to the player inventory when the player opens the PipboyMenu.

There are several ways to do this. This is but one example.

The reader will learn:

  • How to set up a simple, "dummy" Quest
  • How to create a Reference Alias
  • How to fill that Reference Alias with a quest script

The Quest[edit | edit source]

The quest will need to be enabled at start, will have two stages, and will contain a reference alias with a Specific Reference Fill Type. It is not designed to show up in the player menu so it will not have a Type, Location, or a Quest Group. The script is designed to stop the quest after which time the object can be dropped by the player.

First, let's create the quest.

  • In the Object Window, navigate to Character > Quests
  • On any of the quests on the right panel, Right Click > New
  • Give the quest a unique Editor ID (EDID) and a name.

For purposes of this tutorial, we've named it OLT_HolotapeOnOpenCloseMenuQuest. Because it is a "dummy" Quest that will not show in the player inventory and will only run "behind the scenes," you can give a brief description of what the quest does for your eyes only.

The quest we are creating will be set to Start Game Enabled, and we only want the quest to run once so OnInit will not fire twice.

  • Check the boxes for Start Enabled, Run Once, and Warn on Alias Failure
  • Leave the priority at 0. While the quest has a Reference Alias, it does not have dialogue, so dialogue and AI package overrides to vanilla NPCs should not be an issue.

Ck 1.PNG

  • Fill in a namespace under Object Window Filter so that you can easily find it in the Script Objects panel of the Object Window.
InDepth Nerd.png

Note:

  • The Quest form only gives a few tabs when first creating a quest. You'll need to save it after initial creation in order to fully edit it.
  • For easy reference later, make use of the Object Window Filter. You'll be able to easily go to Character > Quests > YourNamespace to find your new quest.
  • If you do not have your Warnings visible in case of Alias fill failure, navigate to View > Warnings. Setting a Layout color for the warnings window for <CURRENT> warnings, will allow you to easily find the warning and double click on it. Most warnings will pop up the form where the warning is located.
  • If "Start Game Enabled" is not also flagged to "Run Once," the OnInit() Event will fire twice.

We're done with the initial set up of our quest.

  • Click "Ok" to save and close the quest to refresh it.

Quest Stages[edit | edit source]

Now let's set up the quest stages. There are two: Stage 10 and Stage 20.

  • Return to the new Quest. All tabs available for quest creation are now shown.
  • Navigate to the Quest Stages tab

The first stage is set up to run on start with a simple Debug trace for Papyrus Logging.

Stage 10:

  • Check the box for "Run on Start".
  • On the left panel Right Click > New to add a new index.
  • Fill in the index number with "10".
  • On the stage items panel Right Click > New to add the new entry to the stage index.
  • Add designer notes, such as "Start Up".
  • Add the following papyrus fragment:

Stage 10 Papyrus Fragment[edit | edit source]

The Quest Stage Fragment for this quest is as follows:

debug.trace(self + "stage 10 - start up")

Ck 2.PNG

  • Click compile
  • Click "OK" to save and close the Quest to save the new fragment.

Renaming the fragment

For organizational purposes and efficient asset tracking for both the mod author and end-user, we're going to rename the fragment with our mod's unique namespace. Namespaces are subfolders within the data folder where the fragment will be output by the editor.

  • Return to your quest.
  • Navigate to Quest Stages and click on the Advanced tab.
  • click Rename Script.
  • For tutorial purposes, rename the script to QF_OLT_HolotapeOnOpenCloseMenuScript and the Namespace to OLT:Example:Fragments:Quests.
  • Click Papyrus Fragment tab and click "Compile."
  • Click "Ok" to save and exit the Quest tab to refresh the script fragment.


InDepth Nerd.png

Note

  • You will not have to do any renaming for the next fragment. Everything will be set up for data entry.
  • If you want the quest item to remain persistent, do not add stage 20.


Stage 20:

  • On the left panel Right Click > New to add a new index.
  • Fill in the index number with "20".
  • On the stage items panel Right Click > New to add the new entry to the stage index.
  • Add designer notes, such as "Shut down".
  • Check the box for "Complete Quest".
  • Add the following papyrus fragment:

Stage 20 Papyrus Fragment[edit | edit source]

debug.trace(self + "stage 20 - shutting down")

;stop quest
Stop()

This will complete the quest once the Quest script has run its functions.


  • Click "Compile".
  • Click "Ok" to save quest and new fragment number.

Ck 3.PNG


Reference Alias[edit | edit source]

Now let's set up the persistent reference.

  • Return to your quest and navigate to the Quest Aliases tab
  • Create a Reference Alias by Right Click > New Reference Alias. For purposes of this example, the name of the alias is SettingsHolotape.
  • Fill type: Specific Reference (none).
  • Check: Optional, Quest Object, Reserves Reference, Allow Reuse in Quest, Allow Disabled
  • Click "Ok" to save and exit the Reference Alias window and "Ok" on the quest to save and refresh the quest.

Ck 4.PNG

The Quest Script[edit | edit source]

  • Open the quest and Navigate to the Scripts Tab.
  • Click "Add" to attach a new script to the quest.
  • Select [New Script] and Click "Ok."
  • Give your script a new name and add it to your mod's Namespace.
  • Copy and paste the following code (rename "YourNameSpace" to the Namespace of your mod):
Scriptname YourNameSpace:AddHolotapeOnMenuOpenCloseScript extends Quest

Group Required_Properties

	Holotape Property HolotapeRef auto const
	{the holotape we're forcing into the player inventory}
	ReferenceAlias Property Alias_SettingsHolotape auto const mandatory
	{autofill}
	Actor Property PlayerRef auto const mandatory
	{autofill}
	
	int Property StageToSet = 20 auto const
	{default stage = 20 - only change this number if using a different shutdown stage number}

EndGroup

;holotapes in the inventory
int maxHolotapeCount = 1 const

Event OnQuestInit()

	; Register for the pipboy opening
	RegisterForMenuOpenCloseEvent("PipboyMenu")
	
	; wait for player input
	while utility.IsInMenuMode()
		utility.wait(0.2)
	endwhile

EndEvent


Event OnMenuOpenCloseEvent(string asMenuName, bool abOpening)

	if (asMenuName == "PipboyMenu")
		
		if abOpening 
			Debug.Trace(self + " PlayerRef has opened " + asMenuName)
		
			;Add the holotape
			TryToAddSettingsHolotape()

			;comment this section out if you wish the holotape to remain a persistent quest item

			; we done
            SetStage(StageToSet)
         endif
	endif

endEvent

Function TryToAddSettingsHolotape()

	ObjectReference TapeRef = PlayerRef.PlaceAtMe(HolotapeRef)
	Alias_SettingsHolotape.ForceRefTo(TapeRef)

    ;count the amount of actual tapes instead of the ref
	int currentCount = PlayerRef.GetItemCount(HolotapeRef)
	
	if currentCount < maxHolotapeCount
		PlayerRef.AddItem(TapeRef, maxHolotapeCount, false)
		debug.trace(self + "Holotape has been added to player inventory")
	endif
	
EndFunction
  • Compile your script by clicking Ctrl + S.


Usage[edit | edit source]

  • This is specifically for compatibility with mods that skip the prologue but should also work during debug if coc'ing directly from main menu with default character.

Customization[edit | edit source]

  • If you do not want a pop-up indicating the player has received the holotape, change PlayerRef.AddItem(TapeRef, maxHolotapeCount, false) to PlayerRef.AddItem(TapeRef, maxHolotapeCount, true). See AddItem_-_ObjectReference.
  • If you want the quest item to remain persistent and cannot be dropped and lost by the player, comment out SetStage(StageToSet) and do not create stage 20.


See Also[edit | edit source]