Creating new monsters or other complex items (ZScript)
Monsters are just regular actors that call some specific monster AI action functions:
Properties, states and sounds
It's these functions that make an actor act like a monster but there's a few more things to observe:
- Use the Monster property to set up all the necessary flags to make an actor act like a monster.
- A monster's Height and Radius should be set properly. Unlike props, it is essential that these values are correct because they are used by the collision detection code which also checks whether a monster has been hit by a weapon.
- A monster should have proper definitions for all standard sounds, or it might remain silent in certain situations. See SeeSound, ActiveSound, PainSound, DeathSound. AttackSound may be required as well, although it's possible to play the sound directly with A_StartSound.
- A monster requires a minimum set of states:
- Spawn: This should define a looping 'idle' sequence. This sequence has to call A_Look (or one of its variants, like A_LookEx) repeatedly so that the monster can react to players.
- See: This defines a looping walking sequence. This sequence has to call A_Chase or one of its variants repeatedly so that the monster can walk around and do things.
- Melee/Missile: This defines a near or far attack sequence. At least one of them is needed so that the monster is able to attack players or other monsters.
- Death: This is called when the monster's health goes below zero.
- Pain: Used for animation when the monster reacts to pain. Usually A_Pain is called here to play the monster's PainSound, but custom behavior can be injected as well.
- You can also define one of the optional special death sequences:
- XDeath: Used instead of Death if the monster's health goes below its GibHealth when it does, to define an "extreme death" sequence.
- Raise: Allows the monster to be resurrected by Arch-Viles or other monsters capable of doing that through A_VileChase. This is the animation of the monster being resurrected (often it's just the death animation played in reverse).
Normally monsters are based on the Actor class (this is shown in the examples below).
Examples
This is an example of a properly defined monster in ZScript. It is just an exact replica of Doom's pistol shooting Zombie:
class ZombieClone : Actor { Default { Monster; Obituary "$OB_ZOMBIE"; // prints "%o was killed by a zombieman" Health 20; Radius 20; Height 56; Speed 8; PainChance 200; SeeSound "grunt/sight"; AttackSound "grunt/attack"; PainSound "grunt/pain"; DeathSound "grunt/death"; ActiveSound "grunt/active"; DropItem 'Clip', 256; +FLOORCLIP; } States { Spawn: POSS AB 10 A_Look; loop; See: POSS AABBCCDD 4 A_Chase; loop; Missile: POSS E 10 A_FaceTarget; POSS F 8 A_PosAttack; POSS E 8; goto See; Pain: POSS G 3; POSS G 3 A_Pain; goto See; Death: POSS H 5; POSS I 5 A_Scream; POSS J 5 A_NoBlocking; POSS K 5; POSS L -1; stop; XDeath: POSS M 5; POSS N 5 A_XScream; POSS O 5 A_NoBlocking; POSS PQRST 5; POSS U -1; stop; Raise: POSS KJIH 5; goto See; } }
Note, in order for this monster to appear in the map editor so you can place it in your map, you'll need to give it a DoomEdNum, also known as editor number. Nowadays this should be don through MAPINFO:
DoomEdNums
{
10246 = "ZombiemanClone"
}
If you don't need a complete monster but ony a subset of its functions you can do so. For example to create a shootable item that doesn't act as a monster all you have to do is to remove the See state, the call to A_Look in the Spawn state and replace the Monster property with the appropriate flags. The one flag you need is SHOOTABLE but normally you might want to set a few others as well. This is an example of a shootable decoration:
class FloorLamp : Actor { Default { Health 1; Radius 16; Height 51; DeathSound "misc/glass"; +SHOOTABLE +SOLID +NOBLOOD } States { Spawn: HAWA A -1 Bright; Loop; Death: HAWA B 11 A_Scream; HAWA C 9; HAWA D -1 A_Fall; Stop; } }
Other things are possible as well, for example an actor that reacts to seeing a player but instead of waking up and attacking the player it is doing something else, for example playing a sound:
class TriggerSound1 : Actor { Default { SeeSound "ts1"; +NOBLOCKMAP } States { Spawn: TNT1 A 2 A_Look; Loop; See: TNT1 A 1; Stop; } }
Virtual functions
Monsters can utilize a large array of virtual functions. Some of the most commonly used ones are: