Jump to content

ArronDominion

Premium Member
  • Posts

    250
  • Joined

  • Last visited

Posts posted by ArronDominion

  1. If you are using it as a dialogue condition, using a global might be more desired.

    But if you just want other scripts to view it, use the above script.

     

    Edit:

    For the above method, here is a resource that might be helpful since it goes over the fringe cases as well as the basic cases for accessing Properties from other scripts:

    Variables and Properties

  2. I got confused about the auto-assign part of the original post, my bad. All of what I was talking about was that you needed the ReferenceAlias property to be pointing at something in your quest(s) in order to work. For your actor properties, you can use your Papyrus logic to assign the Actor properties.

     

    These might be functions to look at ForceRefIfEmpty() and Clear() for the Aliases, but I am not sure if they would be what you are looking for.

  3. Here is a more concrete example, based on some of the functionality I created for MHARPHIN. This particular example is designed to be attached to your custom NPC, and only accounts for one sound marker with 6 sounds in the sound descriptor and does not account for playing an animation:

     

     

    ScriptName DahveedNPCBardTestScript Extends Actor
    
    ;Our current sound ID - is set to 0 and defaults to 0.  Hopefully ID 0 is never called.
    Int Property CurrentSoundPlayingID  Auto  
    ;Our first sound marker
    Sound Property Sound1  Auto
    ;The state of the marker, can have up to 6 states 
    Int Property SoundMarker1State  Auto
    ;Global that holds CurrentSoundPlayingID so can check for it
    GlobalVariable Property GobalMusicControl  Auto  
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;Inputs: Choice to tell the sound to play (allows for moddability), and NPC for the speaker
    ;
    ;This function is designed to play a sound from a NPC upon Function call
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    Function PlayNPCSound(Int Choice, Actor NPC)
    
    	;Choice logic
    	;1 = Sound1
    	if (Choice == 1)
    		CurrentSoundPlayingID = Sound1.Play(NPC)
    		GobalMusicControl.SetValue(CurrentSoundPlayingID)
    		;So the Sound ID resets if the sound finishes before the next call - 325 since this is the complete time for both
    		;However due to how Skyrim calls the Sound Play() function, we will have to keep track of the current song being played
    		if SoundMarker1State == 0
    			;The length of the first piece
    			RegisterForSingleUpdate(173.0)
    			;Prepare the logic to call the next song properly
    			SoundMarker1State = 1
    		ElseIf SoundMarker1State == 1
    			;The length of the last piece
    			RegisterForSingleUpdate(183.0)
    			;Prepare the logic to go back to the beginning of the song queue, aka the first song
    			SoundMarker1State = 2
    		ElseIf SoundMarker1State == 2
    			;The length of the last piece
    			RegisterForSingleUpdate(189.0)
    			;Prepare the logic to go back to the beginning of the song queue, aka the first song
    			SoundMarker1State = 3
    		ElseIf SoundMarker1State == 3
    			;The length of the last piece
    			RegisterForSingleUpdate(183.0)
    			;Prepare the logic to go back to the beginning of the song queue, aka the first song
    			SoundMarker1State = 4
    		ElseIf SoundMarker1State == 4
    			;The length of the last piece
    			RegisterForSingleUpdate(189.0)
    			;Prepare the logic to go back to the beginning of the song queue, aka the first song
    			SoundMarker1State = 5
    		Else
    			;The length of the last piece
    			RegisterForSingleUpdate(175.0)
    			;Prepare the logic to go back to the beginning of the song queue, aka the first song
    			SoundMarker1State = 0
    		EndIf
    	EndIf
    EndFunction
    
    ;Plays at the very beginning
    Event OnInit()
    	PlayNPCSound(1,self)
    EndEvent
    
    Event OnUpdate()
    	PlayNPCSound(1,self)
    EndEvent		
    

     

     

  4. There are several approaches I could see on how to tackle this (might not work or work necessarily as planned, only how I would start to tackle the problem).

     

    The first, and probably more of a brute force (but should be highly compatible) approach would be to have a script listening for OnUpdateGameTime() using some trigger to RegisterForSingleUpdateGameTime(0.0244) (0.0244 translates to 14.64 in-game minutes [pretty small time interval all in all]). Have a property containing the player and check their current health compared to their max health, and transport the player if it falls under a certain percentage.

     

    Another approach (probably not as compatible as the other) would be to attach a script to the player itself to listen for the OnEnterBleedout() event. If the player starts to enter that state, do the action you want (which you can check to see if the player is the one bleeding out in the script) [Not sure if you could instead use the event within the same script for your UpdateGameTime() attempt. If you can, it will be more compatible than attaching it to the player].

     

    Since an Actor is also an ObjectReference, there are a few events that ObjectReference's listen for that might be helpful in trying to determine player health state or player living state. Hope this helps.

  5. Sounds like you just want a NPC playing an idle animation that loops, and sound to come from them.

     

    You will want to attach a script to your NPC. You will want to have properties for all the SoundMarkers representing the songs you want them to play. You will want properties to keep track of the SoundMarkerState if there is more than one song (I.E. a SoundDescription that the SoundMarker is pointing to is composed of 4 sounds, you want logic for all 4).

     

    I recommend either creating an array of SoundMarkers or a FormList so you can keep track of what SoundMarkers have been played (if you want the songs to be picked at random, otherwise ignore this part).

     

    You might want to use OnInit() to call your song playing function. Within your play function you want to use RegisterForSingleUpdate() with the time being the length (in seconds) of the song. You want an Int property to keep track of the song choice you want next for your function logic. In your OnUpdate() you want to call your play function again with the Int property containing your song choice. Within the play function, if you reach the end of the list, and the final sound marker has been played once, you will want to reset your song play property to the first choice and reset the marker states back to their initial values.

     

    Hope this helps.

  6. Hello,

     

    I was recently in an accident which makes it uncomfortable to use my desktop currently. Yet I am still receiving questions on scripts without an ability to test my response, or scripting requests.

     

    I have a 7 yrs old laptop that I could write the scripts on, but Skyrim runs really slow on it (Could do Steam in-home

    streaming but that seems difficult to setup for both modding and testing). I also have a 4 yr old Android tablet, and a Samsung Galaxy S4 (using it for this post).

     

    My first question is if there is a mobile app that works for scripting? The next question if not, is there an easy way to setup the laptop/desktop to remote into each other (one is Win 7 Ultimate 64-bit and the other is Win 7 custom-Enterprise build (thanks college)32-bit?

  7. "=" is used for giving variables values where modifiers such as "+=" are used to do quick value changes to an existing variable.

     

    So in this case, you created a variable "x". "x" does not know its value. You have to give it the value. "x = 10" gives "x" the value of 10.

     

    Now "+=":

     

    Let's say you gave "x" the value of 10. "x += 10" will translate to "x = x + 10" which translates to "x = 10 + 10" which gives "x" the value of 20. Calling "x += 10" again will translate to "x = x + 10" which translates to "x = 20 + 10" giving "x" the value of 30.

     

    Before this post, I always assumed a C-like approach to variables requiring a value before use, but it is good to know that Papyrus defaults values to 0. It is good practice to use "=" when you first create a variable instead of a modifier such as "+=". Using "=" will eliminate potential value-logic errors.

     

    Using "=" also allows for more complex operations in one line.

    Ex:

    "x = 10"

    "x += Health"

    "x -= Damage"

    "x *= Weakness"

    can translate to

    "x = 10 + Health - Damage * Weakness" (In this statement use your order of operations, since Papyrus uses order of operations when assigning values. Damage*Weakness will be computed first with 10 + Health - ResultOfDamageWeaknessMultiplication being computed last)

  8. Something else (outside of the good tutorials here and suggestions here) that is helpful while scripting is to get your mind into a mindset where you are thinking of everything in Skyrim as an object. So take the player real quick as an Actor object. Since Actor is a sub-object type [terminology is wrong but helps with the point], it is also of type ObjectReference and Form which means the functions and events that ObjectReferences and Forms can use are also usable on an Actor, in addition to the Actor functions and events. The creation kit wiki has this object map that can help with keeping track of what is a sub-object of another object.

     

    As Matthiaswagg was saying look at the vanilla scripts. Usually they have decent comments (sometimes not, especially on some of the DLC scripts). Try recreating the vanilla script from scratch, which helps give another level of understanding outside of just looking over the 'code'. Additionally, on items such as the Bookcase scripts, try modifying the scripts to support either a different item type or add on to where the case can support either books or another item type as this will help you understand the mechanics.

     

    A lot of scripting is thinking of an idea and trying to use the tools before you to accomplish the idea. Making an idea map for what functionality you wish to achieve, and list a non-code oriented algorithm can help if you don't know where to start.

    Example in the spoiler:

     

     

    Idea: I want to consume some bread and have the rate of stamina regeneration decrease while the effect is running.

     

    Steps:

    1. You want to keep track of what character ate the bread.

    2. You want to give a basic stamina rate on the start of the bread being eaten.

    3. You want to setup what the value will be next.

    4. You want to setup an update to decrease the rate.

    5. You want to setup an end-point where the updating will stop.

     

    What related things will I think I need:

    -Probably need ActiveMagicEffects

    -Need an Actor property for the character

    -Need a Float (since decimals) property for the Stamina rate

    -Need to look at the Actor script wiki page to see what function will MOD the rate.

    -Look at the OnUpdate or OnUpdateGameTime events to see which one you want

    -Need an Int Property as an internal clock so you know when to stop

     

    What other things are needed that have not been listed which will either be known or require looking up while scripting:

    -Knowledge of If-ElseIf-EndIf blocks

    -Difference of Floats and Ints (decimals vs non-decimals)

    -Arithmetic for the decreased Stamina rate (just subtracting in this case)

    -How to modify values on an Actor

    -What Actor value controls Stamina

     

     

     

    Always have the creation kit wiki open when working on scripts. It becomes a great look-up for functions/events on what you are working on and the descriptions for the majority of the items are helpful for understanding the full effects of the functions or events.

     

    Lastly, experimentation is how to expand on scripting ultimately. You end up learning a lot through just throwing ideas and troubleshooting when they don't work. When you do figure something out, use the semi-colon ( ; ) for single-line comments to note what the function does or the code block does, or { } for a multi-line comment so you can write your thoughts down.

     

     

    You might see the following style in some of my scripts, just do it for readability:

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;Input: none
    ;
    ;Moves the XMarkerHeadings
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    Function MoveMarkers()
    ;code in here somewhere
    EndFunction
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;Input: The target location
    ;
    ;Moves the XMarkerHeadings
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    Function MoveMarkersTargetNeeded(Actor target)
    ;code in here somewhere
    EndFunction
    

     

     

     

     


    AHHHH f*** f*** f*** F THIS s*** OH MY f*#@IGN GOD THERE IS LIKE NOTHIGN ON THIS s*** WTF IS GOING ON WHAT IS THIS SCRIPTING s***

     

    Expect a lot of moments like this even when you think you know what you are doing, as scripting problems are logic problems which take time to process, implement, debug, then use as intended [mostly intended at least].

     

    Edit:

    Talking to/Asking someone, or talking out-loud will help process your ideas if all else is currently failing, or help you find a solution you were not originally thinking of.

  9. Unfortunately you still have to cycle through the doors in some shape or form, as Papyrus doesn't have a function to give a door a key to open it with. You can set the lock level and lock status with a script though with the SetOpen() and SetLockLevel(). Depending on how you did this, you would either have to attach this script to every single door (if you didn't make your own prison door form in the Creation Kit), or add it to a custom door form in the Door object list, and it should apply to each of your doors (though you still have to go through and specify the key individually).

  10. Are all of your traveler NPCs new [to reduce incompatibilities]? If so, as another option, then why not attach an Actor script to them?

     

    If you have setup your NPCs to have travel packages at certain times of the day, create a package for the times that you want them disabled. Then check at package ending if the last travel package was the final package so you can disable them, and if it is your package for when they are disabled as the final one to re-enable them.

     

    Below is an example of an actor script to do this [haven't tested to see if the packages are still evaluated when they are disabled, so you might have to do some GameTime checks]:

     

     

     

    Scriptname TravelingEnableDisableScript extends Actor  
    
    Package Property TravelingPackage Auto
    Package Property NotTravelingPackage Auto
    
    ;When the Actor this script is attached to ends a package, this event will Trigger
    Event OnPackageEnd(Package akOldPackage)
    	;Check to see if the akOldPackage is our Traveling Package
    	if (akOldPackage == TravelingPackage)
    		;Disable the NPC
    		self.Disable()
    		;Register for a GameTime Update in case the next is not evaluated - SET TO DISABLED
    		;RegisterForSingleUpdateGameTime(5.0)  Set for an update in 5 hours from the time the Traveling Package ended
    	;ElseIf (akOldPackage == NotTravelingPackage)
    		;self.Enable()
    	Else ;The case where it is the NotTravelingPackage.  You should only use If-Else in the case of two packages.  
    		 ;If there are other packages, change this to an ElseIf	in a similar fashion to the TravelingPackage check.
    		 self.Enable()
    	EndIf	 
    EndEvent
    
    {
    ;When the registered update is completed, it will re-enable the NPC for the TravelingPackage
    ;Currently Commented Out
    Event OnUpdateGameTime()
    	self.Enable()
    EndEvent
    }
    

     

     

  11. Well the error is from Windows XP not having that linked library ADVAPI32.dll (only Win XP 64 bit and above have this dll from what I read on a stack overflow comment), and there isn't a way to really fix that issue. It also notes on the Oscape page: Requires Vista (and up).

     

    Looking at the referred programs (haven't tried any of this), you might want to try TES4qLOD (the 2010 version):

    http://www.oceanlightwave.com/morrowind/TES4qLOD.html

  12. Honestly you don't necessarily need to go all out for a 900 series nVidia geForce, you can rely on a 700 series, (heck if you aren't planning on anything 4K a nVidia 580 GTX might be enough for Ultra settings). If you are planning on having this machine for some time and play games outside of Skyrim that will be demanding (such as Star Citizen, or any of the current AAA titles), you will want the 900 series card.

     

    My original rig used 3x nVidia geForce 580 GTX 1.5 GB in 3-way SLI. I noticed worse performance for Skyrim in most cases (and most games) at the time (and two of the cards failed back-to-back, making for a bad experience on a college free-time night and a waste of money). The only reason I would see for having multiple cards would be if you planned for a multiple monitor setup. One of my college friends decided to use 3 22 inch(think I got the size right) Dell monitors (1920x1080 if I remember them correctly) for Skyrim, which required quite a bit of tweaking, but ended up with a good Surround-screen experience.

     

    The i7 is probably a good future proof choice if you are utilizing your new machine for more than Skyrim, but an i5 is enough for current games and Skyrim.

  13. As an update for the CTD issue if anyone is curious or runs into Sound Descriptor related CTD in the future, there is a limit on how big a sound file can be. Roughly 3 min 10 sec for the length. After talking to one of my programming friends, the thought is that this is most likely due to the console's memory limit, and the handling for sound on the console being carried over to the PC version.

  14. I recently tested out a script in another thread in order to assist in fixing CTD when selecting sounds. I stored the current sound ID in an Integer property, and when I called StopInstance(CurrentSoundID) before resetting attempting to play the same SoundMarker, it would cause the particular SoundMarker to break and not play. I did a simple work-around by simply not calling PlayNPCSound() until it is technically finished in terms of seconds, but it is somewhat frustrating not understanding what is happening behind the black box of StopInstance() [documentation is little on the Creation Kit page].

     

    I would like to understand what the side-effects of Sound.StopInstance() besides simply stopping the current sound playback, if anyone happens to know.

  15. I imagine you want to utilize Messages for the menu. Specifically, the Show() function. You will probably want to do the meat of your work within the choice logic. I imagine you want to disable your current exterior references (or move them if you decided to just reuse the ship and move the location, might take some more marker setup if you decide to utilize it that way), enable your future exterior reference (or have your reference moved as mentioned earlier), lock the door or whatever you want to do for the player to wait before they can exit the ship, and register for a single update either in game time or real time. You will also want to keep track internally what choice was performed for your update event.

     

    I would probably move that functionality into a function so you can call the function with the correct parameters (the current references, your future references, and the door in use currently) instead of rewriting the logic multiple times. In your update, you will want to check for the choice. Within this choice logic, you will want to enable the door to your new exterior that the player has arrived at. You might want to display a message to allude to the ship arriving.

  16. Sound.Play() has a return value of type Integer. This integer is the unique ID of the current playback, meaning you shouldn't require physical copies of the marker. Below is an example of how you could integrate this (with commented assumptions on quest structure, and one tiny potential bug concerning the global, which probably could be corrected by registering for a single update with the seconds of the current sounds you are playing calling an update event to reset the global, but I haven't tested it):

     

    The Quest Script:

     

     

    Scriptname SoundScriptExample extends Quest
    
    ;These are examples of properties I imagine for this situation
    ;The global is used to keep track and see if you are currently playing one of your sounds
    ;It will never reset back to 0 in its current form, so you might have to rethink that part
    Int Property CurrentPlayingSoundID Auto Hidden
    Global Property YouAreCurrentlyPlayingASound Auto
    Sound Property YourSoundMarkerName Auto
    Sound Property YourSecondSoundMarkerSoundName Auto
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;The purpose of this function is to cease the current playback and play the sound again
    ;In this example, I am utilizing two different markers to show choice logic
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    Function CeaseCurrentPlaybackAndPlaySoundAgain(Actor SpeakingNPC, Int SoundChoice)
    	;Release your current Sound playback
    	StopInstance(CurrentPlayingSoundID)
    	
    	;Call your normal sound function
    	PlaySoundFromChoice(SpeakingNPC, SoundChoice)
    EndFunction
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;The purpose of this function is to play a sound based on an input, storing the play id
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    Function PlaySoundFromChoice(Actor SpeakingNPC, Int SoundChoice)
    	;Choice logic
    	;0 = YourSoundMarkerName
    	;1 = YourSecondSoundMarkerSoundName
    	;Change your CurrentPlayingSoundID
    	;Choice Logic
    	;0 = YourSoundMarkerName
    	;1 = YourSecondSoundMarkerSoundName
    	If Choice == 0
    		CurrentPlayingSoundID = YourSoundMarkerName.Play(SpeakingNPC)
    	Else ;Choice 1
    		CurrentPlayingSoundID = YourSecondSoundMarkerSoundName.Play(SpeakingNPC)
    	EndIf	
    	
    	YouAreCurrentlyPlayingASound.SetValue(1)
    EndFunction
    
    ;Garbage function for kmy initialization
    Function Garbage()
    	;Indeed
    EndFunction
    

     

     

     

    The Dialogue Fragments:

     

     

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;This portion is for your first Dialogue Fragment
    ;I decided to have a global keep track to see if a sound is currently playing so I could use that a dialogue condition
    ;There is probably a more elegant way to tackle this.
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    (GetOwningQuest as SoundScriptExample).PlaySoundFromChoice(akSpeaker, 0)
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;This portion will be used within the version of the Dialogue with the global check
    ;Again, there is probably a more elegant and efficient way to integrate this
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    (GetOwningQuest as SoundScriptExample).CeaseCurrentPlaybackAndPlaySoundAgain(akSpeaker, 0)
    
    

     

     

     

    kmyQuest initialization:

     

     

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;This portion will be used within your quest stage in the kmy block
    ;Set the kmyQuest to SoundScriptExample, or whatever your script is named within the Quest
    ;It might give you an initial error, I know it does in my CK, just close the quest and reopen to see if it properly compiles
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    kmyquest.Garbage()
    

     

     

  17. You do not need to place your SoundMarker in the cell. With the SoundMarker in the properties tab (although I have run into issues with the property not adding itself to the fragment, which is why I posted a Quest script method), it will automatically go to your speaking NPC when you call to play it from the speaking NPC.

×
×
  • Create New...