Jump to content

Cell as script property


SKKmods

Recommended Posts

Have an odd one where trying to define script properties for exterior cells fails, interior cells work fine.

 

The script which compiles fine and the properties all autofill:

 

Cell Property pDiamondCityExt Auto Const Mandatory ;0000e50c
Cell Property pDiamondCityExt01 Auto Const Mandatory ;0000e50b
Cell Property pDiamondCityExt03 Auto Const Mandatory ;0000e097
Cell Property pGoodneighborExt Auto Const Mandatory ;0000e50d
Cell Property pGoodneighborExt02 Auto Const Mandatory ;0000e078
Cell Property pGoodneighborExt03 Auto Const Mandatory ;0000e079

The runtime papyrus error log:

 

error: Property pDiamondCityExt on script SKK_TarkovQuestScript attached to SKK_TarkovQuest (19000F99) cannot be bound because <nullptr form> (0000E50C) is not the right type
error: Property pDiamondCityExt03 on script SKK_TarkovQuestScript attached to SKK_TarkovQuest (19000F99) cannot be bound because <nullptr form> (0000E50B) is not the right type
error: Property pGoodneighborExt02 on script SKK_TarkovQuestScript attached to SKK_TarkovQuest (19000F99) cannot be bound because <nullptr form> (0000E097) is not the right type
error: Property pDiamondCityExt01 on script SKK_TarkovQuestScript attached to SKK_TarkovQuest (19000F99) cannot be bound because <nullptr form> (0000E50D) is not the right type
error: Property pGoodneighborExt03 on script SKK_TarkovQuestScript attached to SKK_TarkovQuest (19000F99) cannot be bound because <nullptr form> (0000E078) is not the right type
error: Property pGoodneighborExt on script SKK_TarkovQuestScript attached to SKK_TarkovQuest (19000F99) cannot be bound because <nullptr form> (0000E079) is not the right type
Eh ?
Link to comment
Share on other sites

I think it's because the game can't see unloaded exterior cells, only the interior ones. (Not sure about this as I mostly use script functions on interior cells).

 

I guess Diamond City and Goodneighbor are not loaded by the time the script initializes so the virtual machine fails to initialize their cell properties.

 

CGF "MyScript.IsPlayerInCell" DD60 only works if SanctuaryExt is loaded.

 

CGF "MyScript.IsPlayerInCell" 1E58 works always.

Scriptname MyScript

; CGF "MyScript.IsPlayerInCell" TheCell
; DD60 = SanctuaryExt
; 1E58 = DmndPlayerHome01
Function IsPlayerInCell(Cell TheCell) Global
     If Game.GetPlayer().GetParentCell() == TheCell
          Debug.MessageBox("True")
     Else
          Debug.MessageBox("False")
     EndIf
EndFunction

GetInCell (the Console/Condition equivalent) should give the same result.

Edited by LarannKiar
Link to comment
Share on other sites

It looks very much like external cells can not be referenced in script unless they are loaded or preloaded.

 

To preload a cell one has to find (or make) an object in it persistent though :sad:

 

Step though this test script with debug log results inserted to learn more:


ObjectReference Property pDmndGateRef Auto Const Mandatory ; property makes it persistent 
Cell            Property pDiamondCityExt Auto Const Mandatory ;Error: ... cannot be bound because <nullptr form> (0000E50C) is not the right type]

Function CellTest() DebugOnly ; cqf SKK_testCellQuest "SKK_testCellQuestScript.Celltest"

Debug.Trace("SKK_testCellScript.pDmndGateRefPROPERTY " + pDmndGateRef)
;RESULT SKK_testCellScript.pDmndGateRefPROPERTY [ObjectReference < (00077A87)>]

Debug.Trace("SKK_testCellScript.pDiamondCityExtPROPERTY " + pDiamondCityExt)
;RESULT SKK_testCellScript.pDiamondCityExtPROPERTY None

Cell DiamondCityExtSTATIC = Game.GetFormFromFile(0x0000e50c, "Fallout4.esm") as Cell
Debug.Trace("SKK_testCellScript.DiamondCityExtSTATIC " + DiamondCityExtSTATIC)
;RESULT SKK_testCellScript.DiamondCityExtSTATIC None

Cell DiamondCityExtDYNAMICnoPreload = pDmndGateRef.GetParentCell()
Debug.Trace("SKK_testCellScript.DiamondCityExtDYNAMICnoPreload " + DiamondCityExtDYNAMICnoPreload)
;RESULT SKK_testCellScript.DiamondCityExtDYNAMICnoPreload None

pDmndGateRef.PreloadExteriorCell()
Cell DiamondCityExtDYNAMICyesPreload = pDmndGateRef.GetParentCell()
Debug.Trace("SKK_testCellScript.DiamondCityExtDYNAMICyesPreload " + DiamondCityExtDYNAMICyesPreload)
;RESULT SKK_testCellScript.DiamondCityExtDYNAMICyesPreload [Cell <DiamondCityExt (0000E50C)>]

EndFunction
Link to comment
Share on other sites

That is a very interesting observation, particularly reguarding an obscure effect being discussed on Discord concerning Cell records and Partial Forms
(That just adding the presistent cell override to a mod, no refs even required, seems to cause any other cell overrides in that mod to act differently).

- this 'could' be related somehow to your assertion -

 

"To preload a cell one has to find (or make) an object in it persistent".

 

What have you seen that suggests this? pDmndGateRef is already defined as persistent, yet the cell is not preloaded until you manually do it via PreloadExteriorCell().

 

I am also struggling with the difference between "Loaded" and "Attached" (for cells), and what it actually means in-game.

Link to comment
Share on other sites

It is not the persistence of the object in the cell that does anything to the cell, rather:

 

To BE ABLE to preload an external cell one needs to be able to REFER TO IT in script.

 

BUT, if the external cell is not loaded then it can not be REFERED TO in script.

 

The only time an unloaded external cell can be referred to is if it is loaded. Amusingly a script property cant be used to test if it is loaded as the script is unlikly to initalize just when the player happens to be in that specific cell. So GetFormFromFile has to be used, but to work that EXPENSIVE function has to be run as every cell loads to then test if it fills and if it is that cell. So *technically* possible, but totally insane.

 

So the only way to REFER TO an external cell in script is to get a handle to an object that is in the cell and use that as the proxy:

 

pDmndGateRef < --- The object I have a direct script handle on to be persistent

.GetParentCell() <----- The probably unloaded cell I can not get a direct handle to

 

If the object is already persistent GetFormFromFile can be used for a dynamic fill. If not, it needs to be made a Script.Property, Quest.ReferenceAlias or put in a FromList to make it statically persistent.

 

I ignore the attached state as it is not well defined. Down the pub I would suggest it may be in the cell buffer to load or unload, but what that means to the objects in it is unqualified and I have not tested.
ps handle == pointer
Link to comment
Share on other sites

Thanks SKK. I understood your code, but took your sentence as implying more than it did.

Just grasping at straws trying to work out this weird partial Cell behavior. Would prefer to be down the Pub.

 

Anyway, your code has given me an avenue for further tests - even though I still don't know what "Attached" really signifies - though the creationkit docs say "Loaded and !attached" = "preloaded" (another undefined state).

Link to comment
Share on other sites

There is this script that is supposed to be more reliable than using "OnCellLoad()" on the player alias and also resource friendly but the question is, how to check if the current cell is the one that you are looking for if you can't use a property or getform every time ? is it possible to manually store the cell ID as "Int" and use GetParentCell().GetFormID ==.

Edited by lee3310
Link to comment
Share on other sites

Thanks SKK. I understood your code, but took your sentence as implying more than it did.

Just grasping at straws trying to work out this weird partial Cell behavior. Would prefer to be down the Pub.

 

Anyway, your code has given me an avenue for further tests - even though I still don't know what "Attached" really signifies - though the creationkit docs say "Loaded and !attached" = "preloaded" (another undefined state).

People seem to use isAttached() as an alternative to isLoaded() in their scripts but i can't tell which fires first ? OnCellLoad() or OnCellAttach() (it can be verified with a little test.)

Link to comment
Share on other sites

A trace of all object and cell script events attached to persistent WorkshopRefs.
Running at 300 units/sec (not sprinting) from NW map corner past Sanctuary past RR to Carla.
Totally vanilla base game.
uGridsToLoad = 5 ;default 10240 radius
uExterior Cell Buffer=36 ;default 24576 radius
Linear sequence split into Sanctuary and RedRocket, Abernathy removed.
Last value is distance from player.
OnLoad[workshopscript < (000250FE)>] [Cell <SanctuaryExt (0000DD60)>] 3d True 11314
OnCellAttach [workshopscript < (000250FE)>] [Cell <SanctuaryExt (0000DD60)>] 3d True 11302
OnCellLoad [workshopscript < (000250FE)>] [Cell <SanctuaryExt (0000DD60)>] 3d True 11288
OnCellDetach[workshopscript < (000250FE)>] 17796
OnUnload[workshopscript < (000250FE)>] 17810 ;cell buffer not full yet ?


OnLoad[workshopscript < (00054BAE)>] [Cell <RedRocketExt02 (0000DDA0)>] 3d True 11322
OnCellAttach [workshopscript < (00054BAE)>] [Cell <RedRocketExt02 (0000DDA0)>] 3d True 11302
OnCellLoad [workshopscript < (00054BAE)>] [Cell <RedRocketExt02 (0000DDA0)>] 3d True 11291
OnCellDetach[workshopscript < (00054BAE)>] 13940
OnUnload[workshopscript < (00054BAE)>] 13954 ;cell buffer full ?

 

Which is why I have always used OnLoad/OnUnload events on my object scripts (yes it still fires when object is disabled).

Link to comment
Share on other sites

 

A trace of all object and cell script events attached to persistent WorkshopRefs.
Running at 300 units/sec (not sprinting) from NW map corner past Sanctuary past RR to Carla.
Totally vanilla base game.
uGridsToLoad = 5 ;default 10240 radius
uExterior Cell Buffer=36 ;default 24576 radius
Linear sequence split into Sanctuary and RedRocket, Abernathy removed.
Last value is distance from player.
OnLoad[workshopscript < (000250FE)>] [Cell <SanctuaryExt (0000DD60)>] 3d True 11314
OnCellAttach [workshopscript < (000250FE)>] [Cell <SanctuaryExt (0000DD60)>] 3d True 11302
OnCellLoad [workshopscript < (000250FE)>] [Cell <SanctuaryExt (0000DD60)>] 3d True 11288
OnCellDetach[workshopscript < (000250FE)>] 17796
OnUnload[workshopscript < (000250FE)>] 17810 ;cell buffer not full yet ?


OnLoad[workshopscript < (00054BAE)>] [Cell <RedRocketExt02 (0000DDA0)>] 3d True 11322
OnCellAttach [workshopscript < (00054BAE)>] [Cell <RedRocketExt02 (0000DDA0)>] 3d True 11302
OnCellLoad [workshopscript < (00054BAE)>] [Cell <RedRocketExt02 (0000DDA0)>] 3d True 11291
OnCellDetach[workshopscript < (00054BAE)>] 13940
OnUnload[workshopscript < (00054BAE)>] 13954 ;cell buffer full ?

 

Which is why I have always used OnLoad/OnUnload events on my object scripts (yes it still fires when object is disabled).

 

So the order is OnLoad -> OnCellAttach -> OnCellLoad. Cell attaches before Cell loads :thumbsup:

Link to comment
Share on other sites

  • Recently Browsing   0 members

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