eberkain Posted May 17, 2021 Share Posted May 17, 2021 I am using two mods in my game. Alchemy Requires Bottles - pretty self explanatoryChasing the Dragon - adds an toxicity/addiction mechanic to using potions I would like a way to dispose of unwanted potions and get back empty bottles without consuming them. The best way I could think about doing this is using a container. place potions inside, when its closed run a script that removes all the potions and puts in empty bottles. So I know what I want to do, but no clue how to make it. I do have the CK installed from doing my mod setup, but I have used it before. Can you direct me to some tutorials or guides that are up to date for SSE that will cover the things I need to learn? Link to comment Share on other sites More sharing options...
xkkmEl Posted May 23, 2021 Share Posted May 23, 2021 The Creation Kit wiki is a good place to start. You'll want a papyrus script on your recycling container that triggers when potions are added. So attach an ObjectReference script, either to a new Container object you can instantiate wherever you like, or on a standard container object placed in the world grid if you want just a few pre-placed recycling containers. See https://www.creationkit.com/index.php?title=OnItemAdded_-_ObjectReference Link to comment Share on other sites More sharing options...
eberkain Posted May 23, 2021 Author Share Posted May 23, 2021 The Creation Kit wiki is a good place to start. You'll want a papyrus script on your recycling container that triggers when potions are added. So attach an ObjectReference script, either to a new Container object you can instantiate wherever you like, or on a standard container object placed in the world grid if you want just a few pre-placed recycling containers. See https://www.creationkit.com/index.php?title=OnItemAdded_-_ObjectReference Ive been playing around with the creation kit. I have a quest that gives the player a power that activates an effect that calls a script. I used the power to allow the player to activate a persistent chest from anywhere, to open it. I attached a script to the chest. Scriptname DumpOutPotionReplaceScript extends ObjectReference Keyword Property VendorItemPoison Auto Keyword Property VendorItemPotion Auto ObjectReference Property akBaseItem Auto MiscObject Property emptyBottle Auto Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) Debug.Trace("added " + aiItemCount + "x " + akBaseItem) if (akBaseItem.HasKeyword(VendorItemPotion) || akBaseItem.HasKeyword(VendorItemPoison) ) RemoveItem(akBaseItem,aiItemCount,True) akSourceContainer.AddItem(emptyBottle,aiItemCount,True) Debug.Trace("exchanging " + aiItemCount + "x " + akBaseItem) else RemoveItem(akBaseItem,aiItemCount,True,akSourceContainer) Debug.Trace("returning " + aiItemCount + "x " + akBaseItem) endif endEvent The emptyBottle property points to the proper reference as defined in the scripts properties window. I had it work sorta once, it would change out potions, but one 1 at a time, and not poisons, didnt work for stacks and would delete some food items, and completely ignore other items like clothing. Ive been tinkering and now I cant get it to do anything at all anymore. I tried changing the spell to just summon a new chest, which works, and the script is attached the the container base object, but it does nothing, no debug output. I don't understand what I am doing wrong. Link to comment Share on other sites More sharing options...
xkkmEl Posted May 23, 2021 Share Posted May 23, 2021 Indeed. Very well done. The trouble is that you won't get repeated OnItemAdded events to update counts. It only triggers when the base object first appears in the inventory. Use an array, StorageUtil or JContainers to accumulate the base objects as the events fire, and use RegisterForSingleUpdate( 0.1) to wait for the events to quiet down. When the update fires, work through your list to perform the recycling. For each base object, you may have more than one inventory entry, so be sure to loop on that base object until the container's GetItemCount( baseObject) returns 0. Link to comment Share on other sites More sharing options...
xkkmEl Posted May 23, 2021 Share Posted May 23, 2021 You probably want to also use a check for baseObject.GetType()==46 instead of the keyword check. Link to comment Share on other sites More sharing options...
xkkmEl Posted May 23, 2021 Share Posted May 23, 2021 Another problem you may be facing. Script properties don't update mid-game. Many things don't. When hashing things out, always have a save game available that has never seen your esp, to test things out. Link to comment Share on other sites More sharing options...
eberkain Posted May 24, 2021 Author Share Posted May 24, 2021 You probably want to also use a check for baseObject.GetType()==46 instead of the keyword check. easy Indeed. Very well done. The trouble is that you won't get repeated OnItemAdded events to update counts. It only triggers when the base object first appears in the inventory. Use an array, StorageUtil or JContainers to accumulate the base objects as the events fire, and use RegisterForSingleUpdate( 0.1) to wait for the events to quiet down. When the update fires, work through your list to perform the recycling. For each base object, you may have more than one inventory entry, so be sure to loop on that base object until the container's GetItemCount( baseObject) returns 0. yeah i dont follow. I looked through everything on the objectreference page to try and figure out what event to use to trigger the script, and I dont understand why onitemadded isn't the right choice. I tried to switch my power back to opening the persistant container, and now I cant get that to work either... /sigh I can figure out how to do an array and loop through it easy enough in this language, but i dont follow the program flow and how the events fire. Can I ignore the containers and power and all. What other methods can be used to give the player an action that would allow them to pick an item and have it turned into a different item? I thought about making a merchant that completely ignored gold values, and whenever you sold him a potion he would delete it and add an empty bottle to his stock. but that seems just as clumsy as a container. I thought about just having it when you drop a potion auto remove it and add an empty bottle back to the player. I thought about maybe having a hotkey or a power, look at a potion in the world and hit the action, instead of picking it up you just get an empty bottle. maybe i should just have it be a container, open the box, put in stuff, when you close it everything is given back to the player and if it was a potion or a poison, instead give an empty bottle. Is there a more elegant solution? I wish there was a way to just add a button to the inventory menu, select the potion, hit the button, dump the potion and get a bottle. I feel like this should not be a complicated mod. Link to comment Share on other sites More sharing options...
xkkmEl Posted May 24, 2021 Share Posted May 24, 2021 Rethinking... you don't need the array. Container's ObjectReference script would need to catch 2 events: OnItemAdded, OnUpdate event OnItemAdded( whocares...) RegisterForSingleUpdate( 0.1) endevent event OnUpdate() foreach item in container int count = container.GetCount( item) container.RemoveItem( item, count) container.AddItem( EmptyBottle, count) endforeach endevent OnItemAdded just calls RegisterForSingleUpdate( 0.1). When it first fires, it schedules OnUpdate to be called in 0.1 seconds. If OnItemAdded fires again before that, the OnUpdate gets pushed back 0.1 seconds (it overrides the previously scheduled update event). Once the OnItemAdded events stop firing for 0.1 seconds, OnUpdate gets called. At that point, you can loop through the inventory looking for potions and recycle them. OnItemAdded is the right event to trigger on, but its tricky because if you add more of an item you already have, it does not fire. In practice, its count and objectref parameters are unusable. You could try to process everything inside the OnItemAdded event, but you'd be more likely to miss some potions as events get crossed. It's also best to limit how much work you do in these events as its easy to overload the script engine with too many threads. Link to comment Share on other sites More sharing options...
eberkain Posted May 24, 2021 Author Share Posted May 24, 2021 I can not for the life of me get the power to open the container anymore. I don't know how I had it working before.... Scriptname DumpOutPotionOpenContainer extends ActiveMagicEffect ObjectReference Property DumpOutPotionContainer Auto Actor Property PlayerRef Auto Event OnEffectStart(Actor akTarget, Actor akCaster) Debug.Notification("opening container!") DumpOutPotionContainer.Activate(PlayerRef) endEvent the event triggers, but for some reason the activate command doens't work. I must be missing something here. Link to comment Share on other sites More sharing options...
xkkmEl Posted May 24, 2021 Share Posted May 24, 2021 Add some debugging trace to dump out the content of your two properties, and run it on a new game. On my end, I've never seen that "<<Default>>" setting resulting in anything but None, and headaches, but I rarely use the actual default property names. Link to comment Share on other sites More sharing options...
Recommended Posts