Passing Properties as Parameters

Post » Wed Mar 11, 2015 11:49 am

Say I wanted to perform the same operations on a number of properties of the same type in a script. My first inclination would be to create a function that takes that type as a parameter and call it with each of the properties. For this to work the function would have to be passing the properties by reference so that the properties remain changed after the function is done.

My questions are:

1) Would this work? If so, is there anything special needed to make sure the properties are passed by reference and not passed by value?

2) Is there a better way to do this?

Example:

...Actor property ActorBase autoActor property Actor1 autoActor property Actor2 autoActor property Actor3 autoObjectReference property Origin autoint[] property Position autoFunction MyFunction()	Helper(Actor1)	Helper(Actor2)	Helper(Actor3)EndFunctionFunction Helper(Actor actor)	actor = Origin.PlaceAtMe(ActorBase) ;fill each ActorX property with a copy of ActorBase	actor.MoveTo(Origin, Position[0], Position[1], Position[2]) ;move each ActorX property to the location specifiedEndFunction;Doing other things with the updated ActorX properties here...

Side Note: Not sure if what I have inside the Helper function above would actually work, so if you have feedback on that feel free to give it as well.

User avatar
Darian Ennels
 
Posts: 3406
Joined: Mon Aug 20, 2007 2:00 pm

Post » Wed Mar 11, 2015 4:52 am

In Papyrus, all object-type variables are essentially passed by reference. So, an Actor type property like you have above is passed by reference. The same single Actor is manipulated by any function that touches those properties.

Literals (int, bool, float, string) are the only types that are not passed by reference. These are always passed by value in Papyrus. [However, properties of literal types, like any property, are essentially global variables. They can be accessed from any function, or even from another script by using the syntax SourceScript.SomeProperty. So there are still ways to access them, even though you can't pass them by reference through a function parameter]

Illustration:

Spoiler
Scriptname exampleActor property Ted autoEvent OnInit()    SomeFunction()EndEventFunction SomeFunction()    Ted.ModActorValue("Health", 10.0)    OtherFunction(Ted)EndFunctionFunction OtherFunction(Actor Harry)    Harry.ModActorValue("Health", 10.0)    Ted.ModActorValue("Health", 10.0)EndFunction

After the script above runs, Ted's health is increased by 30 (Harry is the same as Ted).

Spoiler
Scriptname exampleInt property Ted = 0 autoEvent OnInit()    SomeFunction()EndEventFunction SomeFunction()    Ted += 10    OtherFunction(Ted)EndFunctionFunction OtherFunction(Int Harry)    Harry += 10    Ted += 10EndFunction

After the script above runs, Ted equals 20 (Harry is not the same as Ted)

User avatar
Isabell Hoffmann
 
Posts: 3463
Joined: Wed Apr 18, 2007 11:34 pm

Post » Wed Mar 11, 2015 3:42 am

But that example code can't work, because your Actor1, Actor2, etc. are simple variables that hold objects, not objects themselves. They would get passed to your Helper function by value.Of course if you really are doing something like your example, you should be using arrays anyway.
Actor property ActorBase autoActor[] property ActorsObjectReference property Origin autoint[] property Position autoFunction GenerateActors()	Actors = new Actor[3]	int i = actors.length	while i > 0		i -= 1		actors[i] = Origin.PlaceAtMe(ActorBase)		actor.MoveTo(Origin, Position[0], Position[1], Position[2]) ;move each ActorX property to the location specified	endwhileEndFunction;Doing other things with the updated ActorX properties here
For a different type of function, I might have been using an array that was filled in the CK instead of creating it, but the principle is the same.
User avatar
Sami Blackburn
 
Posts: 3306
Joined: Tue Jun 20, 2006 7:56 am

Post » Tue Mar 10, 2015 8:24 pm

Bookmarked. This is a handy little reference.

I have a related question. I've run into the situation with arrays of literals where:

float[] array1 = new float[3]array1[0] = 1.0array1[1] = ... float[] array2  = array1array2[0] = 5.0 debug.trace(array1[0])---> 5.0

Is this a real phenomenon? (Or was I possibly screwing something up somewhere else in the script?)

I ended up creating a separate function to create float[] array2 by passing array1 as an argument. That worked as you described -- it did not alter array1.

User avatar
Gen Daley
 
Posts: 3315
Joined: Sat Jul 08, 2006 3:36 pm

Post » Wed Mar 11, 2015 7:02 am

Arrays are objects not simple types. Only the CK or the "new" operator create arrays. When you used "array2 = array1" you just gave your first array another name, you didn't create a second one.
User avatar
Natalie Harvey
 
Posts: 3433
Joined: Fri Aug 18, 2006 12:15 pm

Post » Wed Mar 11, 2015 2:59 am

So does the code you give actually create objects for each of the Actors in the array based off of Actorbase, or is it just doing the same thing as my example but with an array? From your last comment on arrays it seems like the former. If the latter, how would you suggest going about creating multiple actors based off of one actor in a script?

Also, your GenerateActors() would look like this, correct?

Function GenerateActors()	Actors = new Actor[3]	int i = Actors.length	while i > 0		i -= 1		Actors[i] = Origin.PlaceAtMe(ActorBase)		Actors[i].MoveTo(Origin, Position[0], Position[1], Position[2]) ;move each ActorX property to the location specified	endwhileEndFunction
User avatar
sw1ss
 
Posts: 3461
Joined: Wed Nov 28, 2007 8:02 pm

Post » Wed Mar 11, 2015 10:11 am

Awesome, thanks!

Edit: Sorry for the double-post. Didn't think to use MultiQuote at first.

User avatar
Kieren Thomson
 
Posts: 3454
Joined: Sat Jul 21, 2007 3:28 am

Post » Wed Mar 11, 2015 10:11 am

I was modeling after your code which does generate three new actors to fill the Actor1, Actor2, and Actor3 properties. The PlaceAtMe function always creates new instances of something. That's why I named by example function GenerateActors. Because of that first line creating a new array, if there were already values in Actors, those earlier actors will be left in the world, but no longer monitored by the script and three new ones will be generated each time the GenerateActors function is called.
User avatar
David John Hunter
 
Posts: 3376
Joined: Sun May 13, 2007 8:24 am


Return to V - Skyrim

cron