Replacing multiple actors with a single new actor?

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!)
Post Reply
BaronGasMask
Posts: 4
Joined: Sat Dec 26, 2020 12:12 pm
Graphics Processor: nVidia (Modern GZDoom)

Replacing multiple actors with a single new actor?

Post by BaronGasMask »

Hey all! Long-time, first-time here--tried searching the wiki and forums for an answer to this question and couldn't find it.

I'm working on my first .pk3 and adding some new weapons via DECORATE as replacements for extant ones--specifically a shotgun replacement. I was wondering if there was a way to use the "replaces" function for multiple actors? If I wanted my new gun to replace both the shotgun and ssg, for instance? Is there another DECORATE function that could do this?

Apologies if this has already been answered elsewhere--I started making this (my first-ever digital game project of any kind, really!) last week so I'm still learning the terminology to search for! Thanks! :D
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: Replacing multiple actors with a single new actor?

Post by Caligari87 »

The naive approach would be to replace all the actors with a dummy actor that spawns the actor you want. Example:

Code: Select all

actor DummyShotgunReplacer replaces Shotgun {
  States {
    Spawn:
      TNT1 A 0 A_SpawnItemEx("MyCustomWeapon")
      Stop
  }
}

actor DummyChaingunReplacer replaces Chaingun {
  States {
    Spawn:
      TNT1 A 0 A_SpawnItemEx("MyCustomWeapon")
      Stop
  }
}
A cleaner possibility is using MAPINFO Editor Number remapping to force certain editor numbers to remap to a different actor.

Code: Select all

DoomEdNums
{
  2001 = MyCustomWeapon  //shotgun
  2002 = MyCustomWeapon  // chaingun
}
If you're willing to use ZScript, a CheckReplacement() handler is one extremely robust method.

8-)
Blue Shadow
Posts: 4949
Joined: Sun Nov 14, 2010 12:59 am

Re: Replacing multiple actors with a single new actor?

Post by Blue Shadow »

^^ The "naive approach" is better replaced with the [wiki=Classes:WeaponGiver]WeaponGiver[/wiki] one. The MAPINFO one only replaces map-placed actors.
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: Replacing multiple actors with a single new actor?

Post by Player701 »

Caligari87 wrote:

Code: Select all

actor DummyShotgunReplacer replaces Shotgun {
  States {
    Spawn:
      TNT1 A 0 A_SpawnItemEx("MyCustomWeapon")
      Stop
  }
}

actor DummyChaingunReplacer replaces Chaingun {
  States {
    Spawn:
      TNT1 A 0 A_SpawnItemEx("MyCustomWeapon")
      Stop
  }
}
Note that this code will not work as-is unless NODELAY is added before A_SpawnItemEx calls. It will also not play well with "items respawn" / "weapons stay" gameplay options, since all dynamically spawned items are considered "dropped" and are not subject to those. WeaponGiver is probably the best non-ZScript based solution here.
Guest

Re: Replacing multiple actors with a single new actor?

Post by Guest »

Sorry for the late response on this! These replies are really helpful, but after perusing it looks like adding a ZScript definition might be the cleanest way to go. Does anyone have any resources/tutorials they'd recommend on creating/editing ZScript docs? Can these run in parallel in my extant DECORATE script, a la KEYCONF or SNDINFO, or would I need to port my DECORATE work over to ZScript? Thanks so much everyone!!
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: Replacing multiple actors with a single new actor?

Post by Player701 »

You can combine ZScript with DECORATE, but you cannot use DECORATE-based actors in your ZScript code because DECORATE is parsed after ZScript. However, this does not prevent you from using CheckReplacement to manage replacements of existing actors with your custom DECORATE-based actors. This is possible because CheckReplacement deals with class names rather than actual actor instances, so your ZScript will compile without errors.

For the most comprehensive ZScript language and API documentation available at the moment, see here. Also check out the wiki for many useful articles on various ZScript topics. In particular, a lot of information on event handlers can be found here.

Now, regarding your particular use case. This is what Caligari87's code would look like in ZScript with CheckReplacement:

Code: Select all

version "4.5"

class MyEventHandler : EventHandler
{
    override void CheckReplacement(ReplaceEvent e)
    {
        if (e.Replacee == 'Shotgun' || e.Replacee == 'Chaingun')
        {
            e.Replacement = 'MyCustomWeapon';
        }
    }
}
You should not forget to add your event handler in your MAPINFO lump, otherwise GZDoom will not register it in the game:

Code: Select all

gameinfo
{
    AddEventHandlers = "MyEventHandler"
}
BaronGasMask
Posts: 4
Joined: Sat Dec 26, 2020 12:12 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Replacing multiple actors with a single new actor?

Post by BaronGasMask »

Oh, neat! So I can just keep a separate ZScript.txt "in front of" my DECORATE script with the checkreplacement handler, call it in MAPINFO, and don't need to tweak anything in DECORATE for the time being? That's awesome! Thanks so much everyone!
BaronGasMask
Posts: 4
Joined: Sat Dec 26, 2020 12:12 pm
Graphics Processor: nVidia (Modern GZDoom)

Re: Replacing multiple actors with a single new actor?

Post by BaronGasMask »

Player701 wrote:You can combine ZScript with DECORATE, but you cannot use DECORATE-based actors in your ZScript code because DECORATE is parsed after ZScript. However, this does not prevent you from using CheckReplacement to manage replacements of existing actors with your custom DECORATE-based actors. This is possible because CheckReplacement deals with class names rather than actual actor instances, so your ZScript will compile without errors.
Sorry, one point of clarification here--how would ZScript recognize my custom actors if it's parsing first? I'm running into a debug code where the ZScript function I've added isn't recognizing my custom weapon name, and I assume that's why. Do I need to add a definition section in ZScript that points to DECORATE? I'm sorry for bugging you about this again, I just don't quite know how to phrase my question in such a way that the extant ZScript documentation is helpful for this rn. :(
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: Replacing multiple actors with a single new actor?

Post by Player701 »

Like I said before, the CheckReplacement event does not create actors by itself, so it doesn't deal with any variables or fields of types that are defined in DECORATE (and are thus yet unknown to ZScript). You only specify a class name, and those are evaluated at runtime, when everything has already been parsed.

Here's an example of code that won't work due to DECORATE / ZScript parsing order:

Code: Select all

//DECORATE
actor MyCoolWeapon : Weapon
{
    ...
}

// ZScript
class MyClass
{
    void MyMethod()
    {
        class<Weapon> weap = 'MyCoolWeapon'; // OK: just a class name
        MyCoolWeapon mcw; // Error: Unknown type MyCoolWeapon

        ...
    }
}
In short: You cannot create variables of DECORATE-defined class types, nor can you cast a variable to such a type. Everything else should work.
Post Reply

Return to “Scripting”