This article's documentation is for anything that uses the Source engine. Click here for more information.

$definemacro

From Valve Developer Community
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
English (en)Translate (Translate)

$definemacro is a QC command available in all Source Source games. It defines a string substitution macro. A macro can be used as a short hand way to specify other QC commands. The macro creates a block a named block of text, that when referred to will virtually insert that text into the QC file, along with replacing the named parameters with the specified values.

Syntax

 $definemacro <macroname> [arg_name1] [arg_name2] [...] \\
  • Defines a string substation macro.
  • The macro definition begins on the next line, and all subsequent lines that end with \\ (two backslashes).
  • Arguments are referenced by surrounding them with $’s (i.e. $arg_name1$ ), and can be embedded inside of other words.
  • To use the macro, type $macroname and the next N tokens will be taken as arguments.

Examples

 $definemacro testmacro seqname filename endframe \\
 $sequence $seqname$01 $filename$ { \\
     frames 0 $endframe$ \\
     subtract $seqname$ 0 delta \\
     weightlist justbody \\
 }

 // Then, to use the macro, do:
 $testmacro small_flinch "npc flinch 01" 20


Despite $sequence and $animation, macros do objectively behave to avoid repetitions. As for $jigglebone example:

 $definemacro JiggleGeneric6 BoneName PitchMin PitchMax YawMin YawMax \\
 $jigglebone $BoneName$ { \\
  is_flexible { \\
   length 64 \\
   tip_mass 200 \\
   pitch_stiffness 50 \\
   pitch_damping 7 \\
   yaw_stiffness 50 \\
   yaw_damping 7 \\
   along_stiffness 100 \\
   along_damping 0 \\
   pitch_constraint $PitchMin$ $PitchMax$ \\
   yaw_constraint $YawMin$ $YawMax$ \\
  } \\
 } \\

 // then execute the above macro
 $JiggleGeneric6 Hair_0 -11 16 -30 30
 $JiggleGeneric6 Hair_1 -15 15 -30 30
 $JiggleGeneric6 Hair_2 -15 15 -30 30
 // [...]


We may use macros to create shortcuts for $sequence and $animation options.

Tip.pngTip:For this case, create and call macros inside brace brackets to avoid syntax issues
 // $lockhands is a whole macro which behave as shortcut for two line ik repetition used by many viewmodels animations
 $definemacro lockhands \\
 { \\
   ikrule "rhand" touch "ValveBiped.weapon_bone" usesource \\
   ikrule "lhand" touch "ValveBiped.weapon_bone" usesource \\
 } \\

 // $freehands release it ik rules, may used for reload, fridget and many other animation sequences
 $definemacro freehands \\
 { \\
   ikrule "rhand" release \\
   ikrule "lhand" release \\
 } \\

 $sequence idle_1 idle loop fixuploop -15 15 { $lockhands }

 // we $freehands for reload
 $sequence reload reload3 {
  ACT_VM_RELOAD 1
  fadein 0 fadeout 0.8
  fixuploop -15 15
  frames 0 84
  { $freehands }
 }

Macro Nesting

You can execute macros from within macros. This is useful if you need to execute a series of commands several times. In this example we use it to create blend spaces for each weapon.

 $definemacro MakeRunDirection direction weapon \\
 $animation a_run_$direction$ run_$direction$ LX LY worldspaceblend a_run_$weapon$_C \\
 
 $definemacro MakeRun weapon ACT \\
 $animation a_run_$weapon$_C aimlayer_$weapon$ frame 5 5 \\
 $MakeRunDirection $weapon$ S \\
 $MakeRunDirection $weapon$ SW \\
 $MakeRunDirection $weapon$ W \\
 $MakeRunDirection $weapon$ NW \\
 $MakeRunDirection $weapon$ N \\
 $MakeRunDirection $weapon$ NE \\
 $MakeRunDirection $weapon$ E \\
 $MakeRunDirection $weapon$ SE \\
 \\
 $sequence run_$weapon$ { \\
 	a_run_$weapon$_SW	a_run_$weapon$_S	a_run_$weapon$_SE \\
 	a_run_$weapon$_W	a_run_$weapon$_C  	a_run_$weapon$_E  \\
 	a_run_$weapon$_NW	a_run_$weapon$_N	a_run_$weapon$_NE \\
 	blendwidth 3 \\
 	blend move_x -1 1 \\
 	blend move_y -1 1 \\
 	addlayer aimlayer_$weapon$ \\
 	fadein 0.3 fadeout 0.5 loop \\
 	node "run" \\
 	$ACT$ 1 \\
 } \\

 $MakeRun smg     ACT_RUN_SMG
 $MakeRun pistol  ACT_RUN_PISTOL
 $MakeRun crowbar ACT_RUN_CROWBAR

Passing Macro Commands Down

You can also pass tokens down a macro nest. This is super useful if you want to create a top level interface for your commands, as well as creating macros that can be used with multiple skeletons.

 $definemacro makeholdtype weapon activity weights \\
 $makeaimlayer9frame $weapon$ \\
 $makeidle $weapon$ ACT_IDLE_$activity$ \\
 $MakeLocomotion run $weapon$ ACT_RUN_$activity$ $weights$ \\
 $MakeLocomotion crouch $weapon$ ACT_CWALK_$activity$ $weights$ \\
 $MakeLocomotion swim $weapon$ ACT_SWIM_$activity$ $weights$ \\

 $makeholdtype pistol_twohand PISTOL_TWOHAND weights_worldspaceblend
 $makeholdtype smg SMG weights_worldspaceblend
 $makeholdtype rifle RIFLE weights_worldspaceblend
 $makeholdtype physcannon PHYSCANNON weights_worldspaceblend
 $makeholdtype shotgun SHOTGUN weights_worldspaceblend
 $makeholdtype grenade GRENADE weights_worldspaceblend_dual

Condition Statements

Due nature of how QC Code works, we can have a minimal boolean statements for macros with some cveats:

$definemacro GestureTouchAllLeftRightIK GestureName FileName BoneName All Left Right \\
$sequence $GestureName$ $FileName$ { \\
   if $All$   { ikrule "lhand" touch $BoneName$ usesource } \\
   if $All$   { ikrule "rhand" touch $BoneName$ usesource } \\
   if $Left$  { ikrule "lhand" touch $BoneName$ usesource } \\
   if $Left$  { ikrule "rhand" release } \\
   if $Right$ { ikrule "lhand" release } \\
   if $Right$ { ikrule "rhand" touch $BoneName$ usesource } \\
   iklock "rfoot" 1 0 iklock "lfoot" 1 0 \\
 } \\

 $GestureTouchAllLeftRightIK "gesture_touch_all"   gesture_fidget_00.dmx "ValveBiped.weapon_bone" 1 0 0
 $GestureTouchAllLeftRightIK "gesture_touch_left"  gesture_fidget_01.dmx "ValveBiped.weapon_bone" 0 1 0
 $GestureTouchAllLeftRightIK "gesture_touch_right" gesture_fidget_02.dmx "ValveBiped.weapon_bone" 0 0 1

Caveats

  • You can not contain tokens within quotes. EX: "animations/$macroexample$_run" will not work; the compiler will read it as-is and look for "animations/$macroexample$_run.smd" instead of replacing it.
  • You can use macro tokens when defining other macros as long as there is SOME text behind it. Ex: "$macroexamplecommand token1 token2 $macrotoken3$" will fail the compile with "macro expand overflow", but "$macroexamplecommand example token1 $macrotoken3$ token2" will work. You can also do "$macroexamplecommand example token1 token2 $macrotoken3$ dummy"
  • You can use macros to define only $animation or $sequence options, however, the macro must be called inside brace brackets otherwise it can't be parsed properly.

See also