Jump to content

Help: How do I assign Script Properties to an object created by the "placeatme" function?


Recommended Posts

I am the creator of the Liminal Portals mod (https://www.nexusmods.com/skyrimspecialedition/mods/104212) and am trying rework the portal logic. Currently, there are 6 pairs of portals that are hardcoded to direct the users to the opposite portal. When they cast the spell to create the portal, it moves one of these portal objects to their location from a hidden cell. This limits the number of portals to the number that I have manually created in advance.

 

I am trying to update the mod so that an infinite number can be placed. The plan is this: Cast the spell to create a copy of the portal object at their current location, placing an item in the player's inventory. When they activate this item, it creates the second portal and links them together.

 

Unfortunately, I have no idea how to go about linking the portals when they are dynamically created. Currently they are linked through a script property that contains an ObjectReference of the destination portal. How can I use papyrus to update the script property on a portal after it has been created by the placeatme function? Also, how do I store the ObjectReference of the first portal inside an item that can be referenced when the second portal is placed?

 

I'm not expecting a walkthrough or anything, just some pointers on functions that I can do more research on, or just the name of a mod that does something similar that I can analyze to learn from. Any help is appreciated.

 

Thank you.

Link to comment
Share on other sites

Classic story. Search for hours, find nothing. Post for help, find the answer in 10 minutes.

I just discovered the SetPapyrusVariable function, which looks like exactly what I need. I'm hoping that I can use it for both parts of my question. So the new plan looks like this:

 

Cast spell to create portal at their current location. Save the ObjectReference of this portal when it's created, then create an item in the player inventory. Apply the portal ObjectReference to a script on the item with SetPapyrusVariable.

When the player activates the item, create another portal at their current location. Save this ObjectReference as well. Then, use SetPapyrusVariable on both ObjectReferences to set their destinations to each other, and destroy the item.

 

If anyone has any advice for me I'm happy to hear it, but I think I have a basic plan in place. I'll leave this thread up in case someone searches for a similar problem.

Link to comment
Share on other sites

The way to access a child script is to cast as. Let's say you have a script called PortalScript attached to your portal (the base object)

Scriptname PortalScript Extends ObjectReference
ObjectReference Property LinkedPortal Auto

in another script you can do this: 

ObjectReference PortalRef = Game.GetPlayer().PlaceAtMe(portal, 1, true) ;portal base object has the PortalScript attached
PortalScript ScriptRef = portalRef as PortalScript 
if scriptRef 
    scriptRef.LinkedPortal = SomeObjectReference
Endif

 

Link to comment
Share on other sites

Thank you for the example, dylbill. That looks very straightforward. Unfortunately, I seem to have run into a problem with the inventory item.

 

When creating the first portal, I want to also create a copy of a "portal stone" item that will be used to create the second portal. Once the portal stone is created, I want to edit the script property on that instance of the item to store the object reference of the first portal. However, the "additem" function does not return the object reference of the created item, so I'm not sure how to actually target the item to edit it's script properties. Is there a way to add a copy of a base item to the player inventory in a way that returns the object reference of the new copy?

Link to comment
Share on other sites

No problem. For the AddItem, what I would do is use placeAtMe first, that way you have an object reference to work with. Make sure the Persistent parameter in the PlaceAtMe function is true so it keeps the reference while in inventory. You can then set the property on the object reference and do Game.GetPlayer().AddItem(PortalStoneReference). 

Link to comment
Share on other sites

That worked perfectly, thank you so much. I would have never figured this out without your help, the "SetPapyrusVariable" did not work at all for me, but your scriptref example was perfect. The basic proof-of-concept is now functional.

Is there a way to keep the portal stones from stacking in the inventory if the player has more than one? And maybe a way to add a unique text (like an enchantment) to tell them apart? Not strictly necessary but makes it easier for the player to use.

Link to comment
Share on other sites

No problem. To keep them from stacking you can use skse and the SetDisplayName function. If they have different names, they won't stack in the inventory. 

Note that that function isn't save game persistent, so you have to store the name and use the OnPlayerLoadGame event to reset the names on game load. 

Another work around if you don't want to use skse is to duplicate the base object of  the stone a bunch of times in the creation kit, then cycle through them so each stone has a different base object when using placeAtMe. 

I also had another thought, instead of using stones you could make your spell a 2 step process. 

The first time you cast the spell, it places a portal and stores the objectReference in another script. 

The second time you cast the spell, it places another portal and links them, then clear the ObjectReference stored in the other script. 

In your spell script you can check if the property is filled to see which step it's on.

 

Link to comment
Share on other sites

I might have to mess around a bit and try some of those. The idea behind using a stone is so that the player can start a second pair without needing to complete the first pair, so they have several "in progress" portals at once, each one linked to a specific item to tell them apart. Also thematically, the portal stones are supposed to be similar to the sigil stones that made the oblivion gates.

 

I think I will try out duplicating the stone a few times. If I have 5 versions of the stone and just limit the player to 5 incomplete portal pairs at a time, then that should be sufficient.

 

Thanks again for all your help. I'm sure I'll run into many more issues as I turn it from a proof-of-concept into a fully reworked mod, but that's enough work for today.

Link to comment
Share on other sites

It is sometimes useful to place a static marker object in some out of sight storage cell, to use with placeAtMe, so that the objects you create don't appear near the player. Otherwise, as dylbill said: out_of_sight_marker.placeAtMe( baseItem, 1, True), set your properties, then player.addItem(...)
Link to comment
Share on other sites

  • Recently Browsing   0 members

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