pitvenin Posted June 19, 2011 Share Posted June 19, 2011 Hello, Does anybody know how can I get the ref of the closest actor/object to the player? Link to comment Share on other sites More sharing options...
SmileyCat Posted June 19, 2011 Share Posted June 19, 2011 You would need NVSE in order to do this, use something similar to this; ScriptName GetClosestActor ref ClosestActor ref CreatureCount ref CreatureCurrent Begin GameMode Set CreatureCount To GetNumRefs 201 1 Set CreatureCurrent To GetFirstRef 201 1 Label 6 If CreatureCount > 0 Set CreatureCurrent To GetNextRef If CreatureCurrent.GetDistance Player <= 500 Set ClosestActor To CreatureCurrent EndIf Set CreatureCount To CreatureCount - 1 Set CreatureCurrent To Pencil01 GoTo 6 EndIf End ; The reference ClosestActor will always remain the actor closest to the player until the actor / player moves, it then checks for the next one. I did not test the code but I hope it helps. Link to comment Share on other sites More sharing options...
NorthWolf Posted June 20, 2011 Share Posted June 20, 2011 Smiley, I'm not particularly trying to use your code, though I like reading the examples on here to learn the language. I'm confused. Shouldn't the lines: Set CreatureCount To GetNumRefs 201 1 Set CreatureCurrent To GetFirstRef 201 1 Refer to inventory objects according to the FOSE documentation? By it the number for the form type should be 200, shouldn't it? Also, I don't understand this: If CreatureCurrent.GetDistance Player <= 500 Set ClosestActor To CreatureCurrent EndIf Why the <= 500? Shouldn't 500 be a variable that updates to the next closest creature's distance every time the loop iterates? Cheers, and thanks in advance if you can explain for me. Link to comment Share on other sites More sharing options...
TheTalkieToaster Posted June 20, 2011 Share Posted June 20, 2011 Yep, right on both counts. Plus the Pencil01 thing might not be necessary; in some versions of OBSE/FOSE the GetNextRef code wouldn't properly overwrite unless the ref it was writing into contained something that was of a different type to what it was passing (so when scrolling through NPC refs you'd reset the variable with an object base like Apple or Pencil) but I don't think that's a problem any more. An example in a slightly different format (using things like the fact GetNextRef returns 0 when it finishes looping over all the refs) would be:ref npc ref npcClosest float npcDistance begin gameMode set npc to GetFirstRef 200 1 set npcDistance to 9999 set npcClosest to 0 label 10 if(npc) if(npc.GetDistance player < npcDistance) set npcClosest to npc set npcDistance to npc.GetDistance player endif set npc to getNextRef goto 10 endif if(npcClosest) ;There exists an NPC within 9999 distance endif end Link to comment Share on other sites More sharing options...
rickerhk Posted June 20, 2011 Share Posted June 20, 2011 I've done it this way.Edit - Ninja'd ScriptName MyClosestActorScript ref rTarget ref rClosestRef short iEnableSearch float fClosestDistance BEGIN GameMode if (iEnableSearch == 1) set rTarget to GetFirstRef 200 1 0; Actor; 1 cell deep set rClosestRef to rTarget if rClosestRef set fClosestDistance to rClosestRef.GetDistance player endif Label 10 if rTarget if rTarget.GetDistance Player < fClosestDistance set rClosestRef to rTarget set fClosestDistance to rTarget.GetDistance Player endif set rTarget to Pencil01 ; Fix "Apple" bug by setting rCurrentRef to arbitrary reference before using GetNextRef set rTarget to GetNextRef Goto 10 endif if rClosestRef ;Do stuff with the closest ref endif set iEnableSearch to 0 endif END Link to comment Share on other sites More sharing options...
pitvenin Posted June 20, 2011 Author Share Posted June 20, 2011 Wow I didn't expect to get this much responses. Thank you all, I will try them as soon as possible. I think rickerhk code works the best... Link to comment Share on other sites More sharing options...
pitvenin Posted June 20, 2011 Author Share Posted June 20, 2011 (edited) Ok I've done some thinking and here's what I think it's the best code ref Bob ref Alice ref dummyRef ref ref1 float distance1 float distance2 float maxiumdistance set dummyRef to GetFirstRef 200 0 0 ; making sure we have stored the first reference set Bob to GetFirstRef 200 0 0 set Alice GetNextRef set maxiumdistance to 1200 Label 1 if Bob != dummyRef ; Condition that prevents the code to be executed on first run set Bob to Alice set Alice to Pencil01 set Alice to GetNextRef endif Label 2 set distance1 to Bob.getDistance player set distance2 to Alice.getDistance player if distance1 <= maxiumdistance && Bob.getDead == 0 ; we check to see if Bob (the main target) meets the distance req and he is not dead Label 3 if distance2 > maxiumdistance || Alice.getDead != 0 ; we check to see if Alice meets the distance req and she is also not dead set Alice to Pencil01 set Alice to GetNextRef set distance2 to Alice.getDistance player goto 3 elseif distance2 < distance1 ; if Alice is closer than Bob set Bob to Alice ; than Bob becomes Alice set Alice to Pencil01 set Alice to GetNextRef ; and Alice becomes the next actor goto 2 ; now we check the req of the new Alice elseif distance2 > distance1 ; if Bob is closer than Alice set ref1 to Pencil01 set ref1 to GetNextRef ; we check for a 3rd actor to see if he is closer than Bob label 11 if ref1 && (ref1.getDistance player > maxiumdistance || ref1.getDead != 0) ; settings req for the 3rd actor set ref1 to Pencil01 set ref1 to GetNextRef goto 11 elseif ref1.getDistance player < distance1 ; if the 3rd actor is closer than Bob, Bob becomes the 3rd actor set Bob to ref goto 2 ; the comparison between Bob and Alice is run again endif endif else goto 1 ; if the minimum distance is not met, go to this label endif Now I think this code will work if you have in the scene : player, Bob, Alice and Brian. But if you have player, Bob, Alice, Brian and Steve; and if Bob is closer than Alice and Brain but not closer than Steve, Steve won't get checked. I see it like this because I understand that GetFirstRef gets the first ref of the specific type in the cell, the first actor in the list in this case. getNextRef gets the next actor that is in the list. So if we compare 1 to 2 and 1 < 2, 3 will never get compared, unless we make that check ( 1 ? 3). And even then you will get 1 < 2 < 3, but what about 4? or 5?...etc. It all comes done to how accurate you want the script to be... I hope I got the way those functions work, because this seems logic to me, if they work the way I think... Edited June 20, 2011 by pitvenin Link to comment Share on other sites More sharing options...
SmileyCat Posted June 20, 2011 Share Posted June 20, 2011 The code I supplied was meant to be expanded further, and yes, the 201 was supposed to be 200. Link to comment Share on other sites More sharing options...
pitvenin Posted June 20, 2011 Author Share Posted June 20, 2011 (edited) After many crashes and testing I finaly got it : float timer ref Bob ref Alice ref marker1 float distance short maxdistance begin ScriptEffectUpdate set maxdistance to 2460 ;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if timer < 1 set timer to (timer + ScriptEffectElapsedSeconds) else ;============================================================================================= if Bob == 0 set Bob to GetFirstRef 200 1 0 endif if Bob.getDead != 0 || player.getDistance Bob > maxdistance set Bob to Pencil01 set Bob to GetNextRef set Alice to Pencil01 set Alice to GetNextRef else if Alice && Alice != Bob if player.GetDistance Alice < player.GetDistance Bob set Bob to Pencil01 set Bob to Alice set Alice to Pencil01 set Alice to GetNextRef else set Alice to Pencil01 set Alice to GetNextRef endif else set marker1 to Bob set timer to 0 ; do something with marker1 endif endif ;============================================================================================= endif ;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- end One problem : If Bob dies or get's out of the range, game crashes.... Edited June 20, 2011 by pitvenin Link to comment Share on other sites More sharing options...
TheTalkieToaster Posted June 20, 2011 Share Posted June 20, 2011 I don't really understand why you completely mangled it like that. Pretty much any of the three functionally near-identical examples posted, with a few corrections, would work fine. Instead you've managed to add that bug by putting in Bob.Function calls without verifying Bob, which of course causes CTDs if Bob is out of the loaded area and not a persistent reference. Plus you've replaced calling GetDistance once per NPC and storing the result with calling it for every comparison, and your GetNextRef loop won't work properly as it doesn't all occur within one frame as you don't use loops and so NPCs can wander into or out of the cell whilst it's running. Link to comment Share on other sites More sharing options...
Recommended Posts