Help with A_Warp for multi-actor entities

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Help with A_Warp for multi-actor entities

Post by vAethor »

I'm going to be making enemies, the player (when viewed in third-person) and other objects composed of multiple actors in order to make animation easier and also to allow realistic damage mechanics when shooting different parts of the enemies or player. To do that I know I need to use A_Warp for all that, but I don't even know where to begin. I read up on it as much as I could on the Zdoom Wiki and was still unable to figure out what to do.

For practice I tried to use it in a project I started where I created a software-friendly brightmaps alternative for sprites, spawning the brightmap as a separate actor with A_SpawnItemEx and placing it right on top of the base sprite with no offsets. It looks pretty good:

Image

Realizing this actor, who will eventually be the player (I have him set as an ExplosiveBarrel replacement just to see him in third person and test stuff out) is going to be moving around a lot I tried to use A_Warp to keep the brightmap on the base actor, but then after shooting the actor to slide it a short distance away, I notice the brightmap stays in place:

Image

Here's my code:

Code: Select all

// Kyrdan knight actor (Simple actor replacement test)
actor KyrdanKnight : ExplosiveBarrel replaces ExplosiveBarrel
{
	Radius 20
	Height 56
	Scale 0.3
	States
	{
		Spawn:
		KYRD A  0
		TNT1 A  0 A_SpawnItemEx("KyrGlowmap", 0, 0, 0) // Spawn the brightmap
		KYRD A -1
		Stop
	}
}

// The eye glow (software-friendly brightmap!)
Actor KyrGlowmap
{
	+NOINTERACTION
	+NOGRAVITY
	+CLIENTSIDEONLY
	+NOTONAUTOMAP
	renderstyle Add
	Scale 0.3 // It was off before because I forgot to set the scale here
	
	States
	{
		Spawn:
		KGLW A -1 Bright
		TNT1 A 0 A_Warp(AAPTR_MASTER, 0, 0, 0)
		Stop
	}
}
I'm guessing it must be something off with the actor pointer, but I really don't know. Any help would be highly appreciated as I eventually want to make this entity and many of the enemies have separate actors for the head, body, arms, legs, etc. which all need to move in unison, along with more software brightmaps for glowing parts, muzzle flash, etc. But for now I'm just worried about this brightmap.

While I wait for replies I can separate this knight into separate actors for the head, body, arms and legs and start a new PK3 that does this.
Blue Shadow
Posts: 5032
Joined: Sun Nov 14, 2010 12:59 am

Re: Help with A_Warp for multi-actor entities

Post by Blue Shadow »

A_SpawnItemEx allows you to designate the spawning actor as the master of the spawned actor. That is something you need to do. Another thing is that you need to constantly call A_Warp as to keep the spawned actor's position in-sync with the spawning actor.
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: Help with A_Warp for multi-actor entities

Post by vAethor »

Blue Shadow wrote:A_SpawnItemEx allows you to designate the spawning actor as the master of the spawned actor. That is something you need to do. Another thing is that you need to constantly call A_Warp as to keep the spawned actor's position in-sync with the spawning actor.
I did glance at the TID parameter of SpawnItemEx, but I really don't know how to declare a TID, as the wiki doesn't say anything about that on the article for it. Is a thing's TID the same as its spawn number? Or maybe its DoomEd number, I dunno. I feel if I learned how to declare tids then I would get pretty far.

But I did change my code in KyrGlowmap to this:

Code: Select all

	States
	{
		Spawn:
		KGLW A -1 Bright
		Goto Warp
		
		Warp:
		KGLW A -1 Bright
		TNT1 A 0 A_Warp(AAPTR_MASTER, 0, 0, 0)
		Loop
	}
And it still isn't connected to the main actor, probably because I didn't add that extra argument in the main actor's SpawnItemEX call.I really need help with tids.

Edit: Wow, nothing is working. I looked for the parameter you speak of on SpawnItemEX's wiki page and found two that looked like they might be it (SXF_ISTARGET and SXF_ISMASTER,) they didn't work either. I also tried looking up tid-related functions, tried a couple and it wouldn't even run, claiming it was an unknown actor property (I'm guessing you work with tids in ACS, not Decorate, but I haven't played with ACS nearly as much as Decorate.)

Still completely in the dark as to what a tid actually is, and how to declare one, get an existing one, etc. I Googled it this way and that and found absolutely nothing on what tids are and how to use them. It seems everyone assumes you already know what a tid is, because nothing online actually tells you.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: Help with A_Warp for multi-actor entities

Post by Apeirogon »

No interacton =/= actor FULLY dont interact with other actors. Like, it still prevent teleportation or spawn other actors, if cvar "telefrag actor which prevent teleportation" set to false.
Add noclip to brightmap actor.
User avatar
Caligari87
Admin
Posts: 6191
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him

Re: Help with A_Warp for multi-actor entities

Post by Caligari87 »

A tid is a Thing IDentifier, basically like sector tags but for things/actors. Giving a thing a tid allows you to arbitrarily reference that thing, or more specifically any thing with that tid (multiple things can have the same tid). This is useful for ACS where things are often spawned by a script instead of other things, so they don't have pointers but might need to be addressed somehow, or maybe you have a line action that automatically kills everything with a tid of 5 when the player crosses it.

In your situation using DECORATE, tids are probably not the issue, it's likely your pointers (which are a little different than tids).

I'm a little rusty on DECORATE (because his would be a LOT easier in ZScript with SetOrigin), but I believe you have to set the flag SXF_SETMASTER in the A_SpawnItemEx call for the brightmap to know who its master is, like so:

Code: Select all

A_SpawnItemEx("KyrGlowmap", 0, 0, 0, 0, 0, 0, 0, SXF_SETMASTER)
That way, when you call A_Warp from the brightmap actor the AAPTR_MASTER pointer actually points to the actor that spawned it.

Also I think Apeirogon might be right: Your brightmap should probably use +NOCLIP instead of +NOINTERACTION, because +NOINTERACTION disables a lot of internal processing. Someone please correct me if I'm wrong.

8-)
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: Help with A_Warp for multi-actor entities

Post by vAethor »

Hmm, I changed the code and yet the problem persists. Starting to think Zscript might be a better option, but I'm the opposite of you, Decorate's usually pretty easy for me but I'm rusty on Zscript. Well more specifically, I'm rusty on "real" programming languages which Zscript's syntax was based on.

So care to enlighten me on SetOrigin? I am THIS close to canning my Decorate attempts altogether and switching to Zscript. Because eventually my mods will have stuff like large enemies made up of multiple actors coded together to move in time, and I've definitely seen Zscript do stuff like that before but not Decorate.
A tid is a Thing IDentifier, basically like sector tags but for things/actors. Giving a thing a tid allows you to arbitrarily reference that thing, or more specifically any thing with that tid (multiple things can have the same tid). This is useful for ACS where things are often spawned by a script instead of other things, so they don't have pointers but might need to be addressed somehow, or maybe you have a line action that automatically kills everything with a tid of 5 when the player crosses it.
Ah, thank you. I am very familiar with sector tags since I use Doom Builder all the time. I just edited one of the things in this map in Doom Builder, under the Action tab there's an option to set tags for the thing. I gave one of the barrels a tag of 1. Does that mean its tid is 1?
User avatar
Caligari87
Admin
Posts: 6191
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him

Re: Help with A_Warp for multi-actor entities

Post by Caligari87 »

Yeah, that's correct.

In Zscript you'd have your knight actor spawn the brightmap in an overriden virtual function. This is from memory so it probably won't run, but:

Code: Select all

class KyrdanKnight : Actor {
    actor spawnedActor;

    //This overrides the built in function from Actor, and is executed when the actor is created
    override void BeginPlay() {
        BeginPlay(); //Calls the original function to make sure everything is set up correctly
        spawnedActor = spawn("KyrGlowmap", pos); //Spawn the glowmap at this actor's position
        if(spawnedActor) { //make sure the spawnedActor is non-null or we get a crash!
            spawnedActor.target = self; //Set the glowmap's target pointer to the calling actor "self"
        }
    }
}

class KyrGlowmap : Actor {

    //Called every tic this actor exists
    override void Tick() {
        super.tick(); //call the built-in function
        if(target) { //make sure the target is non-null or we get a crash!
            setorigin(target.pos, true); //moves this actor's position to the target position
            a_setangle(target.angle, true); //sets this actor's angle to the target's angle
        }
    }
}
Obviously you still have to do your states and default blocks and everything else, but that's the basic idea. The knight spawns the glowmap when it first comes into existence, and then the glowmap moves itself to the knight every tic.

NOTE: This is never going to be quite perfect for the glowmap, since your two actors are occupying the same position! Look at Nash's SpriteShadow mod to see how he has the shadow objects move away from (in your case it would be toward) the viewing player so they have the proper depth.

The nice thing about SetOrigin is it's easy to move things around the actor, so arms/legs/etc are much easier than with a_warp. For example:

Code: Select all

setorigin(target.vec3Angle(32, target.angle+90), true)
would put the calling actor 32 units away, at a 90-degree angle from the target.

Make sure to read up on ZScript on the wiki! It's basically "Advanced DECORATE" in most cases and if you have even a little patience and programming knowledge you'll be able to figure things out.

8-)
User avatar
hg82
Posts: 13
Joined: Thu Mar 22, 2018 11:40 am

Re: Help with A_Warp for multi-actor entities

Post by hg82 »

You actually don't need ZScript to do that.
As soon as you set the SXF_SETMASTER flag in A_SpawnItemEx you can use the code you wrote.
But you should change it to something like this:

Code: Select all

+BRIGHT

States
   {
      Spawn:
      KGLW A 0
      Goto Warp
      
      Warp:
      KGLW A 1 A_Warp(AAPTR_MASTER, 0, 0, 0)
      Loop
   }
That's all there is to it. Again: a frame with a duration of "-1" waits forever... So the following frames are never shown.
If you need "Bright" use the "+BRIGHT" Actor Flag.

If your Actor is an enemy - and enemies in doom are most likely to die - then you need to extend your states like this:

Code: Select all

States
   {
      Spawn:
      KGLW A 0
      Goto Warp
      
      Warp:
      KGLW A 0 A_JumpIfHealthLower(1, "Death", AAPTR_MASTER) //jump to "Death" state if the master's health is lower than 1
      KGLW A 1 A_Warp(AAPTR_MASTER, 0, 0, 0)
      Loop

      Death:
      KGLW 0
      Stop
   }
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: Help with A_Warp for multi-actor entities

Post by Apeirogon »

Caligari87 wrote:Someone please correct me if I'm wrong.

Code: Select all

class item : inventory
{
	actor tester_imp;

override void doeffect()
{
	if(tester_imp == null)
	{
	tester_imp = spawn("doomimp", owner.pos + (0,0,0) );
	tester_imp.bNOINTERACTION = true;
	tester_imp.bFRIENDLY = true;
	tester_imp.master = self.owner;
	tester_imp.bNOCLIP = true;
	}
	
	tester_imp.a_warp(aaptr_master);
	if( (level.time % 170) == 0)
	{
		if(tester_imp.bNOCLIP == false ) {tester_imp.bNOCLIP = true; return;}
		if(tester_imp.bNOCLIP == true ) {tester_imp.bNOCLIP = false; return;}
	}
}
}
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: Help with A_Warp for multi-actor entities

Post by vAethor »

Hey, sorry for necroposting, but I just want to say that this is probably a dead project now. I may revisit it another time, but I found the latest version of the OpenGL renderer now supports 320 x 200 resolution and the ability to turn off interpolation and anisotropic filtering, making it look and feel exactly like software mode while giving me more options to work with while making mods.

So I think I will convert this into a conventional brightmap, and continue my project with OpenGL.

Edit: Actually, it may not be entirely dead. I do still really think creating simulated brightmaps for sprites in software mode is a great idea and a good skill, considering I do still find software mode the easiest to work with. But I really don't think Decorate will cut it. I need Zscript. Any idea on where to get started?
vAethor
Posts: 93
Joined: Wed May 10, 2017 4:10 pm

Re: Help with A_Warp for multi-actor entities

Post by vAethor »

Hey, sorry for double-posting but I want to say I finally changed the code to what Caligari and hg82 suggested and it did something!

But now the only problem is, the brightmap disappears when the knight is in motion. I need to find a way to make it so the offsets for the brightmap are the same as that of its parent.

Return to “Scripting”