Jump to content
  • 0

How do I make a group of monsters face the player in the GZDoom Builder Script Editor?


asd1994

Question

The effect I'm trying to accomplish is having a group of monsters turn towards the player and stare in awkward silence when the player opens the door. I've figured out all the other bits to make it work, except turning the monsters towards the player. At the moment I'm using "SetActorAngle(6,0.75);" to make a group of monsters tagged 6 face south where the player is, but some monsters to the side don't look like they're staring at you. Is there a way to have all the monsters look directly at the player without having to use several "SetActorAngle" scripts at once?

Share this post


Link to post

5 answers to this question

Recommended Posts

  • 2

You can make each monster in the group face the player by using a function that calculates their individual angles to the player one by one, and then makes each one of them face the player using the appropiate angle.

 

I made a custom ACS function that does this, feel free to use it:

Spoiler

// Make sure not to use these temporary TIDs in the map or other scripts!
#define TID_TEMP1 2337
#define TID_TEMP2 2338

Function void Thing_FaceTarget(int source_tid, int target_tid)
{
	// Store activator info
	int activator_tid = ActivatorTID();
	if (activator_tid == 0)
	{
		Thing_ChangeTID(0, TID_TEMP2); // Give activator a tid
		activator_tid = TID_TEMP2;
	}

	// Get target actor coordinates
	int tx = GetActorX(target_tid);
	int ty = GetActorY(target_tid);

	// Loop through actors with source_tid
	While (SetActivator(source_tid) == TRUE)
	{
		int x = GetActorX(0);
		int y = GetActorY(0);

		int vang, angle;
		vang = VectorAngle(x - tx, y - ty);
		angle = (vang + 0.5 ) % 1.0;

		SetActorAngle(0, angle); // Face target actor

		// Change the tid, so the source actor is not selected again in this loop.
		Thing_ChangeTID(0, TID_TEMP1);
	}

	Thing_ChangeTID(TID_TEMP1, source_tid); // Restore source_tid

	SetActivator(activator_tid); // Restore activator

	Thing_ChangeTID(TID_TEMP2, 0); // Clear temp tid from activator (if it was used)
}

 

 

Also attached an example map to this post.

thing_facetarget.zip

Share this post


Link to post
  • 0

I can provide the worst variant of implementing such idea, but it's better than nothing, I think:

1) Create in Decorate the clones of demons which you want to use in this situation. Make their Death/XDeath states to be "TNT1A0" (means "make invisible"), also don't forget to make Death/XDeath sounds as "None".

2) Place them in your scene like they should stay at first.

3) Place MapSpots in opposite direction. They will do some magic which I'll explain later.

4) Now make a script which kills "new" demons when Doomguy opens the door. And instantly spawn new demons by using MapSpots as Spawn Targets. Since Mapspots are looking at player, the instantly Demons will look at player. And this will feel like they turned around.

 

P.S.: You can do it more smoothly by implementing this gimmick few times. I mean, you can add few mapspots in directions between ↑ and ↓ so it will create a true effect of turning around.

Edited by Dexiaz

Share this post


Link to post
  • 0
9 hours ago, Dexiaz said:

I can provide the worst variant of implementing such idea, but it's better than nothing, I think:

1) Create in Decorate the clones of demons which you want to use in this situation. Make their Death/XDeath states to be "TNT1A0" (means "make invisible"), also don't forget to make Death/XDeath sounds as "None".

2) Place them in your scene like they should stay at first.

3) Place MapSpots in opposite direction. They will do some magic which I'll explain later.

4) Now make a script which kills "new" demons when Doomguy opens the door. And instantly spawn new demons by using MapSpots as Spawn Targets. Since Mapspots are looking at player, the instantly Demons will look at player. And this will feel like they turned around.

 

P.S.: You can do it more smoothly by implementing this gimmick few times. I mean, you can add few mapspots in directions between ↑ and ↓ so it will create a true effect of turning around.

Yeah that's kinda confusing. 

Share this post


Link to post
  • 0
18 hours ago, LightwaveAlice said:

Is there a way to have all the monsters look directly at the player without having to use several "SetActorAngle" scripts at once?

 

Worst above has outlined a scalable solution, but if you're trying to keep this simple, you do indeed need to use several SetActorAngles.

 

SetActorAngle literally just defines a specific angle for a given monster to face.  If you have a bunch of monsters all needing to face different angles, then you need different SetActorAngles.  

 

You can use more efficient solutions like Worst outlined above, but honestly if you're new to scripting and don't want to get bogged down in more advanced methods, it might be better to just write out a bunch of individual SetActorAngles.  While inefficient, at least you'll be confident with what you're doing. You'll have a chance to learn more efficient solutions as you get more comfortable with ACS.

Share this post


Link to post
  • 0
4 hours ago, Worst said:

You can make each monster in the group face the player by using a function that calculates their individual angles to the player one by one, and then makes each one of them face the player using the appropiate angle.

 

I made a custom ACS function that does this, feel free to use it:

  Hide contents


// Make sure not to use these temporary TIDs in the map or other scripts!
#define TID_TEMP1 2337
#define TID_TEMP2 2338

Function void Thing_FaceTarget(int source_tid, int target_tid)
{
	// Store activator info
	int activator_tid = ActivatorTID();
	if (activator_tid == 0)
	{
		Thing_ChangeTID(0, TID_TEMP2); // Give activator a tid
		activator_tid = TID_TEMP2;
	}

	// Get target actor coordinates
	int tx = GetActorX(target_tid);
	int ty = GetActorY(target_tid);

	// Loop through actors with source_tid
	While (SetActivator(source_tid) == TRUE)
	{
		int x = GetActorX(0);
		int y = GetActorY(0);

		int vang, angle;
		vang = VectorAngle(x - tx, y - ty);
		angle = (vang + 0.5 ) % 1.0;

		SetActorAngle(0, angle); // Face target actor

		// Change the tid, so the source actor is not selected again in this loop.
		Thing_ChangeTID(0, TID_TEMP1);
	}

	Thing_ChangeTID(TID_TEMP1, source_tid); // Restore source_tid

	SetActivator(activator_tid); // Restore activator

	Thing_ChangeTID(TID_TEMP2, 0); // Clear temp tid from activator (if it was used)
}

 

 

Also attached an example map to this post.

thing_facetarget.zip

Tysm, this works perfectly! :D

 

 

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...