How do you define a Global Reference?

Post » Mon Jun 18, 2012 7:09 pm

This is driving me nutz (SIC) - I want to have a persistant object reference that will work with two spells.

The first spell fires what is essentially a Magelight spell. The object reference is the actual light being carried by the projectile, and so should continue existing wherever the light goes, even when the projectile "drops" it and disappears.

The second spell is supposed to move me to the location of that magelight. but it doesn't seem to be working at all.

Now I seem to have changed something that broke even compiling the things, and I can't figure out what I changed to change it back! Been staring at this dang code for two full days now.

The script on the light: (Note how the Set and Get functions are clearly defined here for the TeleportNodeObject type - but something's wrong, because the other scripts can't call them.)

Scriptname TeleportNodeObject extends ObjectReference  {A node for the teleport spell}; Need a node object reference for this spellObjectReference Store_Node  ; Reference this as TeleportNode with function calls on a TeleportNodeObject in other scripts.ObjectReference Property TeleportNode    ObjectReference Function Get()              Debug.MessageBox("Sending Teleport Node:" + Store_Node)        return Store_Node    endfunction    Function Set(ObjectReference ThisObject)        Store_Node = ThisObject                  Debug.MessageBox("Setting Teleport Node: " + Store_Node)    endfunctionendproperty
The script on the spell effect that fires the projectile carrying the light:
Scriptname FindTeleportProjectile extends ActiveMagicEffect  {Locates the projectile and stores a reference to it.}import gameimport utilityTeleportNodeObject ThisNodeEvent OnSpellCast(form IncomingSpell)    Spell ThisSpell = IncomingSpell as spell    if ThisSpell && ThisSpell == TeleportLaunch        (ThisNode.TeleportNode.Get()).Delete() ; Make sure the old node goes poof.        Utility.Wait(0.25) ; Make sure the projectile has been fired!        ObjectReference ThisIsIt = FindClosestReferenceOfTypeFromRef(MagicLightTeleportSpell,Game.Getplayer(),1000)        ThisNode.TeleportNode.Set(ThisIsIt) ; It sees the type "TeleportNodeObject" just fine, but can't see the Set function? Really?    endifEndEventLight Property MagicLightTeleportSpell  Auto   ; Editor ID of the Light.Spell Property TeleportLaunch Auto ; Editor ID of Teleport spell

The script on the "Move me there" spell: This one, at least, is actually calling the functions. Or it was, until the above script started not propogating it's functions.
Scriptname PlayerTeleportScript extends ActiveMagicEffect  {A script to teleport the player to a destination node.}TeleportNodeObject TheNodeObjectReference playerObjectReference TeleportHereEvent OnEffectStart(Actor Target, Actor Caster) ; No real target, and the caster is the player, since it's a player-only spell  ;Debug.MessageBox("Magic effect was started on " + Target)    player = (game.getPlayer() as ObjectReference)    TeleportHere = TheNode.Get()    if TheNode        Utility.Wait(0.5)        player.MoveTo(TeleportHere)            Utility.Wait(0.5)        TheNode.Delete() ; Make sure node goes poof.    endifEndEvent 

For some reason, this programming language makes it very difficult to make a global reference variable, so I can't simply store the value and get it directly, oh no...Gotta play musical references and create dummy objects just so we can (supposedly) call the Set and Get functions...and even then, it doesn't work...
User avatar
Tarka
 
Posts: 3430
Joined: Sun Jun 10, 2007 9:22 pm

Post » Mon Jun 18, 2012 5:37 pm

Where do you give ThisNode a value in FindTeleportProjectile?

EDIT: Also, TheNode in PlayerTeleportScript doesn't seem to get initialized, only read.

Also also, do you get any errors when compiling and/or during runtime (the latter in the logfile)? Those would be helpful.
User avatar
Cartoon
 
Posts: 3350
Joined: Mon Jun 25, 2007 4:31 pm

Post » Mon Jun 18, 2012 5:54 pm

Where do you give ThisNode a value in FindTeleportProjectile?
Therein lies the problem that's driving me crazy...I didn't want to have ThisNode at all! I want there to be only ONE reference ANYWHERE to a TeleportNodeObject, to prevent conflicts. But there doesn't seem to be a way to create a single global reference variable and change it with global functions.

The compiler forces me to create a ThisNode variable so I can (try to) Call the Get and Set functions.

They made global variables work for Int, Float and other VALUE variables, but NOT for reference variables.
User avatar
Penny Flame
 
Posts: 3336
Joined: Sat Aug 12, 2006 1:53 am

Post » Mon Jun 18, 2012 12:15 pm

Ah, well, a problem I see now is that you define TeleportNode (in the first script) as a property, but you never call it as one in any of the other scripts. Which kind of kills the point.

Hm, maybe it could work if you had a persistant quest where you stored the teleport node, instead of the ObjectReference that script #1 extends. I think. Not sure how you would go about it using properties and such (still hasn't wrapped my head around custom properties... I think) but I think it should work. Eventually O_o

I wish I could help you more but I'm really tired and my brain is spaghetti. I'll try some more if you're still having trouble in a couple of hours when I've zzzzzlept.
User avatar
Jeff Turner
 
Posts: 3458
Joined: Tue Sep 04, 2007 5:35 pm

Post » Mon Jun 18, 2012 7:54 am

How do you define a globale variable reference.

Create the global in the Object Window under Miscellaneous -> Global

GlobalVariable Property pYourGlobal AutopYourGlobal.GetValue()pYourGlobal.SetValue( value )

Does that work?
User avatar
Verity Hurding
 
Posts: 3455
Joined: Sat Jul 22, 2006 1:29 pm

Post » Mon Jun 18, 2012 7:59 am

Create the global in the Object Window under Miscellaneous -> Global

GlobalVariable Property pYourGlobal AutopYourGlobal.GetValue()pYourGlobal.SetValue( value )

Does that work?

No, because you're only allowed Integers, Longs, and Floats, not References, which is what I need.

By creating a new object in each of the 3 scripts, they don't pass information to each other. They all need to be on the same page, looking at the same object. Without access to that one, singular object, the values set by one script will not be reflected in another, and as the object moves, it's location will not be updated if the variables are simple Int values. By referencing the object, you have a constant and accurate fix on it's location.
User avatar
Emzy Baby!
 
Posts: 3416
Joined: Wed Oct 18, 2006 5:02 pm

Post » Mon Jun 18, 2012 6:39 pm

http://www.creationkit.com/Quest_Alias_Tab#Reference_Aliases
User avatar
W E I R D
 
Posts: 3496
Joined: Tue Mar 20, 2007 10:08 am

Post » Mon Jun 18, 2012 11:05 am

http://www.creationkit.com/Quest_Alias_Tab#Reference_Aliases

Hmn...it's part of the quest routines...guess I could try creating a dummy quest so I can get the thing to work, but would the player have to actually GET the quest to use the variable? Would seem kind of silly to have a quest hanging around in the journal that just reads "You know how to teleport! Have fun!"
User avatar
trisha punch
 
Posts: 3410
Joined: Thu Jul 13, 2006 5:38 am

Post » Mon Jun 18, 2012 11:19 am

If I get it correctly, teleportnodeobject is the script attached to the light and the light is the reference where you teleport, isn't it?
If so, the TeleportNodeObject didn't need it's own objectreference to be passed by findteleportprojectile. Use this line in the get function instead: Debug.MessageBox("Setting Teleport Node: " + (self as objectreference))

About the inability to compile, sometimes when you use calls between functions, you may compile one script calling a function you didn't define yet in the called script. This is nasty, as the compiler will go a little crazy about all the implied scripts (even a script that was compiling successfully won't do it now despite you not having changed anything). This could be your case.

What you need to do to stop this nonsense, is disable with ';' all calling lines between those scripts and rename temporarily all the calling arguments in any place they are wrote in those scripts (just add a letter), and save the changes. Then define the all the called functions, each in it's own script. Now compile the scripts. delete the ';' you place on the calling lines rename the argument names again (unless you like more the new name :P ) and compile again. Keep in mind that when your rename anything, the first and the second time, you need to rename each place where that name appear.

Also, when your compilation failed, if you click on the error line, you'll get a debug text explaining what errors you get and in which lines. Sometimes the info is cryptic, but you'll find more and more useful as you get used to it.

Hope this helps :)
User avatar
Trey Johnson
 
Posts: 3295
Joined: Thu Oct 11, 2007 7:00 pm

Post » Mon Jun 18, 2012 10:06 pm

Also, when your compilation failed, if you click on the error line, you'll get a debug text explaining what errors you get and in which lines. Sometimes the info is cryptic, but you'll find more and more useful as you get used to it. Hope this helps :)

Been doing most of that for about 2 days...fiddled with it some more based on your advice, the scripts are now:

On the Light: (Commented out...no longer called, but kept it around just in case)
Scriptname TeleportNodeObject extends ObjectReference{A node for the teleport spell}; Need a node object reference for this spell;    ObjectReference Function GetTeleportNode() ; Don't need Set, since it is itself.;Debug.MessageBox("Setting Teleport Node: " + (self as objectreference));        return  ( Self as objectreference) ; Can't access Self as a global function (that makes sense at least);    endfunction 

On the Launch Projectile Effect: (Compile Error: (13,2): cannot call the member function SetTeleportNode alone or on a type, must call it on a variable)
Scriptname FindTeleportProjectile extends ActiveMagicEffect  {Locates the projectile and stores a reference to it.}import gameimport utilityimport PlayerTeleportScriptEvent OnSpellCast(form IncomingSpell)    Spell ThisSpell = IncomingSpell as spell    if ThisSpell && ThisSpell == TeleportLaunch        Utility.Wait(0.25) ; Make sure the projectile has been fired!        ObjectReference ThisIsIt = FindClosestReferenceOfTypeFromRef(MagicLightTeleportSpell,Game.Getplayer(),1000)        SetTeleportNode(ThisIsIt) ; Can't call this without instancing a PlayerTeleportScriptEffect object...but that will prevent access to the variable.    endifEndEventLight Property MagicLightTeleportSpell  Auto   ; Editor ID of the Light.Spell Property TeleportLaunch Auto ; Editor ID of Teleport spell that uses this effect.

On the Teleport Player Effect: (This compiles)
Scriptname PlayerTeleportScript extends ActiveMagicEffect  {A script to teleport the player to a destination node.}import gameimport utilityTeleportNodeObject TheNodeObjectReference playerObjectReference TeleportHerefunction SetTeleportNode(objectReference InNode)    TeleportHere = InNode ; Compiler can't see the TeleportHere variable if this function is global.; This function cannot be called from outside as a non-global function without instancing a PlayerTeleportScript Object,; which will not be this one, and will not, therefore, share the TeleportHere variable, since we can't declare variables as; "There can be only one" types...or at least the Papyrus reference doesn't tell us how to do so without using quest objects,; and this is a spell, not a quest.endfunctionEvent OnEffectStart(Actor Target, Actor Caster) ; No real target, and the caster is the player, since it's a player-only spell    player = (game.getPlayer() as ObjectReference)Debug.MessageBox("Teleport Node: " + TeleportHere)    if TeleportHere        Utility.Wait(0.5)        player.MoveTo(TeleportHere)            TeleportHere.Delete() ; Make sure node goes poof.        TeleportHere = FindClosestReferenceOfTypeFromRef(MagicLightTeleportSpell,Game.Getplayer(),10000000)        while TeleportHere ; Now to get rid of any extras that may or may not be floating around somewhere in the game.            TeleportHere.Delete()            TeleportHere = FindClosestReferenceOfTypeFromRef(MagicLightTeleportSpell,Game.Getplayer(),10000000)        endwhile    endifEndEventLight Property MagicLightTeleportSpell auto

I've put what I think is going wrong in comments in the above code.
User avatar
Karine laverre
 
Posts: 3439
Joined: Tue Mar 20, 2007 7:50 am


Return to V - Skyrim