Page 1 of 1
Replacing multiple actors with a single new actor?
Posted: Mon Dec 28, 2020 2:27 pm
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!

Re: Replacing multiple actors with a single new actor?
Posted: Mon Dec 28, 2020 3:11 pm
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.

Re: Replacing multiple actors with a single new actor?
Posted: Mon Dec 28, 2020 3:26 pm
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.
Re: Replacing multiple actors with a single new actor?
Posted: Tue Dec 29, 2020 1:09 am
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.
Re: Replacing multiple actors with a single new actor?
Posted: Tue Dec 29, 2020 8:48 pm
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!!
Re: Replacing multiple actors with a single new actor?
Posted: Wed Dec 30, 2020 1:06 am
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"
}
Re: Replacing multiple actors with a single new actor?
Posted: Thu Dec 31, 2020 11:52 am
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!
Re: Replacing multiple actors with a single new actor?
Posted: Wed Jan 06, 2021 6:30 pm
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.

Re: Replacing multiple actors with a single new actor?
Posted: Thu Jan 07, 2021 1:06 am
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.