Array vs FormlistsFunction Question

Post » Sun Aug 24, 2014 9:41 am

What exactly is the difference? Arrays don't actually exist in-game really, they're properties or variables. I get that. But what is the difference otherwise? I'm sure there's plenty, but... I'd like your opinions

Also, to create a function like the following:

I imagined it would look somewhat like this:

Int Function CountActors(Float Radius, FormList ActorsToCount); radius is how close the actors need to be to be counted, array is the actors to count within that radiusInt ActorCount; you can declare variables within functions - they can only be used within those functions, actor count is to count how many actors are within the radiusInt aIndex = ActorsToCount.GetSize    While aIndex; actor index, checks the size of the formlist        aIndex -= 1        Actor kActor = ActorsToCount.GetAt(aIndex) As Actor; forms need to be cast properly, for us we're checking for actors so typecast to an actor        If kActor.GetDistance(Self) <= Radius            ActorCount += 1; add one to count of actors within radius        EndIf    EndWhile    Return ActorCount; return amount of actors within radiusEndFunction

But from what I can tell, this would only work for unique actors. If I just pull in 10 of the same type of actor, would that formlist count 1 of that actor, or 10? So if I had 10 dunBandits (don't think those exist, but something like that - a leveled actor), and I pulled those into the formlist, would the formlist be 10 long, and thus go through 10 actors and return 10 if 10 dunBandits were within the radius, or would it be 1 long and just return 1 or 0, regardless of the amount?

User avatar
Alexis Acevedo
 
Posts: 3330
Joined: Sat Oct 27, 2007 8:58 pm

Post » Sun Aug 24, 2014 1:58 am

GetDistance can only be used on ObjectReferences, which are unique references in the world. Actor extends ObjectReference, so you can call GetDistance on specific Actors. It's not possible to call GetDistance on something like "dunBandit", because dunBandit would be an ActorBase -- which is not the same thing as an Actor, it is a generic template from which Actors (unique references) are created.

You can store Actors or ActorBases in a Formlist, though I wouldn't recommend trying to stick both in the same Formlist, because that will just become confusing in a case like this.

Regarding Arrays vs. Formlists:

Arrays are a built in datatypes for papyrus. This means that you can manipulate them very quickly, particularly if they are holding literal variable types (like int, float, bool, or string). You can iterate through a 128 member array nearly instantaneously.

On the other hand, Formlists are object-type variables. They are very good for situations where you need to interface with the game (particularly if you need to use them in conditions in the CK, etc, which you can't do with arrays). They also have no size limit which is a big plus. However, every time you do something to a Formlist, your script will be delayed and has to wait for the function to return (it may be throttled by other papyrus threads, game framerate, etc)

int i = 0while i < 128    debug.trace(myArray[i]) ;this while loop never gets delayed, so you can access data very quickly.    i += 1endWhilei = 0while i < 128    debug.trace(myFormlist.GetAt(i)) ;every time GetAt() is called, this will be delayed    i += 1endWhile

Often this delay isn't a big deal, and Formlists can be better just for the sake of convenience. But if you plan on manipulating several hundred or thousand values or forms, you may notice the performance impact.

User avatar
Riky Carrasco
 
Posts: 3429
Joined: Tue Nov 06, 2007 12:17 am

Post » Sun Aug 24, 2014 3:15 am

Expressed succinctly, FormLists handle Forms, while Arrays handle Numbers. A form inside an array does not exist as form, only as number. And as mentioned by Egocarib, arrays are much 'faster' in terms of addressing code. On the other side, formlists are much easier to handle, and it's easier to adress a form directly, while in array code you need to create a whole lot of complicated math structures to get the same result. So everyone with good math skills is obviously in advantage when coding Skyrim...Math skills would have taken my code no longer then 1 hours to do...but instead I was limited to trial and fail...:D

User avatar
RUby DIaz
 
Posts: 3383
Joined: Wed Nov 29, 2006 8:18 am

Post » Sun Aug 24, 2014 1:37 pm

So is this function possible, or would it have to be achieved a different way?

User avatar
dean Cutler
 
Posts: 3411
Joined: Wed Jul 18, 2007 7:29 am

Post » Sun Aug 24, 2014 7:42 am

Well, it's not particularly easy.

You can use FindRandomReferenceOfTypeFromRef() a few dozen times and just hope you manage to find all of them. Or you can use GetNthRef(), but that also is not foolproof since it relies on being in the same cell.

There are two better, but more complicated ways to do this:

  • Use a cloak spell with a scripted effect to locate all actors by applying the effect to them, http://www.creationkit.com/Dynamically_Attaching_Scripts
  • Or, set up a quest with some aliases that are conditioned to find particular types of actors within a certain radius.

I've used both methods and found the latter to be the most useful and intuitive.

User avatar
My blood
 
Posts: 3455
Joined: Fri Jun 16, 2006 8:09 am

Post » Sun Aug 24, 2014 2:48 am

For the sake of speed if that's a concern, I should point out that the find families are more than one call. They are more like cascading functions if that makes any sense(though SmkViper can correct me if I'm wrong). I say this because FindClosestReferenceOfTypeFromRef() will first call FindClosestReferenceFromType(). It was something I discovered when it didn't return a weapon in one of my early tests and I looked at my logs.

So I suppose using them sparingly would be good practice.

User avatar
Rude_Bitch_420
 
Posts: 3429
Joined: Wed Aug 08, 2007 2:26 pm

Post » Sun Aug 24, 2014 9:15 am

Ah, well, thank you anyway.

Just for future reference: Would having 10 dunBandits in the formlist, and calling on it like so:

Int Function CountActors(Float Radius, FormList ActorsToCount); radius is how close the actors need to be to be counted, array is the actors to count within that radiusInt ActorCount; you can declare variables within functions - they can only be used within those functions, actor count is to count how many actors are within the radiusInt aIndex = ActorsToCount.GetSize    While aIndex; actor index, checks the size of the formlist        aIndex -= 1        ActorBase kActor = ActorsToCount.GetAt(aIndex)         If kActor.GetDistance(Self) <= Radius            ActorCount += 1; add one to count of actors within radius        EndIf    EndWhile    Return ActorCount; return amount of actors within radiusEndFunction

Would that work? Also, would the formlist have a size of 10 or of 1, since they're all the same actor (kind of)?

User avatar
Ernesto Salinas
 
Posts: 3399
Joined: Sat Nov 03, 2007 2:19 pm

Post » Sun Aug 24, 2014 2:46 am

As I said, you can't call GetDistance() on an ActorBase, it doesn't make sense. You have to call it on a specific Actor that already exists.

User avatar
Mariaa EM.
 
Posts: 3347
Joined: Fri Aug 10, 2007 3:28 am

Post » Sun Aug 24, 2014 9:14 am

Alright. Oh well.

Very, very lastly:

I know you can declare variables in functions. Can you declare properties as well? I very much doubt it, due to the fact that you couldn't fill them for global functions. If I wanted to reference the GameHour global within a global function, would it be a GlobalVariable parameter which you fill with a property when calling the function?

User avatar
Heather Kush
 
Posts: 3456
Joined: Tue Jun 05, 2007 10:05 pm

Post » Sun Aug 24, 2014 4:22 am

No, you can't define properties inside functions.

You could either pass GameHour as a parameter to your global function, or you could call Game.GetFormFromFile() to retrieve GameHour by its formID. But if you have to do that it might be better to think whether that function really needs to be global, and perhaps redesign a little.

User avatar
Ana
 
Posts: 3445
Joined: Sat Jul 01, 2006 4:29 am

Post » Sun Aug 24, 2014 5:33 am

Alright, thanks.

User avatar
Jah Allen
 
Posts: 3444
Joined: Wed Jan 24, 2007 2:09 am

Post » Sun Aug 24, 2014 3:52 am

I decided to post a http://www.gamesas.com/topic/1506369-tutorial-detect-nearby-actors-using-quest-aliases/ explaining this in case it's helpful.

User avatar
Steve Smith
 
Posts: 3540
Joined: Sat Jun 30, 2007 10:47 am

Post » Sun Aug 24, 2014 10:05 am

When trying to "catch" objects in an area quickly I found the best and most reliable way was the quest &alias method. Firstly you set each alias to have conditions (like GetInFaction, or HasKeyword, or HasLocRefType), then Start() the quest. The quest logic will do all the grunt work for you in terms of finding the references.

When the quest has started you can use an array or something else to run through your list of ReferenceAlias properties and do stuff to them. Then Stop() the quest.

Easy.

Edit...

New topic :ninja:

http://www.gamesas.com/topic/1506369-tutorial-detect-nearby-actors-using-quest-aliases/#entry23745412
User avatar
Sheila Reyes
 
Posts: 3386
Joined: Thu Dec 28, 2006 7:40 am


Return to V - Skyrim