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.

Replacing multiple actors with a single new actor?

Postby BaronGasMask » Mon Dec 28, 2020 2:27 pm

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
BaronGasMask
 
Joined: 26 Dec 2020
Discord: Baron#2318
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia (Modern GZDoom)

Re: Replacing multiple actors with a single new actor?

Postby Caligari87 » Mon Dec 28, 2020 3:11 pm

The naive approach would be to replace all the actors with a dummy actor that spawns the actor you want. Example:
Code: Select allExpand view
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 allExpand view
DoomEdNums
{
  2001 = MyCustomWeapon  //shotgun
  2002 = MyCustomWeapon  // chaingun
}


If you're willing to use ZScript, a CheckReplacement() handler is one extremely robust method.

8-)
User avatar
Caligari87
I'm just here for the community
User Accounts Assistant
 
Joined: 26 Feb 2004
Location: Salt Lake City, Utah, USA
Discord: Caligari87#3089

Re: Replacing multiple actors with a single new actor?

Postby Blue Shadow » Mon Dec 28, 2020 3:26 pm

^^ The "naive approach" is better replaced with the WeaponGiver one. The MAPINFO one only replaces map-placed actors.
User avatar
Blue Shadow
 
 
 
Joined: 14 Nov 2010
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: ATI/AMD (Modern GZDoom)

Re: Replacing multiple actors with a single new actor?

Postby Player701 » Tue Dec 29, 2020 1:09 am

Caligari87 wrote:
Code: Select allExpand view
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.
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Replacing multiple actors with a single new actor?

Postby Emma Fingermud » Tue Dec 29, 2020 8:48 pm

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!!
Emma Fingermud
 

Re: Replacing multiple actors with a single new actor?

Postby Player701 » Wed Dec 30, 2020 1:06 am

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 allExpand view
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 allExpand view
gameinfo
{
    AddEventHandlers = "MyEventHandler"
}
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Replacing multiple actors with a single new actor?

Postby BaronGasMask » Thu Dec 31, 2020 11:52 am

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
 
Joined: 26 Dec 2020
Discord: Baron#2318
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia (Modern GZDoom)

Re: Replacing multiple actors with a single new actor?

Postby BaronGasMask » Wed Jan 06, 2021 6:30 pm

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. :(
BaronGasMask
 
Joined: 26 Dec 2020
Discord: Baron#2318
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia (Modern GZDoom)

Re: Replacing multiple actors with a single new actor?

Postby Player701 » Thu Jan 07, 2021 1:06 am

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 allExpand view
//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.
User avatar
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support


Return to Scripting

Who is online

Users browsing this forum: Player701 and 1 guest