Jump to content

Little Jimmy's Papyrus Scripting Thread


Dragonblood

Recommended Posts

This thread is for anything involving Papyrus. 

I hope you like the title. It is supposed to be non-authoritarian and inviting. 

Have any array functions you are interested in sharing? I didn't think so, but it was worth a try. 

Creation Kit Wiki Papyrus

Papyrus Events
Script Objects
Threading
Non-delayed Native Function

Many of these will not work in Papyrus. They are for the conditions template. I find them useful.
Condition Functions

Chesko Array Resources
General-purpose Array Functions
Beyond 128: "Extended" Array Functions to go to 512 and up
[]
[]
[]

 

 

;=============================================================================================================
                                               ;ARRAY FUNCTIONS
;=============================================================================================================

 


Int function TestSortCount( Int i = 0)
;Author: Dragonblood

int len = QuestBooks.Length
bool IsFound
int EmptyPosition
int c
while i < len
If QuestBooks[i]  
  If IsFound
    QuestBooks[EmptyPosition] = QuestBooks[i]
    QuestBooks[i] = none
    EmptyPosition = EmptyPosition + 1
    i = i + 1
    c = c + 1
  Else
    i = i + 1
    c = c + 1
  EndIf
Else
  If IsFound 
    i = i + 1
  Else
    IsFound = true
    EmptyPosition = i
    i = i + 1
  EndIf
EndIf
EndWhile
Return c
EndFunction

Here is a function for sorting reference aliases.  It should work as is but I did not test it as I am not going to be using it now. It does compile.

    Int function SortandCountRefAliases( Int i = 0)
        ;Author: Dragonblood
        
    
        bool IsFound
        int EmptyPosition
        int c
        while i < BAL ; The length of the array or the filled positions.
        ObjectReference B = BooksAlias[i].GetReference()
        If B
          If IsFound 
            BooksAlias[EmptyPosition].ForceRefTo(B)
            BooksAlias[i].Clear()
            EmptyPosition = EmptyPosition + 1
            i = i + 1
            c = c + 1
          Else
            i = i + 1
            c = c + 1
          EndIf
        Else
          If IsFound 
            i = i + 1
          Else
            IsFound = true
            EmptyPosition = i
            i = i + 1
          EndIf
        EndIf
        EndWhile
        Return c
        EndFunction

Here is an array function for filling reference aliases. 

bool function FillRefAlias(ObjectReference BK)
          
    int i = 0

    while i < 100

    ReferenceAlias r = BooksAlias[i]
     ObjectReference ba = r.GetReference()
        If ba
            If ba == BK
               Return false
            EndIf   
        Else
            If r.ForceRefIfEmpty(BK)
                Return true
            EndIf
        EndIf

        i = i + 1

    EndWhile
          
          Return false
            
      endFunction

 

Link to comment
Share on other sites

  • Dragonblood changed the title to Little Jimmy's Papyrus Scripting Thread

Here is a post from SMKViper on Beth.  It is called a spinlock. Used to prevent a function from firing before another has ended.

"Even if it is sent in twos if the begin and end events fire close enough they might fire in reverse order. I'm assuming whatever SneakStarted does would be bad if it never wore off because SneakEnded was called first. Also, whatever you've done in your lock basically broke the lock - you don't care if the lock state equals the sneaking state. Otherwise you're going to have SneakState(…, false) looping forever, stuck waiting for a lock to be taken, and then run at the same time as SneakState(…, true)

Example that prevents the issue:" - SMKViper

bool lock
int sneakCounter
Function SneakState(ObjectReference aRef, bool aSneaking)
  while lock
    Utility.Wait(1)
  endWhile
  lock = true
  if aSneaking
    sneakCounter += 1
    if sneakCounter == 1
      ; the counter went from 0 (not sneaking) to 1 (sneaking) - so we know we're sneaking now, and events aren't out of order
      SneakStarted(aRef)
    endIf
    ; if the counter is >1, then we've already called SneakStarted and there's no need to call it again
    ; if the counter is now 0 or <0, then we've received more sneak end events than sneak started events, and haven't "caught up" yet
    ; so we don't want to start sneaking, because we likely aren't sneaking
  else
    sneakCounter -= 1
    if sneakCounter == 0
      ; the counter went from 1 (sneaking) to 0 (not sneaking) so we know we're not sneaking now, and the events aren't out of order
      SneakEnded(aRef)
    endIf
    ; if the counter is >1, then we've received more sneak start events than sneak end events, and haven't "caught up" yet
    ; so we don't want to start sneaking, because we likely aren't sneaking
    ; if the counter is <0, then we've already called SneakEnded and there's no need to call it again
  endIf
  lock = false
endFunction

 

Link to comment
Share on other sites

5 hours ago, Dragonblood said:

while i < QuestBooks.Length
  (do stuff)
EndWhile

This is bad, because it means that your script will need to evaluate the length of the array in every cycle of the loop. The only reason to do this would be in a case where the code in the loop changes the length of the array (though AFAIR, this is not possible in Skyrim scripting). To save the time for the superfluous array length evaluations, do it as follows:

len = QuestBooks.Length
while i < len
   (do stuff)
endWhile

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 5/30/2021 at 2:54 PM, Sclerocephalus said:

This is bad, because it means that your script will need to evaluate the length of the array in every cycle of the loop. The only reason to do this would be in a case where the code in the loop changes the length of the array (though AFAIR, this is not possible in Skyrim scripting). To save the time for the superfluous array length evaluations, do it as follows:











len = QuestBooks.Length
while i < len
   (do stuff)
endWhile

 

Hey Sclerocephalus, Nice to meet you! You are 100% correct. In the live script I use the count returned by the function. It is stored outside. That way it is only checking the filled spaces of the array, not all of them.  Using that in a while loop is not good coding. Thanks!

 

  1. Right click on B, click Add Masters and chose A
  2. Right click on B and select "Inject Forms Into Master..." menu, chose A. It will ask to optionally preserve ObjectIDs (the YYYYYY part in FormIDs XXYYYYYY numbers), in your case it doesn't matter when simply merging two mods.
  3. Expand B, select all record groups, right click, hold Ctrl+Shift and click "Deep copy as override into", chose A. Say Yes to overwrite any changes if asked.
  4. Close and save A only. Now you have A+B properly merged into A. - Zilav

 

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...