Editing Impulses

From Quake Wiki

The following is taken from a post by numbersix on June 14, 2014.

Original Post[edit]

Quake-c has three distinct ways to know what a human player wants.

1. mouse directional movement (interpreted movement of the mouse, typically across the x-y plane of the monitor with a cursor, but used differently in FPS games)

// defs.qc
.vector angles;

2. button press on the mouse

// defs.qc
.float button0; // fire
.float button1; // use
.float button2; // jump
// Cataboligne - 9.30.11 - extended mouse button support from darkplaces (... and possibly other engines)
// some mice have a lot of buttons now: Cyborggaming.com (yes, I already have one...it is very nice)
.float button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16;

3. impulse command

// defs.qc
.float impulse; // weapon changes

Impulse is a console command - "impulse {number}" where {number} is an integer value 1 - 255.

impulse 2; // select weapon slot 2 - shotgun<

Of course, having to pull down the console to issue commands would be an extreme challenge in game control, so a number of shortcut possibilities are used. The most common type is another console command called bind - "bind {keypress} {command sequence}"

// typical weapon slot key bindings
// note that keys can be bound to multiple commands - either by a semicolon separated list or with aliases

bind "1" "impulse 1"
bind "2" "impulse 2"
bind "3" "impulse 3"
bind "4" "impulse 4"
bind "5" "impulse 5"
bind "6" "impulse 6"
bind "7" "impulse 7"

When the indicated key is pressed, the assigned command is entered directly in the console.

Usage in code[edit]

Mouse movement[edit]

The mouse directional interpretation is assigned by the engine to the player entity vector ".angles". The player entity is set by the engine from a reserved list of entity slots (usually 1 - 16) upon player network connect. (Debugging hint: for singleplayer and the player hosting a "-listen" server [ not a "-dedicated" server ] this will always be entity 1.)

How is mouse movement interpreted by the engine?[edit]

Movement up and down (often thought of as the y plane on your monitor) is interpreted as a scalar rate and used to change angles_x referred to as "pitch". (Debugging hint - pitch is reversed from expectations and limited - this is NOT a viewpoint angle - looking up has positive angles_x and looking down has negative angles_x, with a range of 30 to -30. So when the player looks straight up - 90 degrees from viewpoint of 0 degrees or straight ahead, the value of angles_x is 30.) This causes player viewpoint to move up and down - from pointing straight up to pointing straight down. Additionally any model assigned to the player entity will be adjusted by using the angles_x value as an actual angle. What this means is when a player looks up, the model will "tilt" back at angles_x degrees. When the player looks down the model will "tilt" forward at angles_x degrees .

As if this usage of pitch was not already confusing enough - for a visual understanding this video segment demonstrates first pitch (up-down), then yaw (side to side) and then faster pitch / faster yaw:

fig 1. pitch and yaw

Movement from side to side (often thought of as the x plane on your monitor ) is interpreted as a scalar rate and used to change angles_y referred to as "yaw". This is an actual facing angle that represents the players view offset from angle 0. Any model assigned to the player entity will be rotated to the same angle. The ".angles" vector values are modified by a rate - the faster you move the mouse the faster they change. This degree of rate control is the primary reason some keyboard + mouse users despise console controls. (Even the silly little analog sticks that attempt to do the same thing.)

You can also assign pitch and yaw angles in quake-c. This code fragment forces the engine to change the viewpoint to the assigned value: // teleporters use this to point the player in the proper direction // self must be the player entity - often it will be other in the case of touch with trigger entities self.fixangle = TRUE; // turn this way immediately

Mouse buttons[edit]

The button values are read by the engine from the OS drivers and the floats defined above are assigned the set values. For each mouse button pressed, the corresponding .button{n} value is set to 1 - if that button is not pressed it is 0. While all mouse button presses could be seen per frame - you can only see one impulse value in quake-c per frame! The mouse button values can be read anywhere in the code until they are zeroed. This is typically done in functions called from PlayerPreThink() and PlayerPostThink() ( per frame code: Moddb.com )

Impulse commands[edit]

The float ".impulse" is assigned the value of an impulse command by the engine when one is entered in the console by that player - either directly, by key binding or alias.

Impulse commands are handled in client.qc and weapons.qc. Found in PlayerPostThink() covered here: Moddb.com

// do weapon stuff - after intermission and dead checks

W_WeaponFrame ();

// in weapons.qc

void () W_WeaponFrame =
if (time < self.attack_finished)
if (self.impulse)
ImpulseCommands(); // also in weapons.qc 

void () ImpulseCommands =
// weapons are changed 1 - 7
// cycle weapons (using key press or mousewheel / buttons) are done

// *** any mod impulses should be checked and dealt with here
// *** sample code - this is an example only!
if (self.impulse == 66)
bprint("developer: Impulse 66 detected !\n");
if (self.button6)
bprint("developer: Mouse button #6 detected !\n");
bprint(" player facing angle: ");
bprint(" - pitch: ");
bprint(" - pitch view angle: ");
bprint(ftos(self.angles_x * -3)); // correct for sign, estimate true view angle
// *** end sample code

// MUST be cleared for next impulse and so command is not repeated
self.impulse = 0;

Your best opportunity to handle impulse commands is in this function *** before the value is zeroed. Player interface is done in the per frame code segment via PlayerPreThink() and PlayerPostThink() ( per frame code: Moddb.com ) to interpret commands as quickly as possible.

New impulses can be added for: bots, admin control, alternate weapon modes, grapple hooks, dropping runes or items, and many other exciting details.

Good luck adding new impulses to your mods!