Page 1 of 1

[SOLVED] Monster Spawn Not Dying When A_KillMaster is Called

Posted: Wed Aug 23, 2017 7:31 am
by That Blind Guy
The title says it all. Here's how it's supposed to work.

1. The spawner replaces a monster (e.g., the Cyberdemon is replaced by a "CyberDemonSpawner" actor).
2. This spawner selects a random monster from the set given to it using A_Jump and places it in the level.
3. The spawner waits until the monster is killed. At this point, A_KillMaster is called. Ergo, it's the death of the spawner, not the monster itself, that triggers whatever is supposed to happen such as a level ending or wall lowering.

The mod I'm working on has 5 possible bosses for both the Cyberdemon and Spider Mastermind spawn points. Nine of these 10 bosses work, and we know that the spawners themselves are fine. We tried replacing the faulty monster with one we know works elsewhere, and everything fired off as intended, so something is wrong with the monster itself. I'm all but sure of it.

Here is the actor's code.

Code: Select all

actor SZ_AracnorbQueen 30100
{
	//$Category "Monsters/Bosses"
	//$Title "Arachnorb Queen"
  MONSTER
  +NOGRAVITY
  +FLOAT
  +FLOATBOB
  +BOSS
  +NORADIUSDMG
  +DONTMORPH
  +MISSILEMORE
  Health 2500
  WoundHealth 150
  Radius 34
  Height 76
  Mass 2000
  Speed 15
  var int user_ragetimer;
  var int user_autorage;
  PainChance 45
  PainChance "BFGBlast", 256
  PainChance "Thunderbolt", 256
  PainChance "GreenBFGball", 256
  PainChance "Pierce", 0
  PainChance "Dark", 0
  SelfDamageFactor 0
  DamageFactor "EnergyBlast", 2.0
  DamageFActor "BFGBlast", 2.0
  DamageFactor "Pierce", 0.15
  DamageFactor "Dark", 0.15
  SeeSound "queen/sight"
  ActiveSound "queen/active"
  PainSound "queen/pain"
  DeathSound "queen/death"
  MeleeSound "queen/melee"
  MeleeDamage 16
  MissileHeight 36
  Obituary "%o suffered psychic trauma from an aracnorb queen's brainwaves."
  HitObituary "%o had %p skull chewed by an aracnorb queen."
  Scale 0.85
  States
  {
  Spawn:
	ARNQ A 0 A_SetUserVar(user_autorage, 0)
        ARNQ A 1 A_Look
        Loop
  See:
        ARNQ A 2 A_Chase
        Loop
  Melee:
        ARNQ ABC 3 A_FaceTarget
        ARNQ D 6 A_MeleeAttack
        Goto See
  Missile:
        TNT1 A 0 A_JumpIf(user_ragetimer > 0, "RageMissile")
	TNT1 A 0 A_Jump(96, "BFG")
	TNT1 A 0 A_JumpIfCloser(512, "CloseRange")
	Goto LongRange
  CloseRange:
        TNT1 A 0 A_Jump(176, "RapidFire")
	Goto SpreadFire
  LongRange:
        TNT1 A 0 A_Jump(176, "SpreadFire")
	Goto RapidFire
  BFG:
        TNT1 A 0 A_PlaySound("queen/fire")
	ARNQ BCD 8 A_FaceTarget
        ARNQ E 10 Bright A_CustomMissile("QueenBFG",50,-10,0)
	Goto See
  RapidFire:
        ARNQ BCD 8 A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ P 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 0 BRIGHT A_FaceTarget
        ARNQ E 5 BRIGHT A_CustomMissile ("QueenPlasmaBlast", 40, 0, random(-4,4))
        ARNQ D 5 A_FaceTarget
        //ARNQ D 5
	Goto See
  SpreadFire:
        ARNQ BCD 8 A_FaceTarget
	ARNQ A 0 A_PlaySound("weapons/ionalt")
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	ARNQ E 5 Bright A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-4,4))
	ARNQ BCD 8 A_FaceTarget
	ARNQ A 0 A_PlaySound("weapons/ionalt")
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	ARNQ E 5 Bright A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-4,4))
	ARNQ D 5 A_FaceTarget
	Goto See
  RageMissile:
	ARNQ BCD 8 A_FaceTarget
	ARNQ A 0 A_PlaySound("weapons/ionalt")
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	ARNQ E 5 Bright A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-4,4))
	ARNQ BCD 4 A_FaceTarget
	ARNQ A 0 A_PlaySound("weapons/ionalt")
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	ARNQ E 5 Bright A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-4,4))
	ARNQ BCD 4 A_FaceTarget
	ARNQ A 0 A_PlaySound("weapons/ionalt")
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	TNT1 A 0 A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-7,7), CMF_AIMOFFSET|CMF_OFFSETPITCH, random(-3,3))
	ARNQ E 5 Bright A_CustomMissile("QueenPlasmaBlast", 40, 0, random(-4,4))
        TNT1 A 0 A_PlaySound("queen/fire")
	ARNQ BCD 8 A_FaceTarget
        ARNQ E 10 Bright A_CustomMissile("QueenBFG",50,-10,0)
	ARNQ E 0 A_SetUserVar(user_ragetimer, user_ragetimer-1)
	ARNQ E 0 A_JumpIf(user_ragetimer < 1, "EndRage")
  Pain:
	TNT1 A 0 A_Jump(128, "PainSpam")
        ARNQ F 4
	ARNQ F 4 A_Pain
        Goto See
  Pain.StunBomb:
	ARNQ F 0 A_Pain
	ARNQ F 35 A_SpawnItem("StunLight")
	Goto PainSpam
  Pain.BFGBlast:
        ARNQ A 0 A_CustomMissile("BFGEffect", 40)
	ARNQ F 10 A_Pain
	Goto BeginRage
  Death.BFGBlast:
        ARNQ A 0 A_CustomMissile("BFGEffect", 40)
	Goto Death
  Pain.Thunderbolt:
        ARNQ A 0 A_CustomMissile("PBFGEffect", 40)
	ARNQ F 10 A_Pain
	Goto BeginRage
  Death.Thunderbolt:
        ARNQ A 0 A_CustomMissile("PBFGEffect", 40)
	Goto Death
  Wound:
	ARNQ A 1
	ARNQ A 0 A_JumpIf(user_autorage > 0, "See")
	ARNQ A 0 A_SetUserVar(user_autorage, 1)
  Pain.GreenBFGBall:
  BeginRage:
        ARNQ F 0 A_ChangeFlag("INVULNERABLE", true)
        ARNQ F 0 A_SetSpeed(30)
	ARNQ F 0 A_SetUserVar(user_ragetimer, 2)
	ARNQ F 0 A_Quake(7, 70, 0, 2000)
	ARNQ F 0 A_PlaySound("queen/sight")
	ARNQ F 35
	ARNQ A 0 A_CustomMissile("QueenSummon", 50, 0, -45)
	ARNQ A 0 A_CustomMissile("QueenSummon", 50)
	ARNQ A 0 A_CustomMissile("QueenSummon", 50, 0, 45)
	Goto See
  EndRage:
        ARNQ F 0 A_ChangeFlag("INVULNERABLE", false)
       ARNQ A 1 A_SetSpeed(15)
	Goto See
  PainSpam:
        ARNQ F 4
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,5,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,25,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,45,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,65,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,85,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,105,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,125,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,145,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,165,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,185,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,205,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,225,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,245,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,265,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,285,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,305,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,325,32,0)
        ARNQ F 0 A_custommissile("QueenPainPlasmaBlast",75,0,345,32,0)
	ARNQ F 4 A_Pain
	ARNQ F 0 A_Jump(128, "PainSpam")
        Goto See
  Death:
	ARNQ G 0 A_SpawnItem("SZ_LifeSphere")
        ARNQ G 0 A_ChangeFlag("FLOATBOB",0)
        ARNQ G 9 A_Scream
	ARNQ G 3 A_Fall
	ARNQ G 175 
	ARNQ G 0 A_KillMaster
	ARNQ G 1 A_BossDeath
        Wait
  Crash:
        ARNQ HIJKL 9
        ARNQ M -1
        Stop
  /*Raise:
        ARNQ MLKJIHGA 8
        ARNQ A 0 A_ChangeFlag("FLOATBOB",1)
	Goto See*/
  }
}
Here's what we've tried.

-Deriving the actor from bosses we know work.
-Calling A_KillChildren
-Calling A_UnsetInvulnerable in case that somehow got triggered.
-Changing Wait to Stop in the Death state.
-Creating a fallthrough XDeath state
-Specifying the class of the spawner in the parameters of A_KillMaster

I might be missing a couple. Those are just the ones I remember. We've been just trying everything we can think of.

The real confusing part is that we had this problem with 2 different bosses on this spawner, because we forgot the the SXF_SETMASTER flag. That fixed one, but not the other.

Here's the spawner code too, just to be thorough.

Code: Select all

Actor SpiderMastermindSpawner : SpiderMastermind Replaces SpiderMastermind
{
	Health 10000000000
	Height 0
	Radius 0
	MONSTER
	-COUNTKILL
	+SHOOTABLE
	+CANTSEEK
	+INVISIBLE
	States
	{
	Spawn:
		NULL A 1
		Goto Summon
	Summon:
		NULL A 1
		NULL A 0 A_Jump(220,"Spider","Arachno","Queen","Haed")
		NULL A 0 A_Jump(182,"CM")
	Spider:
		NULL A 0
		NULL A 1 A_SpawnItemEX("SZ_SpiderMastermind",0,0,0,0,0,0,0,304,0)
		NULL A -1
		wait
	Arachno:
		NULL A 0
		NULL A 1 A_SpawnItemEX("SZ_Arachnophyte",0,0,0,0,0,0,0,304,0)
		NULL A -1
		wait
	Queen:
		NULL A 0
		NULL A 1 A_SpawnItemEX("SZ_AracnorbQueen",0,0,0,0,0,0,0,304,0)
		NULL A -1
		wait
	Haed:
		NULL A 0
		NULL A 1 A_SpawnItemEX("SZ_Haedexebus",0,0,0,0,0,0,0,304,0)
		NULL A -1
		wait
	CM:
		NULL A 0
		NULL A 1 A_SpawnItemEX("SZ_CyberMastermind",0,0,0,0,0,0,0,304,0)
		NULL A -1
		wait
	Pain:
		NULL A -1
		wait
	Death:
		NULL A 1 A_BossDeath
		NULL A 0 A_Die
		NULL A -1
		Stop
	}
}
If anyone has suggestions or sees the solution, please let me know.

Thanks!

Re: Monster Spawner Not Dying When A_KillMaster is Called

Posted: Wed Aug 23, 2017 7:53 am
by phantombeta
You don't have SXF_SetMaster in your flags.
Also, don't ever use numbers for flag arguments. Use constants and combine them with '|' instead. Makes it more readable, and if for some reason the values ever need to be changed, it'll still work. (Like this: "SXF_NoCheckPosition | SXF_SetMaster")
(Specifically, 304 has bits 5, 6 and 9 set. That means it has SXF_NoCheckPosition, SXF_Telefrag and SXF_TransferPitch set. No SXF_SetMaster there. If you don't have that flag, it won't set the spawner as the actor's master, and your spawner won't be killed.)

Also, you seem to be using that just to randomize the monsters spawned. You can use the [wiki=Classes:RandomSpawner]RandomSpawner[/wiki] class instead. It automatically handles bosses and stuff, so you don't need to add A_KillMaster to your monsters.

Re: Monster Spawner Not Dying When A_KillMaster is Called

Posted: Wed Aug 23, 2017 8:01 am
by That Blind Guy
You don't have SXF_SetMaster in your flags.
Also, don't ever use numbers for flag arguments. Use constants and combine them with '|' instead. Makes it more readable, and if for some reason the values ever need to be changed, it'll still work. (Like this: "SXF_NoCheckPosition | SXF_SetMaster")
(Specifically, 304 has bits 5, 6 and 9 set. That means it has SXF_NoCheckPosition, SXF_Telefrag and SXF_TransferPitch set. No SXF_SetMaster there. If you don't have that flag, it won't set the spawner as the actor's master, and your spawner won't be killed.)

Also, you seem to be using that just to randomize the monsters spawned. You can use the RandomSpawner class instead. It automatically handles bosses and stuff, so you don't need to add A_KillMaster to your monsters.
I see. I am not the first to work on code for this project. I'd rather use flag names explicitly myself, but the two that were working on this before me had it this way. I just left it alone because it was working at the time.

Unfortunately, setting SXF_SetMaster and SXF_NoCheckPosition did nothing. I had tried SetMaster on its own before posting this, and that had the same result.

Re: Monster Spawner Not Dying When A_KillMaster is Called

Posted: Wed Aug 23, 2017 8:10 am
by phantombeta
Then you're doing something wrong. Anyway, since you're only using this to randomize monster spawns, it'd be a good idea to use a RandomSpawner instead, as that won't require modification of the monsters to make the spawner work with bosses. (It'll also transfer some flags and properties that can be set by the map. Your spawner won't, and if these are not transferred it can completely break some maps.)

Re: Monster Spawner Not Dying When A_KillMaster is Called

Posted: Wed Aug 23, 2017 9:05 am
by That Blind Guy
That works almost perfectly. Thank you!

I do have one small problem now. The game is supposed to wait a few seconds after a boss dies before proceeding so that players have a chance to pick up item drops in the event killing them ends the level (Tower of Babel, Dis, etc.), however, the transitions are happening at the exact moment the boss enters its death state, long before it calls A_KillMaster and A_BossDeath.

This is all there is to the code.

Code: Select all

Actor SpiderMastermindSpawner : RandomSpawner Replaces SpiderMastermind
{
	DropItem "SZ_SpiderMastermind", 255, 1
	DropItem "SZ_Arachnophyte", 255, 1
	DropItem "SZ_AracnorbQueen", 255, 1
	DropItem "SZ_Haedexebus", 255, 1
	DropItem "SZ_CyberMastermind", 255, 1
}
I tried sticking a 200-tic delay in the Death state. Unsurprisingly that doesn't work, so I just pulled it back out.

What am I missing here?

Re: Monster Spawner Not Dying When A_KillMaster is Called

Posted: Thu Sep 07, 2017 7:04 am
by That Blind Guy
Finally a solution! Sorry for resurrecting a slightly old thread. Just giving this some closure.

It turns out the Crash state in the boss' code was the issue. Removing that fixed the problem right up!