jp2x Posted July 7, 2016 Share Posted July 7, 2016 I am working on a big radio mod. To alleviate lag, I need to move a random holotape from one box to another. I am tired and would really appreciate some assistance. Please? I started by trying to generate an OnItemAdded event. The code for that is at the bottom of the spoiler. I know this should be easy but I am just worn out. Scriptname MusiciansModRadio002a extends Quest ConditionalFormList Property akTapeList auto ;an empty formlistObjectReference Property MusiciansModHolotapeBay AutoObjectReference Property MusiciansModHolotapeAutoloader AutoInt Property aiItemCount Auto ConditionalInt Property iMusTapeTotal Auto ConditionalInt Property aiCounter Auto Conditional;Int Function GetItemCount(Form akAllHolotapeList);Int Function GetItemCount(Form akItem)FormList Property akAllHolotapeList auto;Int Property index Auto Conditional;FormList Property akChosenTapeList auto;ObjectReference Property MusiciansModHolotapeAutoloader AutoFunction ChangeTapes() ;Create formlist akTapeList from container:MusiciansModHolotapeAutoloaderiMusTapeTotal = akTapeList.GetSize()aiCounter= akTapeList.GetSize()Debug.Trace(aiCounter)MusiciansModHolotapeBay.Reset(); While aiCounter> 0; akTapeList.AddForm(akBaseItem) ; adding list of items in container; aiCounter-= 1; Debug.Trace("Item, Added!"); EndWhileMusiciansModHolotapeBay.AddItem(akTapeList.GetAt(Utility.RandomInt(0, (iMusTapeTotal))), aiItemCount); MusiciansModHolotapeBay.AddItem(akTapeList.GetAt(Utility.RandomInt(0, (iMusTapeTotal - 1))), aiItemCount)akTapeList.Revert()EndFunction;Int Property aiItemCount Auto Conditional;FormList Property akTapeList auto ;an empty formlist;Function AddInventoryEventFilter(Form akAllHolotapeList) native;Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer); While aiItemCount > 0; akTapeList.AddForm(akBaseItem) ; tracking list of items in container; aiItemCount -= 1 ; Debug.Trace("Item, Added!"); EndWhile;EndEvent;Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer); While aiItemCount > 0; akTapeList.RemoveAddedForm(akBaseItem) ; tracking list of items in container; aiItemCount -= 1; Debug.Trace("Item, Removed!"); EndWhile;EndEvent Link to comment Share on other sites More sharing options...
Reneer Posted July 7, 2016 Share Posted July 7, 2016 Your immediate problem is that you need to use RegisterForRemoteEvent in order for your Quest to receive events from your container. Link to comment Share on other sites More sharing options...
jp2x Posted July 8, 2016 Author Share Posted July 8, 2016 Thank you! I can get back to this tomorrow morning. :laugh: Link to comment Share on other sites More sharing options...
jp2x Posted July 8, 2016 Author Share Posted July 8, 2016 I've been at this for another 2 hours. I'm sorry to keep asking but this is my first Fallout 4 script. Can I have another hint to getting this to work? My container's script: ScriptName MusiciansModHoloLoaderScript01 extends ObjectReferenceInt Property aiItemCount Auto ConditionalFormList Property akTapeList auto ;an empty formlistFunction AddInventoryEventFilter(Form akAllHolotapeList) nativeEvent OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) While aiItemCount > 0 akTapeList.AddForm(akBaseItem) ; tracking list of items in container aiItemCount -= 1 Debug.Trace("Item, Added!") EndWhileEndEventEvent OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) While aiItemCount > 0 akTapeList.RemoveAddedForm(akBaseItem) ; tracking list of items in container aiItemCount -= 1 Debug.Trace("Item, Removed!") EndWhileEndEvent My radio quest script: Scriptname MusiciansModRadio002a extends Quest ConditionalFormList Property akTapeList auto ;an empty formlistObjectReference Property MusiciansModHolotapeBayAlias AutoObjectReference Property MusiciansModHolotapeAutoloaderAlias AutoInt Property aiItemCount Auto ConditionalInt Property iMusTapeTotal Auto ConditionalInt Property aiCounter Auto ConditionalFormList Property akAllHolotapeList auto;Int Function GetItemCount(Form akAllHolotapeList);Int Function GetItemCount(Form akItem);FormList Property akChosenTapeList autoEvent OnInit() ; Special event to receive when the door is activated; Register for Activate event from the secret door RegisterForRemoteEvent(MusiciansModHolotapeAutoloaderAlias, "OnItemAdded") RegisterForRemoteEvent(MusiciansModHolotapeAutoloaderAlias, "OnItemRemoved")EndEvent; Note the type in the event name matches the type of the first parameter, and is also the script where the; event is originally defined.Function ChangeTapes() ;Create formlist akTapeList from container:MusiciansModHolotapeAutoloaderiMusTapeTotal = akTapeList.GetSize()aiCounter= akTapeList.GetSize()Debug.Trace(aiCounter)MusiciansModHolotapeBayAlias.Reset()MusiciansModHolotapeBayAlias.AddItem(akTapeList.GetAt(Utility.RandomInt(0, (iMusTapeTotal))), aiItemCount); MusiciansModHolotapeBay.AddItem(akTapeList.GetAt(Utility.RandomInt(0, (iMusTapeTotal - 1))), aiItemCount)akTapeList.Revert() ;Chosen tape has been moved so we empty the list for next timeEndFunctionEvent ObjectReference.OnActivate(ObjectReference akSender, ObjectReference akActionRef) Debug.Trace(akSender + " was activated by " + akActionRef)EndEvent Link to comment Share on other sites More sharing options...
Reneer Posted July 8, 2016 Share Posted July 8, 2016 (edited) Ok, so there are a few things you're missing here. You've got RegisterForRemoteEvent(MusiciansModHolotapeAutoloaderAlias, "OnItemAdded") RegisterForRemoteEvent(MusiciansModHolotapeAutoloaderAlias, "OnItemRemoved")but you aren't doing anything with it in your quest script, so even if those events fire on your container, the quest can't handle them. I'd write you an example script, but I honestly don't know why you are doing what you are doing (mitigating lag somehow?) or what your ultimate goal is (a radio mod that plays from holotapes?). If you gave me a bit more information I could help more. Edited July 8, 2016 by Reneer Link to comment Share on other sites More sharing options...
jp2x Posted July 8, 2016 Author Share Posted July 8, 2016 (edited) Sorry. My script isn't doing anything with it because I got stuck. Here is some more detail. The radio: I have a radio station that will play a song if the corresponding holotape is placed in a container. That part works fine. The problem is that using quest conditions to manage the playlist doesn't work well. The radio playlist is customizable by placing holotapes in the loader container. So, each time the conditions randomly select a song that isn't in the loader, no song plays and the playlist loop starts over. This creates dead air on the radio; sometimes over a minute. The goal: I would like to place holotapes in a container (holotapeloader) and select one at random to copy to a second container (holotapebay). I've already started changing the radio quest so it will play based on the second container. I was trying to empty and rebuild a formlist from the first container, select from the list at random, then empty the second container and copy the selection to the second container. Your help is much appreciated. Edited July 8, 2016 by jp2x Link to comment Share on other sites More sharing options...
Reneer Posted July 8, 2016 Share Posted July 8, 2016 (edited) You seem to be making this overly complicated. Having a second container is simply making things more complex than they need to be, since everything can be done from your 1st container. Unless you have that 2nd container for a reason? Here is some code that might help you. Note that I haven't tested to see if this compiles, but it should give you a leg up:Scriptname RenMusicSelectQuestScript extends Quest Conditional Formlist Property MySongs Auto ; A formlist holding all your base Tapes Objectreference Property CurrentSong Auto Conditional ; use this as the conditional in your Radio Scene Objectreference Property RadioContainer Auto ; Your container that the player adds tapes into Scene Property MyRadioScene Auto ; the scene that plays the songs Event OnInit() Self.RegisterForRemoteEvent(MyRadioScene, "OnEnd") ; registers this Quest to receive the OnEnd event from the Radio Scene int tries = 0 CurrentSong = none while (tries <= 100 && CurrentSong == none) int randomnum = Utility.RandomInt(0, (MySongs.GetSize() - 1)) if ( RadioContainer.GetItemCount( MySongs.GetAt(randomnum) ) >= 1) CurrentSong = MySongs.GetAt(randomnum) ; CurrentSong now points to one of your tapes endif tries += 1 endWhile if (MyRadioScene.IsPlaying() == false) MyRadioScene.Start() ; forces the scene to start if it hasn't already endif endEvent Event Scene.OnEnd(Scene akSender) ; radio has finished playing the song scene here. CurrentSong = none int tries = 0 while (tries <= 100 && CurrentSong == none) int randomnum = Utility.RandomInt(0, (MySongs.GetSize() - 1)) if ( RadioContainer.GetItemCount( MySongs.GetAt(randomnum) ) >= 1) CurrentSong = MySongs.GetAt(randomnum) endif tries += 1 endWhile if (MyRadioScene.IsPlaying() == false) MyRadioScene.Start() endif endEvent If you end up using this code in your mod, please give me credit in the ReadMe / mod description. Edited July 8, 2016 by Reneer Link to comment Share on other sites More sharing options...
jp2x Posted July 8, 2016 Author Share Posted July 8, 2016 I absolutely will! I'll give this a try and let you know how it goes. To clarify, as I obviously have plenty to learn, "; A formlist holding all your base Tapes". A formlist containing all of the song holotapes that I've created. It's a "all possible choices" list. "Objectreference Property CurrentSong Auto Conditional; use this as the conditional in your Radio Scene" So, 'if currentsong=a certain tape' for each song. "while (tries <= 100 && CurrentSong == none)" This gives the script 100 tries to select a song and fill currentsong. Is the 100 an arbitrary number? Is it better than using MySongs.GetSize() to set tries and subtracting from the total? I'm really tired but I'll try this right now. And, thank you! Link to comment Share on other sites More sharing options...
Reneer Posted July 8, 2016 Share Posted July 8, 2016 (edited) I absolutely will! I'll give this a try and let you know how it goes. To clarify, as I obviously have plenty to learn, "; A formlist holding all your base Tapes". A formlist containing all of the song holotapes that I've created. It's a "all possible choices" list.Exactly. "Objectreference Property CurrentSong Auto Conditional ; use this as the conditional in your Radio Scene" So, 'if currentsong=a certain tape' for each song.Yup. "while (tries <= 100 && CurrentSong == none)" This gives the script 100 tries to select a song and fill currentsong. Is the 100 an arbitrary number? Is it better than using MySongs.GetSize() to set tries and subtracting from the total? I'm really tired but I'll try this right now. And, thank you!The 100 is pretty arbitrary. It's just so that the script won't get stuck in the while loop forever in case something goes wrong. It's better than MySongs.GetSize() because you could, theoretically, have the RandomInt function return multiples of the same number during different passes. Edited July 8, 2016 by Reneer Link to comment Share on other sites More sharing options...
jp2x Posted July 8, 2016 Author Share Posted July 8, 2016 (edited) Here is the code as I adjusted references: Scriptname MusiciansModRadio002a extends Quest ConditionalFormlist Property akAllHolotapeList Auto; A formlist holding all your base TapesObjectreference Property CurrentSong Auto Conditional; use this as the conditional in your Radio SceneObjectreference Property MusiciansModHolotapeAutoloader Auto; Your container that the player adds tapes intoScene Property MusiciansMod01aRadioQuest001SceneA Auto; the scene that plays the songsEvent OnInit() Self.RegisterForRemoteEvent(MusiciansMod01aRadioQuest001SceneA, "OnEnd") ; registers this Quest to receive the OnEnd event from the Radio Scene int tries = 0 CurrentSong = none while (tries <= 100 && CurrentSong == none) int randomnum = Utility.RandomInt(0, (akAllHolotapeList.GetSize() - 1)) if ( MusiciansModHolotapeAutoloader.GetItemCount( akAllHolotapeList.GetAt(randomnum) ) >= 1) CurrentSong = akAllHolotapeList.GetAt(randomnum) ; CurrentSong now points to one of your tapes endif tries += 1 endWhile if (MusiciansMod01aRadioQuest001SceneA.IsPlaying() == false) MusiciansMod01aRadioQuest001SceneA.Start() ; forces the scene to start if it hasn't already endifendEventEvent Scene.OnEnd(Scene akSender) ; radio has finished playing the song scene here. CurrentSong = none int tries = 0 while (tries <= 100 && CurrentSong == none) int randomnum = Utility.RandomInt(0, (akAllHolotapeList.GetSize() - 1)) if ( MusiciansModHolotapeAutoloader.GetItemCount( akAllHolotapeList.GetAt(randomnum) ) >= 1) CurrentSong = akAllHolotapeList.GetAt(randomnum) endif tries += 1 endWhile if (MusiciansMod01aRadioQuest001SceneA.IsPlaying() == false) MusiciansMod01aRadioQuest001SceneA.Start() endif endEvent It almost compiles. C:\Users\OWNER\AppData\Local\Temp\PapyrusTemp\MusiciansModRadio002a.psc(24,3): type mismatch while assigning to a objectreference (cast missing or types unrelated)C:\Users\OWNER\AppData\Local\Temp\PapyrusTemp\MusiciansModRadio002a.psc(44,3): type mismatch while assigning to a objectreference (cast missing or types unrelated) It seems to be having trouble with: CurrentSong = akAllHolotapeList.GetAt(randomnum)It compiles if the line is commented out both times. I am a bit concerned as the station has tapes for all of the game's base songs and I expect roughly 200+ songs by the time the mod has a formal release. If someone makes a 'favorite songs' playlist of 20 songs, that would be 20 of 200+ and 100 tries could technically fail to find a song. But, if it fails to find a song, it just starts over anyway, right? So, no big deal. Edited July 8, 2016 by jp2x Link to comment Share on other sites More sharing options...
Recommended Posts