Creating new weapons
From ZDoom Wiki
While making a custom weapon in ZDoom is a bit tricky, I am writing this "guide" to sort a couple things out.
A basic weapon in the decorate lump would look like this:
ACTOR Doom3Shotgun : Shotgun 20024
{
Weapon.SelectionOrder 350
Inventory.PickupSound "misc/d3pickup"
Weapon.AmmoGive 8
Weapon.AmmoUse 1
AttackSound "weapons/d3shtgnf"
States
{
Spawn:
D3SH A -1
LOOP
Ready:
D3SG A 1 A_WeaponReady
LOOP
Deselect:
D3SG A 1 A_Lower
LOOP
Select:
D3SG A 1 A_Raise
LOOP
Fire:
D3SG A 0 A_JumpIfNoAmmo(1)
D3SG A 6 A_GunFlash
D3SG B 4
D3SG C 4
D3SG D 34
D3SG E 2
D3SG F 2
D3SG G 8
D3SG F 2
D3SG E 2
Goto Ready
Flash:
D3SF A 6 A_FireBullets(10,10,15,30,0,1)
stop
}
}
Now that big chunk of code describes the functions and states of a shotgun. Lets start by analyzing this piece of code.
- (ACTOR Doom3Shotgun : Shotgun 20024)- Describes that this thing is going to be a complex actor, like a monster or a weapon, instead of a static object or projectile. This line must always come first so that ZDoom knows that it is "compiling" a sort of weapon.
Note: This line must always be in the format (ACTOR [weaponname] : [inheriting weapon or "weapon"] [doomed number])
After that line, there is a single bracket. This bracket marks the start of the code.
Next comes the various weapon stats, like what ammo type, how much ammo this weapon gives you when you pick it up, or how much it uses on one shot. Then there are the properties like what sound it should make when firing, or the message you receive when picking up the weapon.
- (Inventory.PickupSound "misc/d3pickup")-Tells ZDoom what sound to play when the item is picked up. [can be defined in the SNDINFO lump]
- (Weapon.AmmoGive 8)-Tells ZDoom how much ammo to give when this weapon is picked up. [this is NOT the maximum amount of ammo it can hold]
- (Weapon.AmmoUse 1)-Tells ZDoom how much ammo to use when firing the weapon. [Providing the use argument in the relevent codepointers is set]
- (AttackSound "weapons/d3shtgnf")-Tells ZDoom what sound to play when A_FireBullets and A_CustomPnch is used. [Has to be defined in the SNDINFO lump: Projectiles use their SpawnSound]
There are other properties you can set there, but not required for that weapon, because it inherits all of its missing properties from the original shotgun. Like the pickup message, if I wanted to define a custom pickup message, then I would have to put in a line of code that looks like this.
- (Inventory.Pickupmessage "You got the Doom 3 Shotgun!")
- Please note that the function 'Weapon.SelectionOrder' prioritizes which weapons the game should switch to if your current weapon runs out of ammo. So if you run out of shells, you would switch to the super shotgun because its preference is higher than, say, the pistol. The lower the number, the higher the priority
That would go at the top of the script above the pickup sound. Also, notice how I didn't define an ammo type. Because of inheriting that, I didn't have to do it. Inheriting makes it a somewhat shorter process by taking out the un-needed pieces of code that need to be written.
Anyways... Let's get back to the analysis!
The next chunk in the code is the most crucial part... The firing sequences!
These tell ZDoom what is going on and what to do at certain frames. This removes the previous limitations of DeHacked or Whacked where you couldn't add in more frames, but could only replace the current ones. With this method, you are able to make brand new sequences, to brand new weapons.
The states code looks a bit like this:
States
{
Spawn:
D3SH A -1
LOOP
Ready:
D3SG A 1 A_WeaponReady
LOOP
Deselect:
D3SG A 1 A_Lower
LOOP
Select:
D3SG A 1 A_Raise
LOOP
Fire:
D3SG A 0 A_JumpIfNoAmmo(1)
D3SG A 6 A_GunFlash
D3SG B 4
D3SG C 4
D3SG D 34
D3SG E 2
D3SG F 2
D3SG G 8
D3SG F 2
D3SG E 2
Goto Ready
Flash:
D3SF A 6 A_FireBullets(10,10,15,2,0,1)
stop
}
Now lets analyze this state by state!
First off is the spawn state: Code:
Spawn:
D3SH A -1
LOOP
This makes it so when the item is placed onto a map, it will display a certain sprite. [like when you see a plasma rifle on the screen, you know what it is by looking at the sprite!]
This (as all other states) has to be in a certain format, which as follows: Code:
Spawn:
[sprite] [frame] [delay]
LOOP
- the SPRITE is always the first four letters of the sprite.
- the FRAME always is the next letter after the SPRITE.
- and the DELAY is how long it will take before it gets to the next frame.
note: DELAY is not in seconds, but in tics. in every second, there are 35 tics. -1 makes the frame last forever
Next in these series of states is the READY state: Code:
Ready:
D3SG A 1 A_WeaponReady
LOOP
- This state tells ZDoom that your weapon is ready to be fired! This state is needed after your weapon is selected or done being fired. ZDoom knows when to stop the sprite animation.
The format of this state is similar to the SPAWN state, except for a couple exceptions. Code:
Ready:
[sprite] [frame] [delay] [action]
LOOP
- The SPRITE, FRAME, and DELAY are all used the same way as in the SPAWN state.
- The ACTION, however, is used in every state except the SPAWN state. The ACTION tells ZDoom what to perform when it gets to this particular frame.
Note: Keep in mind that this sprite is supposed to be the idle state of your weapon, and NOT what it will look like when it is on the ground! Note 2: Always keep the action as "A_WeaponReady" else you can't fire the weapon!
The next two states are basically the exact opposite of each other. Look at the format of the SELECT and DESELECT states: Code:
Deselect:
D3SG A 1 A_Lower
LOOP
Select:
D3SG A 1 A_Raise
LOOP
- These states tell ZDoom what to do when your weapon is selected and deselected. The format is the same as the READY state, except instead of putting "A_WeaponReady" as the action, put the "A_Raise" for the SELECT state, and "A_Lower" for the DESELECT state.
The next state defines what happens when you click the shoot button. It tells ZDoom what to shoot, or what to do at the select frames. On this weapon, there are a bunch of frames, but only about six of them are actual firing frames. The rest are to give the illusion that it is "reloading".
The firing sequence looks like this: Code:
Fire:
D3SG A 0 A_JumpIfNoAmmo(1)
D3SG A 6 A_GunFlash
D3SG B 4
D3SG C 4
D3SG D 34
D3SG E 2
D3SG F 2
D3SG G 8
D3SG F 2
D3SG E 2
Goto Ready
The format of each line is exactly the same as the READY, SELECT, and DESELECT states. For the actions there are a lot of different things you can put in there. You don't need an action on every frame, just on the necessary ones. Here is a short list of actions and their syntaxes:
- A_FireBullets(h-spread, v-spread, number of bullets, damage per bullet, "PuffType", UseNoAmmo,range) - fires certain ammount of bullets with custom damage
- A_RailAttack(damage,x-offset,ammo,"RR GG BB" color of the spiral, "RR GG BB" color of the line.)
For example: A_RailAttack(50,10,1,"00 FF 00", "FF 00 00") would make a railgun fire, dealing 50 damage, it looks like it fires to the right, takes one ammo, has a green spiral around a red line (Cristmas railgun?) A_RailAttack(50,10,1,none, "FF 00 00") Would do the same thing, only the spiral wouldn't be shown. Likewise: A_RailAttack(50,10,1,"00 FF 00, none) The line wouldn't be shown. If you want to make a weapon that fires quickly, I'd recomend that you either leave off the line or the spiral. Zdoom can only handle a certain number of particles at once.
- A_JumpIfNoAmmo(number of frames) - it jumps the specified number of frames when you have no ammo.
- A_GiveInventory("item name", amount) - gives the player "amount" of "item type"
- A_ReFire - goes to the HOLD state or the FIRE state is there is no HOLD state
- A_TakeInventory("item name", amount) - takes "amount" of "item type" from the player
- A_SpawnItem("item name", distance, zheight, useammo) - spawns an "item name" "distance" mapunits in front of user. 0 sets the minimum distance possible without overlapping
- A_CustomPunch(damage, dontrandomize, UseNoAmmo, pufftype,range) - defines a punching paramter
- A_FireCustomMissile(type, angle, UseNoAmmo, xy-offset, spawnheight) - fires a custom missle
- A_GunFlash - goes to the FLASH state, playing through the frames and drawing the sprites directly on top of the weapon's firing frames.
- A_PlaySound("SNDINFO name") - plays the specified sound on the selected frame.
- A_PlayWeaponSound("SNDINFO name") - plays the specified sound on the specified frame on the weapon channel. 1 normal and one weapon sound can be played per actor at any one time.
- A_Explode - Damages all things within the explosion radius.
- A_Gravity - makes the thing subject to falling from the air. (projectiles only)
- A_SeekerMissile(angle threshold, angle maxturnangle) - threshold and maxturnangle determine how 'aggressive' the missile will home in on its target. The larger the values the more precise it is. Both angles are specified in degrees and must be in the range [0, 90]. (projectiles only)
- A_JumpIfInventory("itemname", amount, frames) - Skips a certain number of frames depending on how much of an inventory item you have, the inventory items can also be weapons or ammo.
- A_Jump(chance, frames) - chance is the number between 1-255 that it happens. The higher the number the more likely it will happen. frames is how many frames it will jump.
- A_ThrowGrenade("MissileType",height,xymom,zmom,usenoammo) - xymom is how far it will be thrown. zmom is how high it will be thrown.
These are just some of the states used to define actions.
The next two states are semi-important: The FLASH and HOLD states. The FLASH state is only used if you want a muzzle flash to be in your weapon. The HOLD state is used only if you want your weapon to be able to fire over and over again. [like a machine gun]
The FLASH state looks like this: Code:
Flash:
(sprite) (frame) (delay) (action)
stop
By now you should know what each thing means so I'm not going over them.
The HOLD state looks very similar: Code:
Hold:
(sprite) (frame) (delay) (action)
Goto Ready
- This would be the firing sequence you would see if you held down the mouse button, but only if you use the "A_ReFire" code pointer to make it do so.
This guide was made to show people the basics of the new DECORATE system in the 2.1.X Series of ZDoom. This guide was created by ChaosCentral.

