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
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