GetDistance() returning crazy value

Post » Mon Nov 19, 2012 9:05 pm

Does GetDistance() work if the parameter is a dead actor? Its returning a massive number (336764858952000000000000000000000000.0000000000???). The relevant code is posted in the spoiler tag.

MyInt contains the form ID of my dead actor (aka victim) which I then use as the parameter for Game.GetForm() and cast it as an object reference.

I then check if the victim is in the same cell as the player before trying to get the distance between the player and victim.


Spoiler
   Int MyInt=ZAR_VictimID01.GetValue() as Int   ObjectReference Victim=Game.GetForm(MyInt) as ObjectReference  	  If Victim.GetParentCell()==PlayerRef.GetParentCell()		 Float MyDistance=PlayerRef.GetDistance(Victim)  		 ZAR_PlayerVictimDistance01.SetValue(MyDistance)		 Debug.MessageBox("PlayerVictimDistance is: " +MyDistance+ " .")	  EndIf

Any ideas?
User avatar
Sophie Payne
 
Posts: 3377
Joined: Thu Dec 07, 2006 6:49 am

Post » Mon Nov 19, 2012 8:34 pm

Why are you using http://www.creationkit.com/GetForm_-_Game? You should be using a property for that - it's simpler, easier to understand, probably faster depending on how you do it, and more semantically correct.

Cipscis
User avatar
Amysaurusrex
 
Posts: 3432
Joined: Wed Aug 09, 2006 2:45 pm

Post » Mon Nov 19, 2012 11:39 am

Why are you using http://www.creationkit.com/GetForm_-_Game? You should be using a property for that - it's simpler, easier to understand, probably faster depending on how you do it, and more semantically correct.

Cipscis

I think because he doesn't know who the victim is going to be before the script runs, and this particular script is not the one that decides who it's going to be, so he has to pass it between the scripts, and is using a global variable to store the FormID? I do something similar for my method of setting the owner of summoned creatures.

Zartar, try printing for yourself the x and y position of both the player and the ref, the name of the ref's base object, and the value of the global variable... then check with the console to make sure they all match the victim. I think I'm pretty certain that you are accidentally getting the wrong form. Like maybe this runs before the global variable is set to the correct value, or maybe you made a mistake in getting the correct FormID and setting the global to that. If you're getting the correct ref though as evidenced by the previous suggestions, but GetDistance() still isn't giving the correct value, it would be easy to calculate it yourself with the X/Y/Z positions of both refs.
User avatar
Jessica Lloyd
 
Posts: 3481
Joined: Fri Aug 25, 2006 2:11 pm

Post » Mon Nov 19, 2012 2:09 pm

Why are you using http://www.creationkit.com/GetForm_-_Game? You should be using a property for that - it's simpler, easier to understand, probably faster depending on how you do it, and more semantically correct.

Cipscis

What seventyfour said is the reason why I am not using properties.

Another script attached to a quest is getting the victim's ID using the OnStoryKillActor() event. I am pulling in data from multiple scripts and I intend on using that data to form an array of global variables. That array's data will be accessed and used in calculations for other variables and as conditions for dialogue.

Using properties for what I am trying to do would probably lead to numerous references to become persistent which is something I want to avoid. I was considering using formlists but I heard that accessing them is slow whereas array access is fast.

@seventyfour I really did not want to do the calculation manually but I will give it a try if I cannot figure out what is going wrong.

Thanks for the advice guys.

EDIT: FACEPLAM!!! I forgot to set one of my properties, that is what caused the problem!
User avatar
james kite
 
Posts: 3460
Joined: Sun Jul 22, 2007 8:52 am

Post » Mon Nov 19, 2012 8:36 pm

That sounds like a bad idea to me. By sidestepping persistence, you're enabling the game to delete the ObjectReference you're trying to work on, and possibly even reallocate its FormID (which is the only thing you seem to be storing), and with this method it seems you have no way of detecting whether or not that's happened.

A method that I think would work better would be to use a FormList. ObjectReferences can be stored in a FormList (which you would get via a Property like you're currently doing with a GlobalVariable) without being made persistent, and I think if you try to get an ObjectReference that no longer exists from a FormList, you'll be given None instead (even if the FormID has been recycled).

Spoiler
FormList Property VictimStorage AutoObjectReference Property Victim	Function set(ObjectReference akRef)		VictimStorage.Revert()		VictimStorage.AddForm(akRef)	EndFunction	ObjectReference Function get()		Return VictimStorage.GetAt(0)	EndFunctionEndProperty

Using an ObjectReference[1] might also work, as I'm unsure whether or not array elements force persistence in the same way as variables (and unfortunately I'm also unable to test it at the moment).

Cipscis
User avatar
electro_fantics
 
Posts: 3448
Joined: Fri Mar 30, 2007 11:50 pm

Post » Mon Nov 19, 2012 2:36 pm

Does GetDistance() work if the parameter is a dead actor? Its returning a massive number (336764858952000000000000000000000000.0000000000???). The relevant code is posted in the spoiler tag.

MyInt contains the form ID of my dead actor (aka victim) which I then use as the parameter for Game.GetForm() and cast it as an object reference.

I then check if the victim is in the same cell as the player before trying to get the distance between the player and victim.


Spoiler
   Int MyInt=ZAR_VictimID01.GetValue() as Int   ObjectReference Victim=Game.GetForm(MyInt) as ObjectReference  	  If Victim.GetParentCell()==PlayerRef.GetParentCell()		 Float MyDistance=PlayerRef.GetDistance(Victim)  		 ZAR_PlayerVictimDistance01.SetValue(MyDistance)		 Debug.MessageBox("PlayerVictimDistance is: " +MyDistance+ " .")	  EndIf

Any ideas?
If your victim is inside a walled city (for example) and your player is outside that same city, you will get a ludicrous value. Because the two cells are miles apart (even though they look like they are next to each other in the game)

Same thing with a dungeon or any other area that isn't a Wilderness-Type cell in Tamriel

It's messy, is GetDistance.

I used it, but I only wanted a very small distance to be true, so I could first check both player and NPC Were in the same CELL and then check the distance ... the 1:100000 chance that they were close together but not in the same cell didn't concern me
User avatar
Julie Serebrekoff
 
Posts: 3359
Joined: Sun Dec 24, 2006 4:41 am

Post » Mon Nov 19, 2012 10:06 am

That sounds like a bad idea to me. By sidestepping persistence, you're enabling the game to delete the ObjectReference you're trying to work on, and possibly even reallocate its FormID (which is the only thing you seem to be storing), and with this method it seems you have no way of detecting whether or not that's happened.

A method that I think would work better would be to use a FormList. ObjectReferences can be stored in a FormList (which you would get via a Property like you're currently doing with a GlobalVariable) without being made persistent, and I think if you try to get an ObjectReference that no longer exists from a FormList, you'll be given None instead (even if the FormID has been recycled).

Spoiler
FormList Property VictimStorage AutoObjectReference Property Victim	Function set(ObjectReference akRef)		VictimStorage.Revert()		VictimStorage.AddForm(akRef)	EndFunction	ObjectReference Function get()		Return VictimStorage.GetAt(0)	EndFunctionEndProperty

Using an ObjectReference[1] might also work, as I'm unsure whether or not array elements force persistence in the same way as variables (and unfortunately I'm also unable to test it at the moment).

Cipscis

What I am storing is the victim and (1) witness's form ID's, (2) the murder weapon, (3) the time the witness saw the player, (4) the form ID of each piece of clothing the player was wearing when seen by the witness, (5) the type of weapons the player had equipped at the time the witness saw the player and (6) the distance between the player and victim (if possible) at the time the witness saw the player. And there can be multiple witnesses too so that is a lot of data! I was considering using formlists but I thought my way might be faster... Can you store floats in formlists?

Anyway, its working now but will the game delete the form ID of a unique actor if that actor is dead? And reallocating form ID's? If so thats bad although at the moment the most important data is (2)-(6). (3), (5) and (6) are safe because they are just floats and ints but the rest.. (1) is for more advanced features I have yet to determine if possible...

@h4event I don't understand your point as I was checking to see if the player and victim were in the same cell before using get distance for the very reasons you stated! However I have changed that condition to If Victim.IsNearPlayer() because the player and victim may be close together but on opposite sides of the border between the two cells. Its working well at the moment but needs more testing.

But thanks again guys for the useful information. At least now if (or more likely when :tongue: ) something goes wrong I will have some idea what it is (and will use formlists).
User avatar
Julie Serebrekoff
 
Posts: 3359
Joined: Sun Dec 24, 2006 4:41 am

Post » Mon Nov 19, 2012 8:51 pm

Why don't you just point all the other scripts at the quest and have the quest store the information in some hidden properties? Then you don't have to worry about persistence or form IDs changing (your script would immediately break if someone changed the mod load order while it was running) or make any extra globals (which are for storing values, not forms).

Quest script:
Spoiler
Scriptname MyQuestScript extends Quest; Our properties that other scripts will access - flagged as hidden so they don't show up in the editor; Values stored in these properties will be persistent until clearedObjectReference Property Victim Auto HiddenObjectReference Property Killer Auto HiddenLocation Property DeathLocation Auto Hiddenfloat Property MyFloat Auto HiddenEvent OnStoryKillActor(ObjectReference akVictim, ObjectReference akKiller, Location akLocation, int aiCrimeStatus, \  int aiRelationshipRank)  Victim = akVictim  Killer = akKiller  DeathLocation = akLocation  MyFloat = 10.5EndEventFunction ClearValues()  Victim = None  Killer = NoneEndEvent

Some other script:
Spoiler
Scriptname MyTestScript extends ObjectReferenceMyQuestScript Property ControllingQuest Auto ; Fill this with your quest in the editorEvent OnActivate(ObjectReference akActionRef)  if MyQuestScript    ; Get the values from the quest and display them in the log    Debug.Trace("Killer is " + ControllingQuest.Killer)    Debug.Trace("Victim is " + ControllingQuest.Victim)    Debug.Trace("Death location is " + ControllingQuest.DeathLocation)    Debug.Trace("My float is " + ControllingQuest.MyFloat)    ; We're done with them, clean up!    ControllingQuest.ClearValues()  endIfendEvent
User avatar
Ice Fire
 
Posts: 3394
Joined: Fri Nov 16, 2007 3:27 am

Post » Mon Nov 19, 2012 10:49 pm

Well, if Cipscis and The Viper say its a bad idea... Its a bad idea! Thanks a lot man. Its not every day one gets modding advice from a Bethesda programmer! I will give that a try.
User avatar
Rebekah Rebekah Nicole
 
Posts: 3477
Joined: Fri Oct 13, 2006 8:47 pm

Post » Mon Nov 19, 2012 11:33 pm

I know we're already past this, but just for edification (since I saw these come up in Cipscis's example): my testing has shown that http://www.gamesas.com/topic/1365445-bug-formlist-functions-seem-to-break-under-certain-conditions/ and was a large reason I developed http://www.gamesas.com/topic/1365378-exampleresourcegeneral-purpose-array-functions/ instead. I suggest these functions be steered clear of.
User avatar
Niisha
 
Posts: 3393
Joined: Fri Sep 15, 2006 2:54 am

Post » Mon Nov 19, 2012 8:05 pm

Ooh, I hadn't actually thought of problems with changing load order - assuming one of the forms saved in this method "belongs to" a data file (as opposed to the save file), this would be by far a bigger issue than the one I mentioned.

Thanks for that link Chesko, I've added to my list of reference threads. Do you know if that behaviour has definitely not been fixed in later versions?

Cipscis
User avatar
Gemma Archer
 
Posts: 3492
Joined: Sun Jul 16, 2006 12:02 am

Post » Mon Nov 19, 2012 11:03 pm

Cipscis - I have not reconfirmed on 1.7.7.0.6. I haven't seen these functions pop up again in any of the new DLC scripts so I just assumed it hasn't been looked at.
User avatar
Josee Leach
 
Posts: 3371
Joined: Tue Dec 26, 2006 10:50 pm


Return to V - Skyrim