Jump to content

Closet Actor


pitvenin

Recommended Posts

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

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

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

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

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 by pitvenin
Link to comment
Share on other sites

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 by pitvenin
Link to comment
Share on other sites

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...