Jump to content

Placing NPCs at random around player


WIGWAM

Recommended Posts

I'm trying to spawn an NPC at a random offset from the player each time the NPC spawn.

 

The relevant parts of the script are:

ScriptName zzDCScript Extends Quest

int zzSpawntimer = 1
ActorBase Property Critter1Base auto
Actor Property PlayerRef auto
ObjectReference property TargetMarker auto ;An XMarker placed in the commonwealth.
Float Random

Function Random()
	Random = Utility.RandomFloat(250,500)
EndFunction	

Event OnInit()
	StartTimer(15, zzSpawntimer)
	TargetMarker.SetPosition((PlayerRef.GetPositionX() + Random), (PlayerRef.GetPositionY() + Random),(PlayerRef.GetPositionZ())) ; move the xmarker to player with random x and y offsets.
	ObjectReference newCritter1 = TargetMarker.PlaceActorAtMe(Critter1Base) ;Spawn NPC
EndEvent

;some other code after this...

The problem I have with this is:

1. The NPCs only spawn when the player is in the commonwealth (excluding diamond city and goodneighbour) i.e. where the original marker is placed.

2. The NPCs spawn on top of the player.

 

Are there any changes I can make to this so the NPCs will spawn no matter where the player is and have the NPC spawn with an offset?

 

Thanks,

 

WIGWAM.

Link to comment
Share on other sites

I'm trying to spawn an NPC at a random offset from the player each time the NPC spawn.

 

The relevant parts of the script are:

ScriptName zzDCScript Extends Quest

int zzSpawntimer = 1
ActorBase Property Critter1Base auto
Actor Property PlayerRef auto
ObjectReference property TargetMarker auto ;An XMarker placed in the commonwealth.
Float Random

Function Random()
	Random = Utility.RandomFloat(250,500)
EndFunction	

Event OnInit()
	StartTimer(15, zzSpawntimer)
	TargetMarker.SetPosition((PlayerRef.GetPositionX() + Random), (PlayerRef.GetPositionY() + Random),(PlayerRef.GetPositionZ())) ; move the xmarker to player with random x and y offsets.
	ObjectReference newCritter1 = TargetMarker.PlaceActorAtMe(Critter1Base) ;Spawn NPC
EndEvent

;some other code after this...

The problem I have with this is:

1. The NPCs only spawn when the player is in the commonwealth (excluding diamond city and goodneighbour) i.e. where the original marker is placed.

2. The NPCs spawn on top of the player.

 

Are there any changes I can make to this so the NPCs will spawn no matter where the player is and have the NPC spawn with an offset?

 

Thanks,

 

WIGWAM.

 

1.) For one thing, you are positioning the spawning marker with SetPosition(), which changes the coordinates of an ObjectReference. Each worldspace (and interior) has its own coordinate plane. You might want to use MoveTo to relocate the marker to the Player (this takes into account also the cell & worldspace of the target reference). If there's just a coordinate change, you are likely plopping down your actors close to the middle of the Commonwealth map when you are in, for instance, interiors.

 

2.) Random seems to refer to a variable you declared (Float Random), but did not intuitively define. You do assign a value in the body of a function also called Random(), but is this function called per random deviate you want (x and y) to generate? Also, if you wanted to immediately get the return value of the function and add it to the result of a GetPosition call, you would want to declare your function as such (float Function Random() and explicitly return the value of Utility.RandomFloat(250,500)).

Link to comment
Share on other sites

Thanks, I think I have sorted, I haven't tested it out but I'm not getting any compilation errors.

 

Changed the relevant line to this:

;
;
float Function Random()
	Return Utility.RandomFloat(250,500)
EndFunction	
;
;
;
TargetMarker.MoveTo(PlayerRef,(PlayerRef.GetPositionX() + Random()), (PlayerRef.GetPositionY() + Random()), (PlayerRef.GetPositionZ()))
;
;
;

Link to comment
Share on other sites

X and Y run positive and negative so to totally randomise all quadrants you may want to add a random bit flip:

If (Utility.RandomInt(0,1) == 0)
   Return Utility.RandomFloat(250.0,500.0)
Else
  Return Utility.RandomFloat(-250.0,-500.0)
Endif

If you would like your actors to face the player after spawning for instant engagement:

Float fHeading = ThisActorREF.GetHeadingAngle(pPlayerREF)			
ThisActorREF.SetAngle( ThisActorREF.GetAngleX(), ThisActorREF.GetAngleY(), (ThisActorREF.GetAngleZ() + fHeading) )
ThisActorREF.Enable(abFadein = True)

If you don't want the player to see the actor slew, as soon as you PlaceActorAtMe then .Disable(abfadout = False) move 'em around and then enable.

Link to comment
Share on other sites

Thanks both of you.

 

I have tested this but now the NPCs have started spawning off the top left corner of the map, I had to put a quest marker on it the find out where they are. The location of the marker doesn't seem to change when I fast travel or change cell. Could it be a problem with the reference I'm using - should I use the ObjectReference for the player or the actor reference?

Link to comment
Share on other sites

Yes totally must be the ObjectReference, to help with casting the naming conventions are usually:

 

ObjectReference Property pPlayerREF auto const mandatory

Actor Property pPlayerACTOR auto const mandatory

 

Can define one or either to save casting as:

 

(pPlayerREF as Actor).ActorScriptFunction()

(pPlayerActor as ObjectReference).ORScriptFunction()

 

If I am calling both a lot in a script I set 'em both as properties for a tiny performance bonus on calls. Really doesn't matter, just makes *me* happy :)

Link to comment
Share on other sites

 

TargetMarker.MoveTo(PlayerRef,(PlayerRef.GetPositionX() + Random()), (PlayerRef.GetPositionY() + Random()), (PlayerRef.GetPositionZ()))

Thanks both of you.

 

I have tested this but now the NPCs have started spawning off the top left corner of the map, I had to put a quest marker on it the find out where they are. The location of the marker doesn't seem to change when I fast travel or change cell. Could it be a problem with the reference I'm using - should I use the ObjectReference for the player or the actor reference?

 

If you are using just MoveTo (as opposed to doing MoveTo to do a relocation to the player's cell and position and then a SetPosition based on the new absolute coordinates you compute), I think those offsets should be then relative-to-the-target (not incorporating player position) rather than absolute. There's an example of these semantics on the Creation Kit wiki for Skyrim (but amusingly not the Fallout 4 page?):

Actor PlayerRef = Game.GetPlayer()
Portal.MoveTo(PlayerRef, 120.0 * Math.Sin(PlayerRef.GetAngleZ()), 120.0 * Math.Cos(PlayerRef.GetAngleZ()), PlayerRef.GetHeight() - 35.0)
Link to comment
Share on other sites

Function MoveTo(ObjectReference akTarget, float afXOffset = 0.0, float afYOffset = 0.0, float afZOffset = 0.0, bool abMatchRotation = true) native

 

Based on this you are getting the x and y coordinates and taking those values and adding random() to those values and using them as the offset.

 

Hence if the player is at x=100, y=100. Your using x=100 + random as the offset. Obviously in that scenario it might be close but if it was x=600 y=1000.... some times its easier to figure out what is going on if you define the variables outside of the function call. I realize it's not as tidy but sometimes unexpected stuff can happen bc its overly complicated.

 

I think that's right.

 

I've been hesitant to reply with any advice bc I been getting alot of stuff wrong lately. But I'm pretty sure that what I'm saying is correct

 

Basically I'm saying the offset is relative to the player position as if the player was at 0,0 relative to himself but you're taking the x and y relative to his position in the world or cell (not sure ) then adding random and using those combined values as the offset.

 

I could be completely off base in assuming this isn't what you're trying to do. I'm assuming that you want the creature to spawn in the general vicinity of the player. But based on what is happening now the creature is going to spawn in a random spot on the map that may or may not be close to the player. Also I'd advise you to use debug.notification to spit out values of these variables and even let you know where in your script you are. Bc again there could be unexpected behavior that youd never know how or why it's happening without the notifications. Save you alot of pain and frustration

Edited by markyrocks
Link to comment
Share on other sites

  • Recently Browsing   0 members

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