Talk:Variables and Properties
Conditional propertiesEdit
What does it actually mean if a property is "conditional"? I'm assuming this means I can access it through conditions in spells and such, is this right? Fowl 20:24, 7 February 2012 (EST)
- The conditional keyword seems to be described here - Papyrus Introduction: Writing Custom Functions
- It's hardly the most obvious place, however. Perhaps the keyword reference should be expanded?
- -- Cipscis 20:29, 7 February 2012 (EST)
- That's awesome, thank you. I'm going to add that link to the article Fowl 19:13, 8 February 2012 (EST)
Manipulating PropertiesEdit
I can't seem to get the referencing. I'm in an active magic effect (AME) script wanting to add/subtract on an Int property attached to a quest script. I have a quest property (called QST) attached to the AME script whose value is the quest whose Int property I want to manipulate. But doing a line like (from within the AME script):
QST.IntProperty += 1
just gives a compile error saying that the quest doesn't have property "IntPropery." So, I'm thoroughly confused. I don't completely understand "casting," either. That may have something to do with it. --Doulos 04:53, 11 February 2012 (EST)
- You're absolutely right that casting has something to do with it. The problem is, as the compiler tells you, that "IntProperty" doesn't exist on the type "Quest".
- The important thing to remember here is that, when you wrote the script containing "IntProperty", you wrote it such that you extended "Quest". What' you've essentially done is create a new object type that is an extension of "Quest" and, as such, I expect you should be able to access your property like this (with "MyNewQuestScript" as a placeholder for the name of the script containing "IntProperty"):
(QST as MyNewQuestScript).IntProperty += 1
- -- Cipscis 05:35, 11 February 2012 (EST)
Thanks for the reply, it worked! I think I'm getting more of a handle on the idea, but I'm still having some conceptual problems. So, if I understand it right, when I made a new Quest script on a quest that extends "quest," I can only use the stuff in the "quest" object. Then, if I make a AME script with a property whose value is MyQuest, I really only have a property that uses stuff from the "quest" objects. So, in order to use objects specifically from MyQuest, I have to have to cast the AME property as MyQuestScript? Why MyQuestScript and not just MyQuest? Thanks, --Doulos 14:17, 11 February 2012 (EST)
Ah, I think I figured it out. I'll keep all of this up here in case someone else might benefit from it. I'm so used to Oblivion and how quests own variables. So I was assuming that I should be able to something like MyQuest.IntProp. But that's not the case. I have to attach a quest property (value MyQuest) to my AME script because that's the quest wherein the variable of interest lies. However, the property "IntProp" doesn't belong to MyQuest, it belongs more specifically to the script to which it it attached. So, if I want to use the properties of MyQuest, I have to cast the QST property as MyQuestScript, since the script contains the property I want. --Doulos 14:49, 11 February 2012 (EST)
I am trying to do something similar to above working with a script on an ActiveMagicEffect trying to access a property or rather properties from a QuestScript but I'm having difficulty with compiler errors Ive tried as suggested above to point to my property in the quest script in this way.
If (HasHastenDead as PsiNecromancyQuestScript).Intproperty == 1
But I just get an Error "cannot compare a psinecromancyquestscript to a int (cast missing or types unrelated)" And Error "cannot cast a int to a psinecromancyquestscript, types are incompatible"
It may have something to do with me declaring the property incorrectly I was under the impression that you declared or referenced a property from another script as
PsiNecromancyQuestScript Property HasHastenDead auto
But I just get another compiler error "cannot compare a psinecromancyquestscript to a int (cast missing or types unrelated)"
And it doesn't work to declare the property as normal either.
int Property HasHastenDead auto
Any help on this would be greatly appreciated.
--PsiSoldier 14:09, 21 April 2012 (EDT)
Correct way:
PsiNecromancyQuestScript Property PsiNecromancyQuest Auto
;;;
if PsiNecromancyQuest.HasHastenDead == 1
Alternatively:
Quest Property PsiNecromancyQuest Auto
;;;
if (PsiNecromancyQuest as PsiNecromancyQuestScript).HasHastenDead == 1
--Fg109 14:34, 21 April 2012 (EDT)
Excellent. That worked great! Thanks Fg109 --PsiSoldier 16:11, 21 April 2012 (EDT)
"Warnings" UnclearEdit
At the moment, the "Warnings" at the bottom of the page reads like this:
"Be careful with variables and auto properties on scripts that are extended by other scripts - especially where some script somewhere else may have a property pointing to the base script, or trying to cast to the base script. This is because it would be possible to have two copies of a script attached to the same object, thereby creating two copies of the variable/auto property - and the other scripts that refer to the base script may randomly pick which one to talk to.
This is doubly-true of scripts with native functions, as the game can attach these to in-game objects at any time if it needs to, thereby creating another copy of the variable or auto property."
To me, at least, this seems rather unclear. Could anyone help me decipher it?
-- Cipscis 17:27, 14 February 2012 (EST)
- I've attempted to clarify this warning based on some useful feedback from SmkViper. Hopefully it's clearer now.
Getting Properties From Any Other ScriptEdit
This section has caused a bit of confusion for some. They followed the magicEffect -> QuestScr example of declaring their custom script type, but things didn't work. Unlike the quest, some objects will have multiple instances. So their reader script had a property referring to the script on some base object. The same principles apply, but it would first involve grabbing a world reference and casting to the Type.
I'm not sure if there is already a page explaining that. -- Tunaisafish 08:17, 17 March 2012 (EDT)
Yes I am having difficulty passing variables between my scripts and getting values that actually work that I can do something with. I am trying to pass values from my Quest Script to my Active Magic Effects script and while they both compile correctly I do not get any results that I expect. The Quest is configured correctly and is advancing as it should and I even get my debug message that shows the script SHOULD be working but I'm not able to pass my property values from one script to the other. Currently my scripts look like this.
This is my Quest Script that should be assigning the variables and hopefully passing them along. Ive tried playing around with Globalvariable instead of Int but that didn't seem to be of any help unless I just did it incorrectly.
Scriptname PsiNecromancyQuestScript extends Quest
Int Property PsiUpkeepcharge auto
Int Property PsiHasHastenDead auto
Int Property PsiHastenDeadHealthBonus auto
Quest Property PsiNecromancyQuest Auto
Float CheckonceA
Event OnInit()
PsiUpkeepcharge = 30
while PsiNecromancyQuest.Getstage() < 10000
If PsiNecromancyQuest.GetStage() == 150
If CheckonceA == 0
PsiHasHastenDead = 1
PsiHastenDeadHealthBonus = 40
Debug.Messagebox("Player Has Gained the Hasten Dead Bonus")
CheckonceA = 1.0
Endif
Endif
EndWhile
EndEvent
Trying to pass my Properties to my Active Magic Effects Script here..
Scriptname PsiSummonScript extends activemagiceffect
PsiNecromancyQuestScript Property PsiNecromancyQuest Auto
float Checkonce1
Event OnEffectStart(Actor Target, Actor Caster)
if Checkonce1 == 0
Game.GetPlayer().ModActorValue("Magicka", - PsiNecromancyQuest.PsiUpkeepcharge)
Checkonce1 = 1.0
Debug.Messagebox("Player Charged Magicka Upkeep!")
if PsiNecromancyQuest.PsiHasHastenDead == 1
Target.ModAv("Health", PsiNecromancyQuest.PsiHastenDeadHealthBonus)
Debug.Messagebox("The Summon Has been buffed!")
Endif
Endif
EndEvent
Event OnEffectFinish(Actor Target, Actor Caster)
Game.GetPlayer().ModActorValue("Magicka", PsiNecromancyQuest.PsiUpkeepcharge)
Checkonce1 = 0
Debug.Messagebox("Player No longer Charged Magicka Upkeep!")
if PsiNecromancyQuest.PsiHasHastenDead == 1
Target.ModAv("Health", - PsiNecromancyQuest.PsiHastenDeadHealthBonus)
Endif
EndEvent
So I'm guessing either what I want to do is not possible or obviously there is something here I'm just not getting right. Would greatly appreciate some help!
--PsiSoldier 21:02, 21 April 2012 (EDT)
- I think the problem here is that you are trying to do too much in the OnInit() block. See the very first Note on that page about how it blocks other scripts until it finishes.
- If you've not already done so can you raise this problem on the forum? It will be easier to solve there than here.
- -- Tunaisafish 02:22, 22 April 2012 (EDT)
Indeed that was the problem I just needed to register for updates in OnInit and then run most of the code in an OnUpdate() event.
If anyone feels this might not be helpful delete this. Otherwise it may help someone because most things in the scripts are working after changing to register (except buffing my summoned creatures health which is not working) so I'll leave it.
--PsiSoldier 06:42, 22 April 2012 (EDT)
AutoReadOnlyEdit
It is worth noting that Properties defined as AutoReadOnly are not only constant but also permanent.
If you define property iCarrot = 3 in your script, game save files will consider 3 to be the absolute immutable value for iCarrot, even if a later version of your script changes the definition to iCarrot = 5.
This can lead to unexpected behavior. -- Jaxonz 12:16, 27 September 2012
- Really? Unfortunately I'm unable to test this right now, but that would run counter to what I know about how AutoReadOnly properties are handled by the compiler. Consider your iCarrot property, for example:
Int Property iCarrot = 3 AutoReadOnly
- The compiler handles that property as though this was its content:
Int Property iCarrot
Int Function get()
Return 3
EndFunction
EndProperty
- What I mean by this is that, if you were to view the assembly generated by the compiler, both of those properties would be indistinguishable from one another. This also means that, if I were to change the property to use a different "default value" and recompile the script, that property's "get" function would be changed to have a different return value.
- As far as I'm aware, such a change would be reflected in an existing saved game, excluding any function calls active within that save (see Save File Notes - Changing Code).
- P.S. Please sign your posts on talk pages with ~~~~. This just appends your username and the date so it can be easier to follow a conversation :)
Initial Value for other propertiesEdit
I can successfully set initial value for int and float properties, but how can I set initial value, for istance, for a book? --MannyGT (talk) 2013-04-15T14:07:00 (EDT)
- Outside of functional code, only literals can be used to initialise variables and properties. As the only object literal is None, that's the only value that can be used to give a default value to a variable or property with a type like Book. This is the same as not setting a default value, however.
- If you associate a property with a particular object via the Creation Kit, then the property will act as though you've set that as its default value. You can't do that just in Papyrus though, that information needs to be stored in the data file.
Adding Properties on Script in Current GameEdit
I think this should probably be included in the Notes or Warnings Section.
Which I learned the hard way; Properties appear to be connected to the objectReference as if its separate from the script. These properties get baked into the save along with the objectReference itself.
Apparently deleting properties is a bad idea, these will continue to persist in a save game and can cause problems, but adding properties, through amending a script on a Base Item, to already loaded or baked in objects has the effect of not filling the properties. this can cause alot of unnecessary stuff placed on the stack and your script will fail to work correctly. if you have alot of properties or those properties are used numerous times in your script, then every time that property shows up it will throw an error causing alot of congestion for the VM. calling other scripts off the base script is one work around. may seem obvious to some, but a bad idea that will only work on new games.
- From my understanding, all properties are baked into the save the moment the game is loaded. ObjectReferences tend to be a bigger issue because the properties pointing at them, will make them persistent. So in practice, one should use ObjectReference properties when absolutely necessary, and never no more than what you need. There's a clearer info on this but the page is inaccessible at the moment. --Lisselli (talk)
- I could be wrong here, but its not just ObjectReferences. Now, this could be because I wasn't adding Properties to an ObjectReference, but in fact adding Properties to the Base Item. Because there was hundreds of child ObjectReferences, and filling each one was too monumental. It appears to have cascaded down to the objectReferences in terms of filling these Properties though, however, if those ObjectReferences were already baked in to the game, adding Properties would always return a Null (None) value. Those Properties could be a Boolean array, MiscObject, Static, etc,etc. In terms of adding Properties to a child Object Reference in some cell that has a script attached to it, that I do not know if the same thing occurs.
Personally, I think it should be an absolute avoided practice unless you reset every Cell in the game where these objectReferences exist.
- So for example, if you add a script to a sword(a base item in the CK) any properties added will be applied to all the same swords in game(the objectreferences of the base item)? Yes this "inheritance" is true and is a well known horrible practice, unless there is a specific reason you need all the objects to have this script. Lisselli (talk) 2017-02-13T02:13:30 (EST)