Jump to content

GetFormFromFile difficulty


Recommended Posts

I have the following in an MCM menu:

Event OnKeyDown(Int code)

If code == ess_hotkey && !Utility.IsInMenuMode()

;debug.messagebox("essential toggle pressed")

scriptRef_things = (Game.GetFormFromFile(0x00000800, "dz_little_things.esp") as dz_little_things_script)

scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

   debug.messagebox(scriptRef_hfclean)

   debug.messagebox(scriptRef_things)

 

  ;scriptRef_things.dz_essential_toggle()

EndIf

EndEvent

the onkeydown is working because I get a message box with the result of scriptRef_hfclean

but the messagebox for scriptRef_things just says NONE

however both esp names are correct, both scriptnames are correct and both lower order formids are correct.

both esps are active and at the beginning of the script I have:

dz_hearthfire_cleanup_script scriptRef_hfclean
dz_little_things_script scriptRef_things

there must be something else, perhaps outside the script that makes one work and not the other,

any suggestions?

 

diziet

Link to comment
Share on other sites

scriptRef_things = (Game.GetFormFromFile(0x00000800, "dz_little_things.esp") as dz_little_things_script)

 

With this line you are telling papyrus to go fetch the form with the ID 0x00000800 within the ESP dz_little_things and then cast it to the script.

 

You discovered that it will only work when the script extends ObjectReference rather than Actor.

 

Why? The form with the ID 0x00000800 is most likely pointing to an ObjectReference form (i.e. a pre-placed actor). If you had cast the returning form into the appropriate type(s) then you would not have needed to change the script.

 

For example:

scriptRef_things = (((Game.GetFormFromFile(0x00000800,"dz_little_things.esp") as ObjectReference) as Actor) as dz_little_things_script)

Link to comment
Share on other sites

Put like that it makes sense, but leaves me wondering why it ever worked before since, in both cases:

scriptRef_things = (Game.GetFormFromFile(0x00000800, "dz_little_things.esp") as dz_little_things_script)
scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

the intent is to run a function or access a variable that are on the scripts, in each case the esps may or may not exist e.g.

scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

  scriptRef_hfclean.dz_state_windstad(toggle_cleanup_windstad)

  If scriptRef_hfclean.wind_first_run == False

   ShowMessage("$haven't_finished_quest",False)

   toggle_cleanup_windstad = False

  EndIf

so the form will be that of an xmarker in each esp to which one of the scripts is attached:

 

 

 

So I'm not sure how I would follow your example of casting multiple times.

Fortunately I have managed to get my dz_little_things_script to compile extending Objectreference, so at the moment it's an academic confusion for me:)

 

Thanks for replying.

 

 

diziet

Link to comment
Share on other sites

The hfclean works because it is pointing to an ObjectReference (a pre-placed object). Same reason that the actor one ended up working when the script was changed to extend ObjectReference.

 

Script wise ObjectReference does extend Form, so casting would typically be: SomeForm as ObjectReference. But because pre-placed objects have their own formID already, fetching that with GetFormFromFile will yield the object reference form and it can then be cast into the script without explicitly casting into ObjectReference beforehand.

 

The same line with casting would appear as:

scriptRef_hfclean = ((Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as ObjectReference) as dz_hearthfire_cleanup_script)

 

Now because the mod may or may not exist, it might be smarter to not cast directly to the script but first check that the mod exists. Cause while GetFormFromFile will fail without in-game issue, the code following doesn't even need to try running (which it will) if the mod does not exist.

 

An adjustment as an example:

 

 

ObjectReference Ref_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as ObjectReference
If Ref_hfclean ;if a valid object - the mod exists
  scriptRef_hfclean = Ref_hfclean as dz_hearthfire_cleanup_script
  scriptRef_hfclean.dz_state_windstad(toggle_cleanup_windstad)
  If scriptRef_hfclean.wind_first_run == False
    ShowMessage("$haven't_finished_quest",False)
    toggle_cleanup_windstad = False
  EndIf
EndIf 

 

 

Link to comment
Share on other sites

the line:

scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

appears in an mcm menu that only appears if a check for the mod's existence succeeds

misc_menus_script

 

 

ScriptName dz_misc_mcm_menu_script Extends SKI_ConfigBase
import FissFactory

String[] page_names

Actor Property PlayerRef Auto
;;;variables for diziet's drafting table remover mod mcm menu;;;

Bool toggle_cleanup_lakeview               ;enable/disable draftint tables

Bool toggle_cleanup_heljarchen               ;enable/disable draftint tables

Bool toggle_cleanup_windstad               ;enable/disable draftint tables
dz_hearthfire_cleanup_script scriptRef_hfclean           ;access diziet's drafting table remover mod script

;;;----------------------------------------------------------;;;
;;;variables for diziet's little things;;;

Int ess_hotkey = 24

Int null_key = -1

dz_little_things_script scriptRef_things            ;access diziet's little things script

Float carry

;;;----------------------------------------------------------;;;
Int Function GetVersion()                ;version function

Return 2 ; Default version

EndFunction
Event OnConfigInit()



EndEvent
Event OnConfigOpen()

;;;max number of supported mods is two;;;

;;;hearthfire cleanup aka Diziet's Drafting Table Remover;;;

page_names = New String[3]               ;max size of page_names array
;;;test for number of installed diziet misc mods;;;

Int i = 0

If Game.IsPluginInstalled("dz_hearthfire_cleanup.esp")        ;check for diziet's drafting table remover mod

page_names[i] = "Drafting Tables"

  i += 1

EndIf



If Game.IsPluginInstalled("dz_little_things.esp")         ;check for diziet's little things

carry = PlayerRef.GetActorValue("CarryWeight") as Float

RegisterForKey(ess_hotkey)

page_names[i] = "Little Things"

  i += 1

EndIf

 

;;;number of menu pages needed is i;;;

If i == 1

  Pages = New String[1]

ElseIf i == 2

  Pages = New String[2]

EndIf
;;;set the names of the pages;;;

Int k = 0

While k < i

  Pages[k] = page_names[k]

  k +=1

EndWhile
EndEvent
Event OnVersionUpdate(Int a_version)

If (a_version >= 2 && CurrentVersion < 2)

  Debug.Trace(self + ": Updating Diziet's Misc MCM Menus script to version 2")

  Debug.Notification("Diziet's Misc MCM Menus updating to Version 2")

EndIf

EndEvent
Event OnPageReset(String a_page)

If a_page == ""                  ;exit if page  is ""

  ;ShowMessage("a_page = \"\" Returning",False)

  Return

EndIf
If a_page == "Drafting Tables"

  ;/ AddHeaderOption("Options for Diziet's Drafting Table Remover")

  AddEmptyOption()

  AddEmptyOption() /;

  SetCursorFillMode(TOP_TO_BOTTOM)            ;fill the page with toggles etc.

  AddEmptyOption()

  AddHeaderOption("$Lakeview_Cleanup")

  AddToggleOptionST("state_lakeview_cleanup","$cleanup_lakeview?",toggle_cleanup_lakeview)

  AddEmptyOption()

  AddHeaderOption("$Heljarchen_Cleanup")

  AddToggleOptionST("state_heljarchen_cleanup","$cleanup_heljarchen?",toggle_cleanup_heljarchen)

  AddEmptyOption()

  AddHeaderOption("$Windstad_Cleanup")

  AddToggleOptionST("state_windstad_cleanup","$cleanup_windstad?",toggle_cleanup_windstad)

EndIf
If a_page == "Little Things"

  SetCursorFillMode(TOP_TO_BOTTOM)            ;fill the page with toggles etc.

  AddHeaderOption("$select_key_essential")

  AddKeyMapOptionST("state_essential_hotkey","$set_essential_hotkey",ess_hotkey)

  AddToggleOptionST("state_null_essential_hotkey","$null_essential_hotkey",False)

  AddEmptyOption()

  AddEmptyOption()

  AddHeaderOption("$carryweight_cheat")

  AddSliderOptionST("state_carry_slider", "$choose_the_carryweight", carry)

 

EndIf

EndEvent


;;;the following states apply to the mod Diziet's Drafting Table Remover;;;

State state_lakeview_cleanup

Event OnSelectST()

  toggle_cleanup_lakeview = !toggle_cleanup_lakeview

  scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

  scriptRef_hfclean.dz_state_lakeview(toggle_cleanup_lakeview)

  If scriptRef_hfclean.lake_first_run == False

   ShowMessage("$haven't_finished_quest",False)

   toggle_cleanup_lakeview = False

  EndIf

  SetToggleOptionValueST(toggle_cleanup_lakeview)

EndEvent



Event OnDefaultST()

  toggle_cleanup_lakeview = False

  SetToggleOptionValueST(toggle_cleanup_lakeview)

EndEvent



Event OnHighlightST()

  SetInfoText("$remove_exterior_crafting_table_from_lakeview_manor")

EndEvent

EndState
State state_heljarchen_cleanup

Event OnSelectST()

  toggle_cleanup_heljarchen = !toggle_cleanup_heljarchen

  scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

  scriptRef_hfclean.dz_state_heljarchen(toggle_cleanup_heljarchen)

  If scriptRef_hfclean.helj_first_run == False

   ShowMessage("$haven't_finished_quest",False)

   toggle_cleanup_heljarchen = False

  EndIf

  SetToggleOptionValueST(toggle_cleanup_heljarchen)

EndEvent



Event OnDefaultST()

  toggle_cleanup_heljarchen = False

  SetToggleOptionValueST(toggle_cleanup_heljarchen)

EndEvent



Event OnHighlightST()

  SetInfoText("$remove_exterior_crafting_table_from_heljarchen_hall")

EndEvent

EndState
State state_windstad_cleanup

Event OnSelectST()

  toggle_cleanup_windstad = !toggle_cleanup_windstad

  scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

  scriptRef_hfclean.dz_state_windstad(toggle_cleanup_windstad)

  If scriptRef_hfclean.wind_first_run == False

   ShowMessage("$haven't_finished_quest",False)

   toggle_cleanup_windstad = False

  EndIf

  SetToggleOptionValueST(toggle_cleanup_windstad)

EndEvent



Event OnDefaultST()

  toggle_cleanup_windstad = False

  SetToggleOptionValueST(toggle_cleanup_windstad)

EndEvent



Event OnHighlightST()

  SetInfoText("$remove_exterior_crafting_table_from_windstad_manor")

EndEvent

EndState

;;;end of states for Diziet's Drafting Table Remover;;;
;;;the following states and functions apply to Diziet's Little Things;;;

State state_essential_hotkey

Event OnKeyMapChangeST(Int keyCode, String conflictControl, String conflictName)

  Bool continue = True

  If (conflictControl != "")

   String msg

  

   If (conflictName != "")

    msg = "$KeyMapConflict{" + conflictControl + "}{" + conflictName + "}"

   Else

    msg = "$KeyMapConflict{" + conflictControl + "}"

   EndIf
   continue = ShowMessage(msg, True, "$Yes_text", "$No_text")

  

  EndIf

 

  If (continue)

   ess_hotkey = keyCode

   SetKeyMapOptionValueST(keyCode)

  EndIf
  RegisterForKey(keyCode)

EndEvent

EndState
State state_null_essential_hotkey

Event OnSelectST()

  ess_hotkey = null_key

  SetKeyMapOptionValueST(null_key,False,"state_essential_hotkey")

EndEvent



EndState



State state_carry_slider

Event OnSliderOpenST()

  SetSliderDialogStartValue(carry)

  SetSliderDialogDefaultValue(300)

  SetSliderDialogRange(100,10000)

  SetSliderDialogInterval(10)

EndEvent



Event OnSliderAcceptST(float a_value)

  carry = a_value

  PlayerRef.SetActorValue("CarryWeight", carry)

  SetSliderOptionValueST(carry)

EndEvent



Event OnDefaultST()

  carry = 300

  SetSliderOptionValueST(carry)

EndEvent



Event OnHighlightST()

  SetInfoText("$carry_slide_info")

EndEvent



EndState


;;;the following functions are for FISSES;;;

;;;save function for Diziet's Little Things

Function dz_save_fiss_little_things()

;;;get a reference to the FISS Interface;;;

FISSInterface fiss = FISSFactory.getFISS()

;;;check if FISS is installed;;;

If !fiss

debug.messageBox("FISS not installed. Saving disabled")

Return

EndIf

;;;save variables;;

fiss.beginSave("diziets_little_things\\fiss.xml","little_things")

fiss.saveInt("ESSKEY", ess_hotkey)

String saveResult = fiss.endSave()

;;;check the result;;;

If saveResult != ""

debug.Trace(saveResult)

EndIf

EndFunction
Function dz_load_fiss_little_things()

;;;get a reference to the FISS Interface;;;

FISSInterface fiss = FISSFactory.getFISS()

;;;check if FISS is installed;;;

If !fiss

debug.messageBox("FISS not installed. Loading disabled")

Return

EndIf

;;;load variables;;;

fiss.beginLoad("diziets_little_things\\fiss.xml")

ess_hotkey = fiss.loadInt("ESSKEY")

EndFunction

;;;end of states and functions for Diziet's Little Things


;;;the following keydown events apply to all;;;

Event OnKeyDown(Int code)

If code == ess_hotkey

;debug.messagebox("essential toggle pressed")

scriptRef_things = (Game.GetFormFromFile(0x00000800, "dz_little_things.esp") as dz_little_things_script)

;scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

   ;debug.messagebox(scriptRef_hfclean)

   ;debug.messagebox(scriptRef_things)

  If scriptRef_things.secondpress == False

   scriptRef_things.dz_essential_toggle()

  ElseIf scriptRef_things.secondpress == True

   scriptRef_things.dz_setessential()

  EndIf

EndIf

EndEvent

 

 

 

hearthfire_cleanup_script

 

 

Scriptname dz_hearthfire_cleanup_script Extends ObjectReference;;this mod will be controlled by my misc mcm menus mod
;dz_misc_mcm_menu_script Property dz_mcm Auto;;;insert objects as properties here;;;---------------------;;;ObjectReference Property dz_new_lake_xmarker Auto
ObjectReference Property dz_new_helj_xmarker Auto
ObjectReference Property dz_new_wind_xmarker Auto;;;has this script been run before on any of the homes?;;;
Bool Property lake_first_run Auto
Bool Property helj_first_run Auto
Bool Property wind_first_run AutoFunction dz_state_lakeview(Bool cleanup)ObjectReference lake_xmarker = (Game.getForm(0x0300307b) as ObjectReference) ;vanilla game xmarker
If cleanup == True && lake_xmarker.IsDisabled()
  Return                ;since you can't clean up a non-existent table)
ElseIf cleanup == True && !lake_xmarker.IsDisabled()     ;we wish to clean up and the marker is enabled
  lake_xmarker.Disable()            ;disable the marker
  dz_new_lake_xmarker.Enable()          ;enable our marker to keep chopping block present and prevent disabled trees etc. from coming back
  lake_first_run = True
ElseIf cleanup == False && !lake_xmarker.IsDisabled()
  Return
ElseIf cleanup == False && lake_xmarker.IsDisabled() && lake_first_run == True
  lake_xmarker.Enable()
EndIf

EndFunctionFunction dz_state_heljarchen(Bool cleanup)ObjectReference helj_xmarker = (Game.getForm(0x0300C3C6) as ObjectReference) ;vanilla game xmarker
If cleanup == True && helj_xmarker.IsDisabled()
  Return                ;since you can't clean up a non-existent table)
ElseIf cleanup == True && !helj_xmarker.IsDisabled()     ;we wish to clean up and the marker is enabled
  helj_xmarker.Disable()            ;disable the marker
  dz_new_helj_xmarker.Enable()          ;enable our marker to keep chopping block present and prevent disabled trees etc. from coming back
  helj_first_run = True
ElseIf cleanup == False && !helj_xmarker.IsDisabled()
  Return
ElseIf cleanup == False && helj_xmarker.IsDisabled() && helj_first_run == True
  helj_xmarker.Enable()
EndIf

EndFunctionFunction dz_state_windstad(Bool cleanup)ObjectReference wind_xmarker = (Game.getForm(0x0300A50E) as ObjectReference) ;vanilla game xmarker
If cleanup == True && wind_xmarker.IsDisabled()
  Return                ;since you can't clean up a non-existent table)
ElseIf cleanup == True && !wind_xmarker.IsDisabled()     ;we wish to clean up and the marker is enabled
  wind_xmarker.Disable()            ;disable the marker
  dz_new_wind_xmarker.Enable()          ;enable our marker to keep chopping block present and prevent disabled trees etc. from coming back
  wind_first_run = True
ElseIf cleanup == False && !wind_xmarker.IsDisabled()
  Return
ElseIf cleanup == False && wind_xmarker.IsDisabled() && wind_first_run == True
  wind_xmarker.Enable()
EndIf

EndFunction

 

 

 

little_things_script

 

 

ScriptName dz_little_things_script Extends Actor
import Actor
;;;this mod will be controlled by my misc mcm menus mod;;;these GMST variables control daylight/night;;;
;fTimeSpanAfternoonEnd
;fTimeSpanAfternoonStart
;fTimeSpanEveningEnd
;fTimeSpanEveningStart
;fTimeSpanMidnightEnd
;fTimeSpanMidnightStart
;fTimeSpanMorningEnd
;fTimeSpanMorningStart
;fTimeSpanNightEnd
;fTimeSpanNightStart
;fTimeSpanSunriseEnd
;fTimeSpanSunriseStart
;fTimeSpanSunsetEnd
;fTimeSpanSunsetStart;Int Property ess_keycode = 24 Auto
Bool Property secondpress Auto              ;to keep track of messagebox open
Bool ess_bool;;;to toggle the NPC under the crosshair to essential/non-essential;;;
;;;press hotkey once for status, a second time to toggle while message still displays;;;
Function dz_essential_toggle()
;debug.notification("essential toggle pressed")Actor NPCRef = Game.GetCurrentCrosshairRef() as Actor        ;the actor under the crosshair
  If !NPCRef
   debug.messagebox("There is no NPC under the crosshair")
   Return
  EndIf
String actorname = NPCRef.GetBaseObject().Getname()         ;the actor's name
;debug.notification("NPC is "+actorname)
ess_bool = NPCRef.IsEssential()              ;is the actor essential?
Bool prot_bool = NPCRef.GetActorBase().IsProtected()        ;is the actor protected?
String ess_status                 ;message about essentual status
String prot_status                 ;message about protected status  If ess_bool == True
  ess_status = "essential"
  Else
  ess_status = "non-essential"
  EndIf  If prot_bool == True
  prot_status = "protected"
  Else
  prot_status = "not protected"
  EndIf
  ;String msg = "$status_msg"
  String msg = "press the key again within five seconds  to change the essential status."
  debug.messagebox(actorname+ " is "+ess_status+ "\n and "+prot_status+" \n"+msg)
  secondpress = True                ;while this is true a second press is diverted to dz_setessential() function
  ;debug.notification("secondpress is "+secondpress)
  Utility.WaitMenumode(5.0)
  secondpress = False
  ;debug.notification("secondpress is "+secondpress)
  Int ActKey = Input.GetMappedKey("Activate")
  Input.TapKey(ActKey)                ;Send 'Enter' to close messageboxEndFunctionFunction dz_setessential()
Int ActKey = Input.GetMappedKey("Activate")
Input.TapKey(ActKey)                  ;Send 'Enter' to close messagebox
secondpress = False
;debug.notification("secondpress is "+secondpress)
Actor NPCRef = Game.GetCurrentCrosshairRef() as Actor
String actorname = NPCRef.GetBaseObject().Getname()         ;the actor's name                ;is messagebox open?
ess_bool = !ess_bool                ;toggle essential status
debug.notification("setting essential status")
If ess_bool == True
  NPCRef.GetActorBase().SetEssential(True)          ;need to use GetActorBase here
  If NPCRef.IsEssential()
   debug.messagebox(actorname+" is now essential")
  EndIf
  Utility.WaitMenumode(1)
  Input.TapKey(Actkey)
Else
  NPCRef.GetActorBase().SetEssential(False)
  If !NPCRef.IsEssential()
   debug.messagebox(actorname+" is no longer essential")
  EndIf
  Utility.WaitMenumode(1)
  Input.TapKey(Actkey)
EndIf
;debug.notification("setting function")

EndFunction

 

 

 

perhaps I'm confusing myself but in both the lines:

scriptRef_things = (Game.GetFormFromFile(0x00000800, "dz_little_things.esp") as dz_little_things_script)

scriptRef_hfclean = (Game.GetFormFromFile(0x00000801, "dz_hearthfire_cleanup.esp") as dz_hearthfire_cleanup_script)

 

the form is an xmarker, both markers have the relevant script attached with a function I wish to run e.g scriptRef_x.the_function

 

hence my difficulty in seeing the functional difference. As I said I did rewrite the one script to compile and work, so this isn't currently a 'live' issue:)

 

diziet

Link to comment
Share on other sites

You may be confusing yourself. Just remember that if the target of GetFormFromFile is a pre-placed ObjectReference (i.e. has its own formID) and the attached script extends ObjectReference then you can cast to the script without casting to ObjectReference. But if the target script extends a child class such as Actor then you'll need to cast to Actor before trying to cast to the script.

 

Also, the screenshot shows a plugin local formID of 00001801 for the xmarker rather than 00000801. Is there a mistake somewhere?

Link to comment
Share on other sites

Also, the screenshot shows a plugin local formID of 00001801 for the xmarker rather than 00000801. Is there a mistake somewhere?

 

That's just xedit isn't it? the esp is the first esl flagged file loaded so xedit adds a 1 as in FE001 for the mod order loading. in the esp the low order form id is still 801, if loaded later the full id in xedit might be 00002801.

 

diziet

Link to comment
Share on other sites

If that is the case, I did not know. I haven't delved too much into light plugins. I certainly haven't converted any that were targets of GetFormFromFile.

 

Another approach to consider is SKSE mod events. I actually find them to be a little more useful. But if you don't have control over the other mod, then you cannot register for the event and run the code when your script sends the event. In that case, you're still stuck with using GetFormFromFile.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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