Jump to content

Papyrus help needed.


Raider1

Recommended Posts

Posted

I am hoping that some one could help me understand Arrays.   I tend to go cross eyed when trying to script and arrays and their functions make me want to do serious drugs and go kick puppies and push old ladies into crosswalks.  

 

I will probably have other questions later but this is the big one at the moment.  Thanks in advance for the help.

Posted

Well I'm not sure what it is about arrays that you find complicated. Essentially an array is just a list. It's a list of a specific type of object. In my coming example array the object type is that of ObjectReference. The only thing I can think of that people find confusing is that the first item in the array is indexed with a value of zero. So you can define an array such as ObjectReference[] myObjectArray = new ObjectReference[0]. This array has no entities in it. We created it with 0 starting entities. If we used ObjectReference[] myObjectArray = new ObjectReference[10] then our myObjectArray.Length would be 10 because we created it with 10 entities. They have no actual valid references but the array has entities pointing to nothing. We can access the existing entities with something like myObjectArray[0] this gives us the first entity in the array. Going on up to myObjectArray[9] because our index values are 0 based, meaning the number starts at 0 as opposed to 1. This is why if you look at other people's code you'll see loops like while (iCounter < myArray.Length) instead of <=. The last entity index is n-1.

 

I'm sure you've seen it already but just in case you haven't the wiki has a detailed explanation as well http://www.creationkit.com/fallout4/index.php?title=Array_Reference

 

If you need to dynamically add or remove array entities you can with the Add() and Remove() methods.

 

Sometimes people confuse arrays with FormLists or Structs. Getting slightly off topic here, Fallout 4 introduces Structs (http://www.creationkit.com/fallout4/index.php?title=Struct_Reference) as a helpful way of arranging a special type of object that has sub properties. In previous games (Skyrim like) if you wanted to do something associated like let's say have an Actor reference for an npc, then a linked home marker, and then maybe some other value. You would have to have 3 different property arrays and make sure that the index of each matches each other. Doable but kludgy some would say. With a struct you can have all 3 properties in the same base object. So you'd have something like NPC.ActorRef, NPC.HomeMarker, and NPC.SomeOtherVariable.

 

One thing that seasoned programmers hate is that you can't have arrays of arrays or arrays in structs. You can have an array of structs though.

 

I hope this helped you grasp some understanding. If not a better description of what it is you don't understand about arrays would be needed for anyone to help further.

Posted

One thing that seasoned programmers hate is that you can't have arrays of arrays or arrays in structs. You can have an array of structs though.

 

There is also an annoying array length limit of 128.

 

jaam has done some fantastic work on multi-dimensional arrays. They will be used in the next Four-Play update.

Posted

 

One thing that seasoned programmers hate is that you can't have arrays of arrays or arrays in structs. You can have an array of structs though.

 

There is also an annoying array length limit of 128.

 

jaam has done some fantastic work on multi-dimensional arrays. They will be used in the next Four-Play update.

 

 

I'm pretty curious to know how that was pulled off. The best thought I came  up with was building an array of spawned objects with a script that had an array. So you then have an array of arrays. Though not entirely sure of the logistics for managing that. Let alone performance or memory implications.

Posted

thanks for the replies.  

 

See some people are code wonks, some people's minds slid into neutral when reading tech gobbly gook. I am not a wonk LOL. though I get most of the basic scripting and can read a script and for the most part figure out how it works.  

 

 

so if I have this right, a array is a list, say of weapons or NPC's that can be called on by a script to add/subtract one or more of the items in the list to the game world.  

 

Of course again if I am getting this it can also be a list of effects and functions as well and again called on by a script.  

 

 

Posted

To some extent that's basically it. Arrays are what you would call a typed list. So you can't mix different types of objects in the list. There are some notable exceptions here though.

 

So for example you would have an array of weapons, or an array of armor. You wouldn't have an array that contained both.

 

Here's the exception. Object References. They're a special type of basic object identifier of a specific instance of something.

 

You can have an array of object references which could be any kind of object. But it's specific instances of objects not generic types.

 

If you're not familiar with object oriented programming this concept might take a but to sink in.

Posted

To some extent that's basically it. Arrays are what you would call a typed list. So you can't mix different types of objects in the list. There are some notable exceptions here though.

 

So for example you would have an array of weapons, or an array of armor. You wouldn't have an array that contained both.

 

Here's the exception. Object References. They're a special type of basic object identifier of a specific instance of something.

 

You can have an array of object references which could be any kind of object. But it's specific instances of objects not generic types.

 

If you're not familiar with object oriented programming this concept might take a but to sink in.

 

let me see if I got this..... a regular weapon/object type can be assigned to a array but only an array set up for that class of object.   But assigning a weapon, or some other object as a Object ref essentially make its a new class, the object ref class  so each Ob Ref can be one of a half dozen things its still only a Ob Ref.   sorry if that makes no sense its 0220 hrs here and I need sleep.

Posted

 

To some extent that's basically it. Arrays are what you would call a typed list. So you can't mix different types of objects in the list. There are some notable exceptions here though.

 

So for example you would have an array of weapons, or an array of armor. You wouldn't have an array that contained both.

 

Here's the exception. Object References. They're a special type of basic object identifier of a specific instance of something.

 

You can have an array of object references which could be any kind of object. But it's specific instances of objects not generic types.

 

If you're not familiar with object oriented programming this concept might take a but to sink in.

 

let me see if I got this..... a regular weapon/object type can be assigned to a array but only an array set up for that class of object.   But assigning a weapon, or some other object as a Object ref essentially make its a new class, the object ref class  so each Ob Ref can be one of a half dozen things its still only a Ob Ref.   sorry if that makes no sense its 0220 hrs here and I need sleep.

 

 

I probably didn't explain it too clearly to begin with. I was typing on my phone at work while being yelled at on the 2-way radio there.

 

Ok so you have base types of objects:

  • Weapon
  • Armor
  • ActorBase (this confuses a lot of people because there is Actor as well but that is an ObjectReference type)

There's a lot more but we'll start with these to give you some primer. They have no reference to use in the world yet. I guess maybe think of them as descriptions of something like blueprints. When you create one for use in the world it gets an ObjectReference ID and is instantiated. Think of this as a manufactured product. It is a unique reference of a specific instance of that type of object. Typically most of the time arrays will be dealing with ObjectReferences not base classes. If you wanted to have a list of base classes sometimes people will use FormLists instead. They're easier to make and change in the CK than arrays. However dynamically building and modifying arrays can be more useful depending on the circumstances. I've never actually needed to have an array of base classes myself. A FormList for comparing against or adding items like I describe below, sure.

 

I'm going to jump into a real world examples of how you might do something with both. Let's say you have a weapon, armor, grenade, and food you want to give an npc. You wouldn't use an array of those items because they're different types. You *could* do it with arrays if you wanted to make one for each time and loop through each array adding them. Arguably inefficient. You could also do it if you were to spawn each item and then place their ObjectReference in the arraylist and then loop the list adding it to the npc. Though there are far easier ways to accomplish that. Papyrus includes a nifty feature to give the AddItem method of an ObjectReference a FormList of items to add. So you could do something like this:

 

Actor Property someNPC Auto Const
FormList Property ItemsToGive Auto Const
 
Function GiveNPCItems()
    someNPC.AddItem(ItemsToGive)
EndFunction

 

This is super basic as it will give 1 of each item in the FormList to the npc. The NPC and the FormList will be set in the properties page of the script and the NPC is a unique reference.

 

An array might be used to have a list of NPC's you want to give the items to. So something like this might be done:

 

Actor[] Property NPCList Auto Const
FormList Property ItemsToGive Auto Const
 
Function GiveNPCItems()
    int iCounter = 0
    while (iCounter < NPCList.Length)
        NPCList[iCounter].AddItem(ItemsToGive)
        iCounter += 1
    endwhile
EndFunction

Now you add multiple NPCs to the array in the CK and when you call the GiveNPCItems() function it will loop through the array giving each one the items.

 

If each of the items you wanted to give were all of the same type (ie all armors) the you could use an array instead of a FormList though you'd have to iterate a loop through the array adding each entry one at a time instead of giving a singular list to add. To better illustrate how this would look I'm going to build the array in script instead of in the CK. This will not actually be valid Papyrus that can be used verbatim but should give a better visual aid.

 

Function GiveNPCItems()
    Armor[] armorList = new Armor[0]
    armorList.Add(leftArmHeavyMetal)
    armorList.Add(leftLegHeavyMetal)
    armorList.Add(rightArmHeavyMetal)
    armorList.Add(rightLegHeavyMetal)
    armorList.Add(torsoHeavyMetal)
 
    ; now our array has 5 items in it. Note arrays entities start at 0 not 1.
    ; So to get the first item we reference it with 0.
 
    int iCounter = 0
    while (iCounter < armorList.Length)
        targetNPC.AddItem(armorList[iCounter])
        iCounter += 1
    endwhile
EndFunction

We could add more items to the armor list but they must all be base armor form types. If this was a property for the script we could build the array in the CK in the properties form for the script. 

 

Now I mentioned above that Actor was a type of ObjectReference. A very common use of arrays is to house a list of created actors that a script is dealing with. Let's say you wanted to spawn 5 mole rats around the player.

 

ActorBase Property MoleRat Auto Const

Function Spawn()
    int iCounter = 0
    while (iCounter < 5)
        PlayerREF.PlaceAtMe(MoleRat)
        iCounter += 1
    endwhile
EndFunction

Now while this will do exactly that, if we wanted to then do anything with those MoleRats other than let them roam free and disregard them we can't easily. However adding them to an array during their production allows us to manipulate them later.

 

ActorBase Property MoleRat Auto Const
Actor[] rats ; we place the array in script scope instead of function scope so other functions can access it
 
Function Spawn()
    rats = new Actor[0] ; we have to initialize the array
    Actor tmpRat
    int iCounter = 0
    while (iCounter < 5)
        tmpRat = PlayerREF.PlaceAtMe(MoleRat) ; this and the add could be comprised of a single line
        rats.Add(tmpRat) ; but is left as 2 for easier readability of flow 
        iCounter += 1    
    endwhile 
EndFunction

We can then access the rats array to manipulate any or all of the mole rats we spawned. This might be an function also on the same script.

 

Function KillTheRats()
    int iCounter = 0
    while (iCounter < rats.Length)
        rats[iCounter].Kill()
        iCounter += 1
    endwhile
EndFunction

I hope this isn't too overwhelming and is somewhat easy to follow.

Posted

 

 

To some extent that's basically it. Arrays are what you would call a typed list. So you can't mix different types of objects in the list. There are some notable exceptions here though.

 

So for example you would have an array of weapons, or an array of armor. You wouldn't have an array that contained both.

 

Here's the exception. Object References. They're a special type of basic object identifier of a specific instance of something.

 

You can have an array of object references which could be any kind of object. But it's specific instances of objects not generic types.

 

If you're not familiar with object oriented programming this concept might take a but to sink in.

 

let me see if I got this..... a regular weapon/object type can be assigned to a array but only an array set up for that class of object.   But assigning a weapon, or some other object as a Object ref essentially make its a new class, the object ref class  so each Ob Ref can be one of a half dozen things its still only a Ob Ref.   sorry if that makes no sense its 0220 hrs here and I need sleep.

 

 

I probably didn't explain it too clearly to begin with. I was typing on my phone at work while being yelled at on the 2-way radio there.

 

Ok so you have base types of objects:

  • Weapon
  • Armor
  • ActorBase (this confuses a lot of people because there is Actor as well but that is an ObjectReference type)

There's a lot more but we'll start with these to give you some primer. They have no reference to use in the world yet. I guess maybe think of them as descriptions of something like blueprints. When you create one for use in the world it gets an ObjectReference ID and is instantiated. Think of this as a manufactured product. It is a unique reference of a specific instance of that type of object. Typically most of the time arrays will be dealing with ObjectReferences not base classes. If you wanted to have a list of base classes sometimes people will use FormLists instead. They're easier to make and change in the CK than arrays. However dynamically building and modifying arrays can be more useful depending on the circumstances. I've never actually needed to have an array of base classes myself. A FormList for comparing against or adding items like I describe below, sure.

 

I'm going to jump into a real world examples of how you might do something with both. Let's say you have a weapon, armor, grenade, and food you want to give an npc. You wouldn't use an array of those items because they're different types. You *could* do it with arrays if you wanted to make one for each time and loop through each array adding them. Arguably inefficient. You could also do it if you were to spawn each item and then place their ObjectReference in the arraylist and then loop the list adding it to the npc. Though there are far easier ways to accomplish that. Papyrus includes a nifty feature to give the AddItem method of an ObjectReference a FormList of items to add. So you could do something like this:

 

Actor Property someNPC Auto Const
FormList Property ItemsToGive Auto Const
 
Function GiveNPCItems()
    someNPC.AddItem(ItemsToGive)
EndFunction

 

This is super basic as it will give 1 of each item in the FormList to the npc. The NPC and the FormList will be set in the properties page of the script and the NPC is a unique reference.

 

An array might be used to have a list of NPC's you want to give the items to. So something like this might be done:

 

Actor[] Property NPCList Auto Const
FormList Property ItemsToGive Auto Const
 
Function GiveNPCItems()
    int iCounter = 0
    while (iCounter < NPCList.Length)
        NPCList[iCounter].AddItem(ItemsToGive)
        iCounter += 1
    endwhile
EndFunction

Now you add multiple NPCs to the array in the CK and when you call the GiveNPCItems() function it will loop through the array giving each one the items.

 

If each of the items you wanted to give were all of the same type (ie all armors) the you could use an array instead of a FormList though you'd have to iterate a loop through the array adding each entry one at a time instead of giving a singular list to add. To better illustrate how this would look I'm going to build the array in script instead of in the CK. This will not actually be valid Papyrus that can be used verbatim but should give a better visual aid.

 

Function GiveNPCItems()
    Armor[] armorList = new Armor[0]
    armorList.Add(leftArmHeavyMetal)
    armorList.Add(leftLegHeavyMetal)
    armorList.Add(rightArmHeavyMetal)
    armorList.Add(rightLegHeavyMetal)
    armorList.Add(torsoHeavyMetal)
 
    ; now our array has 5 items in it. Note arrays entities start at 0 not 1.
    ; So to get the first item we reference it with 0.
 
    int iCounter = 0
    while (iCounter < armorList.Length)
        targetNPC.AddItem(armorList[iCounter])
        iCounter += 1
    endwhile
EndFunction

We could add more items to the armor list but they must all be base armor form types. If this was a property for the script we could build the array in the CK in the properties form for the script. 

 

Now I mentioned above that Actor was a type of ObjectReference. A very common use of arrays is to house a list of created actors that a script is dealing with. Let's say you wanted to spawn 5 mole rats around the player.

 

ActorBase Property MoleRat Auto Const

Function Spawn()
    int iCounter = 0
    while (iCounter < 5)
        PlayerREF.PlaceAtMe(MoleRat)
        iCounter += 1
    endwhile
EndFunction

Now while this will do exactly that, if we wanted to then do anything with those MoleRats other than let them roam free and disregard them we can't easily. However adding them to an array during their production allows us to manipulate them later.

 

ActorBase Property MoleRat Auto Const
Actor[] rats ; we place the array in script scope instead of function scope so other functions can access it
 
Function Spawn()
    rats = new Actor[0] ; we have to initialize the array
    Actor tmpRat
    int iCounter = 0
    while (iCounter < 5)
        tmpRat = PlayerREF.PlaceAtMe(MoleRat) ; this and the add could be comprised of a single line
        rats.Add(tmpRat) ; but is left as 2 for easier readability of flow 
        iCounter += 1    
    endwhile 
EndFunction

We can then access the rats array to manipulate any or all of the mole rats we spawned. This might be an function also on the same script.

 

Function KillTheRats()
    int iCounter = 0
    while (iCounter < rats.Length)
        rats[iCounter].Kill()
        iCounter += 1
    endwhile
EndFunction

I hope this isn't too overwhelming and is somewhat easy to follow.

 

 

Thanks for taking the time to type all that out, I do better at understanding with examples LOL. 

 

Let me go over this before I ask any questions.  

Posted

after going over the work you provided, I get it thanks.   adding your post to my mod tut files LOL  Thanks

 

 

Every time I've added stuff in my mods (mostly FNV), I've scripted it out for each object or NPC. .  this stream lines things and keeps script bloat from being as big an issue. 

 

now to try a practical application in my current WIP and see what happens.  

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

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