Need help solving SpawnItemEX with Random spawner monsters

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!)

Need help solving SpawnItemEX with Random spawner monsters

Postby swc132994 » Sun Dec 13, 2020 8:32 pm

Hello,

This is my first post in a long while. I am seeking any advice/help with how to resolve this issue that has finally left me in despair.
I have been patching and modding an existing mod and ran into a problem when I added an optional toggle to spawn random monsters using the SpawnItemEx and RandomSpawner.
I set up a menu option to use either the default spawns or to use random spawners for items and monsters. at first I thought it was working well until I noticed monsters that should be waiting in ambush coming for me without sighting me. I also had issues with lost Boss death flags triggering instant map completions or issues from monsters losing their TIDs but manged to resolve those in the end.

What remains is the monster spawns using the SpawnItemEx with RandomSpawner losing their map set ambush flags. I've been battling with this problem for a few weeks now without success. Despite constantly referring to the wiki and the forum for an solution, the answer still evades me. My knowledge of ACS is quite limited but just managed to do something basic. I wish I could learn and use ZScript but I am trying to maintain compatibility with the latest Zandronum 3.1 development version.

If anyone needs to know the specific mod, here it the link
https://www.moddb.com/mods/brutal-doom- ... v2-patched

DECORATE
Code: Select allExpand view
//WEAPON RANDOM SPAWNERS
actor D64PRifleReplacer : RandomSpawner
{
DropItem "PlasmaRifleSpawner"
DropItem "PlasmaRifleSpawner"
DropItem "Lasergun"
}

Actor D64BFGReplacer : RandomSpawner
{
DropItem "BFG9000Spawner"
DropItem "BFG9000Spawner"
DropItem "BFG9000Spawner"
DropItem "UnmakerSpawner"
}

//ITEM RANDOM SPAWNERS
actor WpnPower1Replacer : RandomSpawner
{
DropItem "64Blursphere"
DropItem "64Blursphere"
DropItem "64Blursphere"
DropItem "64Blursphere"
DropItem "64Blursphere"
DropItem "64Blursphere"
DropItem "WpnPower1"
}

Actor WpnPower2Replacer : RandomSpawner
{
DropItem "64Berserk"
DropItem "64Berserk"
DropItem "64Berserk"
DropItem "64Berserk"
DropItem "64Berserk"
DropItem "64Berserk"
DropItem "WpnPower2"
}

Actor WpnPower3Replacer : RandomSpawner
{
DropItem "64Soulsphere"
DropItem "64Soulsphere"
DropItem "64Soulsphere"
DropItem "64Soulsphere"
DropItem "64Soulsphere"
DropItem "64Soulsphere"
DropItem "WpnPower3"
}

//MONSTER RANDOM SPAWNERS
Actor D64ImpReplacer : RandomSpawner
{
DropItem "64DoomImp"
DropItem "64DoomImp"
DropItem "64DoomImp"
DropItem "NightmareImp"
}

Actor D64SpectreReplacer : RandomSpawner
{
DropItem "64Spectre"
DropItem "64Spectre"
DropItem "64Spectre"
DropItem "64Spectre"
DropItem "64NightmareSpectre"
}

Actor D64CacodemonReplacer : RandomSpawner
{
DropItem "64Cacodemon"
DropItem "64Cacodemon"
DropItem "64Cacodemon"
DropItem "64Cacodemon"
DropItem "64Cacodemon"
DropItem "64Cacodemon"
DropItem "NightmareCacodemon"
}

Actor D64CyberdemonReplacer : RandomSpawner// Replaces Cyberdemon
{
DropItem "64Cyberdemon"
DropItem "64Cyberdemon"
DropItem "64Cyberdemon"
DropItem "Annihilator64"
}

actor D64HellHoundReplacer : RandomSpawner
{
DropItem "64Demon"
DropItem "64Demon"
DropItem "64Demon"
DropItem "64Demon"
DropItem "64Demon"
DropItem "64Demon"
DropItem "64HellHound"
}

//ACS TRIGGERED DYNAMIC SPAWNERS
Actor Dyn_PlasmaRifleReplacer Replaces Plasmarifle
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1478,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("PlasmaRifleSpawner",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64PRifleReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
}
}

Actor Dyn_BFGReplacer Replaces BFG9000
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1478,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("BFG9000Spawner",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64BFGReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
}
}

Actor Dyn_WpnPower1Replacer Replaces Blursphere
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1478,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Blursphere",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("WpnPower1Replacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
}
}

Actor Dyn_WpnPower2Replacer Replaces Berserk
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1478,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Berserk",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("WpnPower2Replacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
}
}

Actor Dyn_WpnPower3Replacer Replaces Soulsphere
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1478,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Soulsphere",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("WpnPower3Replacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48)
   Stop
}
}

Actor Dyn_ImpReplacer Replaces Doomimp
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1480,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64DoomImp",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64ImpReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
}
}

Actor Dyn_SpectreReplacer Replaces Spectre
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1480,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Spectre",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64SpectreReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
}
}

Actor Dyn_CacodemonReplacer Replaces Cacodemon
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1480,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Cacodemon",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64CacodemonReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
}
}

Actor Dyn_CyberdemonReplacer Replaces Cyberdemon
{
+NOTDMATCH
+BOSS
+BOSSDEATH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1480,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Cyberdemon",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64CyberdemonReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
}
}

////////////////////////////
//ARCHVILE HELLHOUND REPLACER
///////////////////////////
Actor Dyn_ArchvileReplacer Replaces Archvile
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1479,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Hellhound",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("64Archvile",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
}
}

Actor Dyn_HellhoundReplacer Replaces Demon
{
+NOTDMATCH
States
{
Spawn:
   TNT1 A 0
   TNT1 A 1 ACS_ExecuteAlways(1480,0)
   TNT1 A 1 A_Jump(256,"Deciding")
Deciding:
   TNT1 A 1
   loop
NormalSpawner:
   TNT1 A 0 A_SpawnItemEx("64Demon",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
DynSpawner:
   TNT1 A 0 A_SpawnItemEx("D64HellHoundReplacer",0,0,0,0,0,0,0, SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL |SXF_TRANSFERAMBUSHFLAG | SXF_CLEARCALLERTID | 304, 0, tid)
   Stop
}
}


Here is the ACS script part just in case it's needed
Code: Select allExpand view
script 1478 (void)                                                
{
if   (GetCvar("DynamicSpawnCvar") == 0) { SetActorState(0,"NormalSpawner"); }
if   (GetCvar("DynamicSpawnCvar") == 1) { SetActorState(0,"DynSpawner"); }
}

script 1479 (void)                                                
{
if   (GetCvar("DynamicSpawnCvar2") == 0) { SetActorState(0,"NormalSpawner"); }
if   (GetCvar("DynamicSpawnCvar2") == 1) { SetActorState(0,"DynSpawner"); }
}

script 1480 (void)   
{                                             
if   (GetCvar("DynamicSpawnCvar3") == 0) { SetActorState(0,"NormalSpawner"); }
if   (GetCvar("DynamicSpawnCvar3") == 1) { SetActorState(0,"DynSpawner"); }
}


Best regards,
swc132994
swc132994
 
Joined: 12 Jun 2014

Re: Need help solving SpawnItemEX with Random spawner monste

Postby Player701 » Mon Dec 14, 2020 2:02 am

The problem is that even though the RandomSpawner receives the AMBUSH flag, it does not handle it in any way because it only handles AMBUSH via spawn flags. Spawn flags are derived from the flags set in the map editor, and are not directly related to normal flags. Actors spawned as a result of replacement or via RandomSpawner will pass on their spawn flags from the original mapthing, while actors spawned via A_SpawnItemEx won't.

Unfortunately, I'm not sure if there is any way to fix this, especially if you're aiming for Zandronum compatibility. Your code is already extremely hacky as it is, and attempting to rectify your problem might cause your mod to break unexpectedly in other scenarios. Also see this bug report which is currently on-hold.

A few other things I'd like to point out:

  1. Instead of ACS_ExecuteAlways and SetActorState, your could use A_JumpIf and ACS_ExecuteWithResult. The wiki article on ACS_ExecuteWithResult has an example of using it in concert with A_JumpIf. Please disregard this suggestion if your Zandronum version doesn't support these actions (though I'm pretty sure it should).
  2. You could also check if your Zandronum supports calling GetCVar from DECORATE - in this case you can get rid of your ACS completely and combine GetCVar with A_JumpIf directly.
  3. Do not use magic numbers in flags expressions, e.g. "SXF_TRANSFERPOINTERS | SXF_TRANSFERSPECIAL | 48". What does that 48 stand for? Are you sure you remember? In this case, it means "SXF_SETMASTER | SXF_NOCHECKPOSITION", and SXF_SETMASTER takes precedence over SXF_TRANSFERPOINTERS, which probably means that your code contains a bug. And 304 stands for "SXF_SETMASTER | SXF_NOCHECKPOSITION | SXF_TRANSFERAMBUSHFLAG", which means that: a) you have the same problem with SXF_SETMASTER overriding SXF_TRANSFERPOINTERS, and b) you're essentially specifying SXF_TRANSFERAMBUSHFLAG twice, which is quite meaningless (although not an error in and of itself).
  4. If you find out that you cannot get rid of ACS (see p.2), then you could at least combine multiple ACS scripts into a single script with an argument, e.g.:
Code: Select allExpand view
script 1478 (int cvarNum)                                               
{
    str cvar;
   
    switch(cvarNum)
    {
        case 0:
            cvar = "DynamicSpawnCvar";
            break;
        case 1:
            cvar = "DynamicSpawnCvar2";
            break;
        // TODO: Add more cvars
        default:
            SetResultValue(0);
            terminate;
    }
   
    SetResultValue(GetCvar("DynamicSpawnCvar") == 1);
}

and use it like this:

Code: Select allExpand view
TNT1 A 0 A_JumpIf(ACS_ExecuteWithResult(1478, 1 /* <-- use the correct cvarNum depending on the actor */) == 1, "DynSpawner")
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: Need help solving SpawnItemEX with Random spawner monste

Postby swc132994 » Mon Dec 14, 2020 7:20 pm

Hi Player701,

Thanks for the advice.

It is a real shame that I cannot do anything about the Map set Ambush flag as it was the last thing I needed to resolve to make the spawner work as intended. Oh well!

I have seen that bug report post before when I was searching for an answer to my problem. Fortunately in Plynthus's case he managed to work around the spawner issue using ZScript.

I first checked Zandronum, but unfortunately it doesn't support using GetCVar using Decorate. A shame as it would have been straightforward otherwise :(
Zandronum however does support using A_JumpIf with ACS_ExecuteWithResult so I will see on combining the three separate scripts into one and using arguments as you have shown.
BTW I removed the magic number flags. I realised quite late that I really don't know what the magic numbers stood for and had in fact just copy/pasted these numbers from elsewhere.

Cheers,
swc132994
swc132994
 
Joined: 12 Jun 2014

Re: Need help solving SpawnItemEX with Random spawner monste

Postby swc132994 » Thu Dec 24, 2020 10:43 am

I noticed that the map set ambush flag only affected monsters using the random spawner combined with the SpawnItemEx. Therefore I changed the script to use the SpawnItemEx only and it seems to work as intended with monsters keeping their map set ambush flags.

Code: Select allExpand view
Actor Dyn_ImpReplacer Replaces Doomimp
{
+NOTDMATCH
+FLOORCLIP
+NOBLOCKMONST
   States
   {
   Spawn:
      TNT1 A 0
      TNT1 A 1 ACS_ExecuteAlways(1480,0)
      TNT1 A 1 A_Jump(256,"Deciding")
   Deciding:
      TNT1 A 1
      loop
   NormalSpawner:
      TNT1 A 0 A_SpawnItemEx("64DoomImp",0,0,0,0,0,0,0, SXF_TRANSFERAMBUSHFLAG|SXF_NOCHECKPOSITION|SXF_TRANSFERPOINTERS|SXF_TRANSFERSPECIAL|SXF_CLEARCALLERTID, 0, tid)
      Stop
   DynSpawner:
      TNT1 A 1 A_Jump(64,2) // 64/256 is approx. 25% chance of jump
      TNT1 A 0 A_SpawnItemEx("64DoomImp",0,0,0,0,0,0,0, SXF_TRANSFERAMBUSHFLAG|SXF_NOCHECKPOSITION|SXF_TRANSFERPOINTERS|SXF_TRANSFERSPECIAL|SXF_CLEARCALLERTID, 0, tid)
      stop
      TNT1 A 0 A_SpawnItemEx("Nightmareimp",0,0,0,0,0,0,0, SXF_TRANSFERAMBUSHFLAG|SXF_NOCHECKPOSITION|SXF_TRANSFERPOINTERS|SXF_TRANSFERSPECIAL|SXF_CLEARCALLERTID, 0, tid)
      stop
   }
}


I tried implementing a combined ACS script and calling a case number but I couldn't get it to work properly so I have left that part is for now.
swc132994
 
Joined: 12 Jun 2014

Re: Need help solving SpawnItemEX with Random spawner monste

Postby swc132994 » Fri Jun 17, 2022 3:06 am

Sorry to raise my old post again. However this is related to the same spawner as before with different issues. I am still trying to keep Zandronum compatibility hence I need to stick with DECORATE.

I have since revised my spawner scripts (which seem to better than old ones above) and added new ones for more monster options. Basically this is a menu option driven monster replacer.

DECORATE:
Actor RevenantChooser Replaces Revenant
{
States
{
Spawn:
TNT1 A 0 NoDelay A_JumpIf(CallACS("RevenantChooserACS")==1,2)
TNT1 A 0 A_SpawnItemEx("64Revenant",0,0,0,0,0,0,0,SXF_TRANSFERAMBUSHFLAG|SXF_NOCHECKPOSITION|SXF_TRANSFERPOINTERS|SXF_TRANSFERSPECIAL|SXF_CLEARCALLERTID,0,tid)
Stop
TNT1 A 0 A_SpawnItemEx("64Revenant_OLD",0,0,0,0,0,0,0,SXF_TRANSFERAMBUSHFLAG|SXF_NOCHECKPOSITION|SXF_TRANSFERPOINTERS|SXF_TRANSFERSPECIAL|SXF_CLEARCALLERTID,0,tid)
Stop
}
}

CVARINFO:
server int RevenantChooserCvar = 0;

ACS:
script "RevenantChooserACS" (void)
{
SetResultValue(GetCVar("RevenantChooserCvar"));
}

MENUDEF segments:
Option "Revert back to old Revenant =", "RevenantChooserCvar", "YesOrNo"

OptionValue "YesOrNo"
{
0, "No"
1, "Yes"
}


The above works great for replacing monsters. Map set AMBUSH flags and map set tids are successfully transferred over to the spawned monster so all maps function as they should. However other map set flags are not transferred, such as DORMANT and ALLY. See image attached for the revenant property flags set on the map. I cannot find any other useful flags I could use from the wiki https://zdoom.org/wiki/A_SpawnItemEx

N.B. Both new revenants monsters inherit from revenant and they behave similar but with different sprites and death states. These monsters will behave fine on their own when not put through the spawner above ,i.e. all map set flags are ok.

I hope I have posted enough info. Can anyone help me with this problem as I want the monsters to fully behave as they are defined on the map?

If more info is needed. The project is now on github: https://github.com/swc132994/BD64game_v2.5_r31

Best regards,

swc132994
You do not have the required permissions to view the files attached to this post.
swc132994
 
Joined: 12 Jun 2014

Re: Need help solving SpawnItemEX with Random spawner monste

Postby swc132994 » Sun Jun 19, 2022 5:46 pm

I was hoping someone may have some insight into a way to transfer these map set flags over. It will also be fine if someone from above can tell if this is impossible using this method so at least I can investigate alternatives, if there are any.
I know that if using the RandomSpawner, then all the monster map flags will transfer over. However I can not seen a method of how to use this through a MenuDef option toggle as a cvar would need to be read to jump to normal spawn or one with a random chance to spawn another monster type.
swc132994
 
Joined: 12 Jun 2014

Re: Need help solving SpawnItemEX with Random spawner monste

Postby Player701 » Mon Jun 20, 2022 12:08 am

If you want to use RandomSpawners, you can only read CVARs if you inherit from the RandomSpawner class and override the ChooseSpawn method. This is only possible with ZScript. With DECORATE, you are mostly limited to what A_SpawnItemEx can offer. In addition to that, if you use one of the SXF_IS... flags (e.g. SXF_ISMASTER) with A_SpawnItemEx, you can attempt to transfer the dormant and ally flags by calling the following script from your spawner actor after spawning:

Code: Select allExpand view
// NB: Thing_Deactivate does not work with TID 0.
// You will have to set a temporary TID, which may affect compatibility.
#define TEMP_TID 65535

script "TransferDormantAndFriendlyFlags" (void)
{
    // Get flags from the calling actor (the spawner)
    bool isDormant = GetActorProperty(0, APROP_DORMANT);
    bool isFriendly = GetActorProperty(0, APROP_FRIENDLY);

    // Change the activator to the spawned actor
    SetActivator(0, AAPTR_MASTER); // if SXF_ISMASTER was used (otherwise use AAPTR_TARGET or AAPTR_TRACER accordingly)

    // Transfer friendly flag
    SetActorProperty(0, APROP_FRIENDLY, isFriendly);
   
    // NB: SetActorProperty(..., APROP_DORMANT, ...) is not supported
    if (isDormant)
    {
        // Give a temporary TID to the activator for Thing_Deactivate to work
        int oldTid = ActivatorTID();
        Thing_ChangeTID(0, TEMP_TID);

        Thing_Deactivate(TEMP_TID);

        // Restore original TID
        Thing_ChangeTID(0, oldTid);
    }
}

Note that I cannot confirm at this time that the script will work, but it is theoretically possible; it mostly depends on when (and under what conditions) mapthing flags are transferred to actor flags.
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: Need help solving SpawnItemEX with Random spawner monste

Postby swc132994 » Mon Jun 20, 2022 8:14 am

Hi Player701,

Many thanks for taking the time to type this up. It is much appreciated :)

When I am next at my computer I will see if I can get this working. Like you said, I too have a fear Changing tids could end up breaking maps. We shall see.

Thanks again and all the best,

Swc132984
swc132994
 
Joined: 12 Jun 2014

Re: Need help solving SpawnItemEX with Random spawner monste

Postby Player701 » Mon Jun 20, 2022 8:33 am

A small update: I've taken some time to test Thing_Activate and Thing_Deactivate ACS calls in GZDoom, and it seems that my initial information was not correct: at least in GZDoom 4.8.0, these functions do support the value 0 as the first argument to refer to the activator of the script. But this might not have been the case in earlier versions, so I have no idea whether it'll work in Zandronum. Just in case, here's the updated script, which does not use a temporary TID. If it doesn't work for you, you will have to try the previous version instead.

Code: Select allExpand view
script "TransferDormantAndFriendlyFlags" (void)
{
    // Get flags from the calling actor (the spawner)
    bool isDormant = GetActorProperty(0, APROP_DORMANT);
    bool isFriendly = GetActorProperty(0, APROP_FRIENDLY);

    // Change the activator to the spawned actor
    SetActivator(0, AAPTR_MASTER); // if SXF_ISMASTER was used (otherwise use AAPTR_TARGET or AAPTR_TRACER accordingly)

    // Transfer friendly flag
    SetActorProperty(0, APROP_FRIENDLY, isFriendly);

    // NB: SetActorProperty(..., APROP_DORMANT, ...) is not supported
    if (isDormant)
    {
        Thing_Deactivate(0);
    }
}
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: No registered users and 0 guests