Difference between revisions of "GetFormFromFile - Game"

From the CreationKit Wiki
Jump to navigation Jump to search
imported>JustinOther
m (bPluginArray Δ bDLCArray)
imported>JustinOther
m (→‎Examples: Omitted '> 0' as iIndex is cast as 'False' when it counts down to 0, ending the loop on time after all.)
 
(15 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:Scripting]]
[[Category:Scripting]]
[[Category:Papyrus]]
[[Category:Papyrus]]
[[Category:Non-delayed Native Function]]
'''Member of:''' [[Game Script]] ''(Requires 1.6)''
'''Member of:''' [[Game Script]] ''(Requires 1.6)''


Line 31: Line 32:
*To merely detect if a plugin is loaded.
*To merely detect if a plugin is loaded.
<source lang="papyrus">Bool bIsBagOfHoldingLoaded = Game.GetFormFromFile(0x000012EE, "Bag of Holding.esp") ; Is Bag of Holding.esp loaded?</source>
<source lang="papyrus">Bool bIsBagOfHoldingLoaded = Game.GetFormFromFile(0x000012EE, "Bag of Holding.esp") ; Is Bag of Holding.esp loaded?</source>
*Say you want to detect if DLCs are loaded and need to do/undo something in the event a DLC is added or removed from the user's load list: Create a boolean and string array, each with one element per DLC to check. When setting up the properties, leave the boolean elements with their default 'False' values and set each string element with the exact name of the plugin to check for such that their indices correspond. For this to work, the '000000' instances must be changed to match a known existing FormID in each plugin.
*Say you want to detect if DLCs are loaded and need to do/undo something in the event a DLC is added or removed from the user's load list: Create a Boolean, Int, and String array, each with one element per DLC to check such that the indices of all three correspond. Leave the boolean elements with their default 'False' values and set each string element with the exact name of the plugin to check for. For this to work, the Int[] elements must match known existing FormIDs in the corresponding plugins converted from Hex to Dec (easily done with Windows' calculator in programmer mode).
<source lang="papyrus">Bool[] Property bDLCArray Auto
<source lang="papyrus">Bool[] Property bDLCIsLoaded Auto ; Element 0 is bDawnguard, etc.
String[] Property sDLCArray Auto
Int[] Property iKnownFormID Auto ; Element 0 is 2048 for Dawnguard's DLC1AurielsBow "Auriel's Bow" [WEAP:02000800], etc.
String[] Property sDLCName Auto ; Element 0 is Dawnguard.ESM, Element 1 is HearthFires.ESM, element 2 is Dragonborn.ESM, etc.


Function CheckForDLC(Int aiIndex = 0, String asDLCName = "")
Function CheckForDLC()
aiIndex = bDLCArray.Length
Int iIndex = sDLCName.Length
While aiIndex > 0
While iIndex
aiIndex -= 1
iIndex -= 1
If aiIndex == 0 ; Dawnguard.ESM
If bDLCIsLoaded[iIndex] != Game.GetFormFromFile(iKnownFormID[iIndex], sDLCName[iIndex])
If bDLCArray[aiIndex] != Game.GetFormFromFile(0x00000000 sPluginArray[aiIndex])
bDLCIsLoaded[iIndex] = !bDLCIsLoaded[iIndex]
bDLCArray[aiIndex] = !DLCArray[aiIndex]
If bDLCIsLoaded[iIndex]
If bDLCArray[aiIndex]
Debug.Trace(sDLCName[iIndex] + " is loaded")
Debug.Trace("Dawnguard.ESM is loaded")
If iIndex == 0 ; Dawnguard
Else
; Make any changes needed for Dawnguard
Debug.Trace("Dawnguard.ESM was loaded, but is no longer")
ElseIf iIndex == 1 ; Hearthfire
; Make any changes needed for Hearthfire
ElseIf iIndex == 2 ; Dragonborn
; Make any changes needed for Dragonborn
EndIf
EndIf
EndIf
Else
ElseIf aiIndex == 1 ; Hearthfire.ESM
Debug.Trace(sDLCName[iIndex] + " was loaded, but is no longer")
If bDLCArray[aiIndex] != Game.GetFormFromFile(0x00000000, sPluginArray[aiIndex])
If iIndex == 0 ; Dawnguard
bDLCArray[aiIndex] = !DLCArray[aiIndex]
; Revert any changes previously made for Dawnguard
If bDLCArray[aiIndex]
ElseIf iIndex == 1 ; Hearthfire
Debug.Trace("Hearthfire.ESM is loaded")
; Revert any changes previously made for Hearthfire
Else
ElseIf iIndex == 2 ; Dragonborn
Debug.Trace("Hearthfire.ESM was loaded, but is no longer")
; Revert any changes previously made for Dragonborn
EndIf
EndIf
EndIf
EndIf
ElseIf aiIndex == 2 ; KillerBees.esp
If bDLCArray[aiIndex] != Game.GetFormFromFile(0x0000ABCD, sPluginArray[aiIndex])
bDLCArray[aiIndex] = !DLCArray[aiIndex]
If bDLCArray[aiIndex]
Debug.Trace("KillerBees.esp izzz loaded")
Else
Debug.Trace("KillerBees wazzz loaded, but izzz no longer")
EndIf
EndIf
ElseIf aiIndex == 3 ; DLC04.ESM
; etc.
ElseIf aiIndex == 4 ; DLC05.ESM
; etc.
EndIf
EndIf
EndWhile
EndWhile
EndFunction</source>
EndFunction</source>
== Notes ==
== Notes ==
*If asFilename is not loaded, it will be reported in one's log.
*If asFilename is not loaded, it will be reported in one's log.
*Don't forget to cast if setting a property to any given form type with GetFormFromFile.
*Don't forget to cast if setting a property to any given form type with GetFormFromFile.
*Almost invariably, a plugin will have a form with 0x00000800 or 0x00000D62 as its FormID. The latter for a plugin that is masterless when its first form is created and the former when another plugin is loaded at that time. Checking for both FormIDs in most plugins will suffice to merely determine if asFileName is loaded, but there's always the possibility the first form added gets deleted in which case you'd get a false negative. Whenever possible, use a verified FormID that is likely to remain in asFileName.
== See Also ==
== See Also ==
*[[Game Script]]
*[[Game Script]]
*[[GetForm - Game]]
*[[GetForm - Game]]
*[[GetFormID - Form]]
*[[GetFormID - Form]]
*[[Arrays (Papyrus)#Creating_a_FormID Array|FormID Array]]

Latest revision as of 22:39, 17 January 2013

Member of: Game Script (Requires 1.6)

Obtains the form specified by its form ID number which originated in the specified file. The ID for a form changes based on the load order of the file it loaded from. So a form which shows up as 0101ABCD in the editor may show up as 0401ABCD in game depending on how many other files load before it. This function lets you blindly grab a form based on the lower bytes of its ID and the expected file which created the form.

Syntax[edit | edit source]

Form Function GetFormFromFile(int aiFormID, string asFilename) native global

Parameters[edit | edit source]

  • aiFormID: The form ID number of the form we want. (FormID proceeded by 0x) For example Form ID "0001ABCD" is given as: 0x0001ABCD
  • asFilename: The name of the file we expect the form to have originated in.

Return Value[edit | edit source]

The requested Form, or None if the form ID is not valid or the file does not exist or is not loaded.

Examples[edit | edit source]

  • Assume a mod or DLC called "KillerBees.esp" was released which made the bee critters agressive and immortal, only killable by weapons in the form list BeeKillerWeapList (0100ABCD). Another mod or DLC wants to add a BeeSlayer sword which they want to be able to kill the killer bees if you have that mod.
; Obtain form 0000ABCD we expect to be added by the KillerBees plugin
; Note the top most byte in the given ID is unused so 0000ABCD works as well as 0400ABCD
FormList beekillerlist = Game.GetFormFromFile(0x0000ABCD, "KillerBees.esp") As FormList
; If "KillerBees.esp" is not loaded the form will be NONE. Otherwise, add our weapon to the list.
if ( beekillerlist )
  beekillerlist.AddForm( WeapBeeSlayer )
endif
  • To merely detect if a plugin is loaded.
Bool bIsBagOfHoldingLoaded = Game.GetFormFromFile(0x000012EE, "Bag of Holding.esp") ; Is Bag of Holding.esp loaded?
  • Say you want to detect if DLCs are loaded and need to do/undo something in the event a DLC is added or removed from the user's load list: Create a Boolean, Int, and String array, each with one element per DLC to check such that the indices of all three correspond. Leave the boolean elements with their default 'False' values and set each string element with the exact name of the plugin to check for. For this to work, the Int[] elements must match known existing FormIDs in the corresponding plugins converted from Hex to Dec (easily done with Windows' calculator in programmer mode).
Bool[] Property bDLCIsLoaded Auto ; Element 0 is bDawnguard, etc.
Int[] Property iKnownFormID Auto ; Element 0 is 2048 for Dawnguard's DLC1AurielsBow "Auriel's Bow" [WEAP:02000800], etc.
String[] Property sDLCName Auto ; Element 0 is Dawnguard.ESM, Element 1 is HearthFires.ESM, element 2 is Dragonborn.ESM, etc.

Function CheckForDLC()
	Int iIndex = sDLCName.Length
	While iIndex
		iIndex -= 1
		If bDLCIsLoaded[iIndex] != Game.GetFormFromFile(iKnownFormID[iIndex], sDLCName[iIndex])
			bDLCIsLoaded[iIndex] = !bDLCIsLoaded[iIndex]
			If bDLCIsLoaded[iIndex]
				Debug.Trace(sDLCName[iIndex] + " is loaded")
				If iIndex == 0 ; Dawnguard
					; Make any changes needed for Dawnguard
				ElseIf iIndex == 1 ; Hearthfire
					; Make any changes needed for Hearthfire
				ElseIf iIndex == 2 ; Dragonborn
					; Make any changes needed for Dragonborn
				EndIf
			Else
				Debug.Trace(sDLCName[iIndex] + " was loaded, but is no longer")
				If iIndex == 0 ; Dawnguard
					; Revert any changes previously made for Dawnguard
				ElseIf iIndex == 1 ; Hearthfire
					; Revert any changes previously made for Hearthfire
				ElseIf iIndex == 2 ; Dragonborn
					; Revert any changes previously made for Dragonborn
				EndIf
			EndIf
		EndIf
	EndWhile
EndFunction

Notes[edit | edit source]

  • If asFilename is not loaded, it will be reported in one's log.
  • Don't forget to cast if setting a property to any given form type with GetFormFromFile.
  • Almost invariably, a plugin will have a form with 0x00000800 or 0x00000D62 as its FormID. The latter for a plugin that is masterless when its first form is created and the former when another plugin is loaded at that time. Checking for both FormIDs in most plugins will suffice to merely determine if asFileName is loaded, but there's always the possibility the first form added gets deleted in which case you'd get a false negative. Whenever possible, use a verified FormID that is likely to remain in asFileName.

See Also[edit | edit source]