Jump to content

Turn a Container into an Activator


Recommended Posts

Hi people. I'm pretty new at modding. I'm trying to make a mod that adds a spell, and when you cast it on any container, it should be marked so the next time I try to open that container, it will activate something else instead.

The first thing I thought was to disable the original container, and place a custom activator there. However, I couldn't find a function to change an activator mesh (so it looks like the original container). There's this SKSE function: SetWorldModelPath, but it affects all instances of a form, so I can't use it. Without a function, I would need to create an activator for every container mesh...

 

The next thing I thought is marking the container (storing it in a list), so when the player tries to open it, it activates something else. The thing is, I don't know how to get the reference of the container the player is currently opening. Is it possible to attach a script to an object through another script? if not, is there an event that triggers every time a player opens a container, so I can check if that container is marked or not? (I could use OnMenuOpen, but then I wouldn't have the reference of the container).

 

Any help would be appreciated.

Link to comment
Share on other sites

You can change anything to look like whatever mesh you wish. Just go to the object you wish to copy, such as a chest, open up the object then copy the model. Then create a new activator. When you've done that, open the activator. Go to Model/Edit within the activator, that will open up a Model Data popup which will be blank. Click edit again and then Select File will pop up. Navigate to the Skyrim Directory and the Meshes subfolder then in the File Name area paste your model that you copied and click Open and you should be back to the previous Model Data popup and you should now see a picture of your chest in the window. Click ok, then ok, save.

Link to comment
Share on other sites

Amm yes, I know, but I need to change the model through a script, because I want to spawn a (generic) activator in place of the container. I need to assign the container mesh to the new activator, so It looks like they are the same object. I don't know if that's possible. I would need to create a different activator for every container mesh.

Link to comment
Share on other sites

There are two problems with what you propose although there are easy workarounds for both problems.

  1. You can't dynamically attach scripts to a container other than by using a quest reference alias and adding the chest to the alias.
  2. Containers can't be the target of spells.

The solution to the first problem is very easy. You can use a perk on the player with an OnActivate entry point and appropriate conditions to effectively override the normal container activation for any container the player ties to activate. You just need to decide what conditions to use and then have the perk fragment script activate the appropriate remote container. My recently released Enchantment Swapper mod has a perk that overrides activation of enchanting tables in certain situations if you want to see an example.

 

Problem two is slightly harder but there are multiple options.

  • You could give up the idea of a spell and instead have a special token object that you place in the container to mark it. A script on some misc. item will trigger an event when it's added to a container and that event includes the container id. More importantly just the fact that the token is in the container could be one of the key conditions used on the perk to handle container activation. You could generate the token item in any way you like from having a set of them in some special container (maybe the original), letting the player craft them, or even adding one to the player inventory as the result of casting a spell.
  • You can use a scripted spell effect that calls SKSE's GetCurrentCrossHairRef() function that checks to see if the player was targeting a container as the spell was cast then use that reference to mark the container. You could then add the container to some formlist, but frankly I would just put some special token object into the container to mark it as special since that's a really easy thing to check with the perk conditions.
  • If you didn't want to use SKSE you can attempt to locate the container by using a spell with a projectile that then tries to detect the nearest container when it strikes something. But frankly that's the least reliable and most complicated to get working.

If you really just want all marked containers to link to a single remote container I would certainly use the Perk, a token object, and the spell with GetCurrentCrosshairRef to get the token into it. And for a robust implementation casting the spell again could remove the token so the container could be used normally again.

 

If you wanted to allow different marked containers to link to one of a small set of remote containers I would still approach it the same way and mark which of the different containers should be accessed by how many of the token object are placed inside. Place one token and you access the first. Place two and you access the second, etc. If you're adding tokens by casting the spell on the container then when there are more tokens than remote containers you just remove all of the tokens.

Link to comment
Share on other sites

That's a really good idea! I'll replace the spell with the token. I just needed a way to mark a container, and a spell was the first thing that came to my mind, but it will probably make things more complicated. Also, I need each container to activate a different reference, and counting the amount of tokens inside makes it really simple. I don't know much about how perks and quests work, so I'll take a look at your mod source if you don't mind, but for now I think I have enough to continue with my mod. Thanks for the help, cdcooley!

Link to comment
Share on other sites

I just remembered that the source scripts are packed in a way that makes them a little hard to find. You don't really need them for what you're doing, especially the actual enchantment swapper. But you might be curious about the perk fragment so here's its source.

 

 

 

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment
;NEXT FRAGMENT INDEX 1
Scriptname CDC_EnchantmentSwapperPerkScript Extends Perk Hidden

;BEGIN FRAGMENT Fragment_0
Function Fragment_0(ObjectReference akTargetRef, Actor akActor)
;BEGIN CODE
	if akActor.GetItemCount(CDC_EnchantmentSwapGuide) < 1
		akActor.AddItem(CDC_EnchantmentSwapGuide)
	else
		CDC_ESItemPicker.Activate(akActor)
	endif
;END CODE
EndFunction
;END FRAGMENT

ObjectReference Property CDC_ESItemPicker Auto
Book Property CDC_EnchantmentSwapGuide Auto

 

 

That fragment gets triggered if you are holding Wabbajack or the special book. (If you have Wabbajack equipped but don't have a copy of the book this script gives the book. Otherwise it does the remote container activation.)

 

 

In your case I would probably do something like this for your perk fragment if using the token count method.

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment
;NEXT FRAGMENT INDEX 1
Scriptname LinkedContainerAccessPerkFragmentScript Extends Perk Hidden

;BEGIN FRAGMENT Fragment_0
Function Fragment_0(ObjectReference akTargetRef, Actor akActor)
;BEGIN CODE
	int tokenCount = akTargetRef.GetItemCount(LinkedContainerAccessSpecialToken)
	if tokenCount >= 0 && tokenCount < LinkedContainerAccessContainerList.length
	ObjectReference remoteContainer = LinkedContainerAccessContainerList[tokenCount-1]
	if remoteContainer
		remoteContainer.Activate(akActor)
	endif
;END CODE
EndFunction
;END FRAGMENT

MiscObject Property LinkedContainerAccessSpecialToken Auto
{fill with special token object}

ObjectReference[] Property LinkedContainerAccessContainerList Auto
{fill with all of the remote containers the player should be able to access}

Or if you want to use different tokens to represent the different remote containers (which is probably a good idea) you can simply use two form lists to do the matching of special token to remote container like this:

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment
;NEXT FRAGMENT INDEX 1
Scriptname LCA_PerkFragmentScript Extends Perk Hidden

;BEGIN FRAGMENT Fragment_0
Function Fragment_0(ObjectReference akTargetRef, Actor akActor)
;BEGIN CODE
	int i = LCA_SpecialTokenList.GetSize()
	while i > 0
		i -= 1
		if akTargetRef.GetItemCount(LCA_SpecialTokenList.GetAt(i)) > 0
			LCA_RemoteContainerList.GetAt(i).Activate(akActor)
			return
		endif
	endif
;END CODE
EndFunction
;END FRAGMENT

FormList Property LCA_SpecialTokenList Auto
{fill with a list that the MiscObject special token forms}

FormList Property LCA_RemoteContainerList Auto
{fill with a matching list of the remote container ObjectReference forms}
Link to comment
Share on other sites

Oh ok. I see you add the perk to the player in the init() function of your hidden container. In my case, there isn't any container (the entity I need to activate remotely is a General Stores activator, it comes from another mod), so I guess I should create a dummy quest to add the perk when the mod loads. I have a question: if I make the marked container activate something else, will it show its contents anyway? When I activate the marked container, a menu should appear to select the real cloud container (all that is done by General Stores), but the menu also allows me to cancel and do nothing. I must make sure that the original container screen is not shown. I guess I should add "Game.DisablePlayerControls" to force close he container screen, right?

Link to comment
Share on other sites

  • Recently Browsing   0 members

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