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

$bodygroup: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(bah)
(Removing deprecated Category)
 
(26 intermediate revisions by 16 users not shown)
Line 1: Line 1:
''Body Groups'' are sub-meshes of a model that can have changeable states. Server code can change the state of a model's body groups.
{{LanguageBar|title = $bodygroup}}{{tabsBar|main=gs|base=$bodygroup}}
{{this is a|QC command|name=$bodygroup}} It defines a group of meshes that can be turned on or off, or changed entirely. Server code can change their state.
{{toc-right}}


== Syntax ==
{{note|Body groups '''cannot''' change [[skeleton|skeletons]] or [[collision model|collision models]].}}
To define a body groups, you need to add lines in the [[.qc]]:


$bodygroup (name)
== Example ==
{
studio (modelname)
["studio" modelname]
[blank]
}


== Examples ==
This body group allows a weapon to have iron sights, laser sights, or no sights at all:


A single .mdl could be used for characters with and without glasses:
<source lang=php>
$bodygroup sights
{
studio "ironsights"
studio "laser_dot"
blank
}
</source>


$bodygroup studio
This body group defines the entire chest region of the model, which spans multiple bones:
{
studio "dude.smd"
}
$bodygroup eyewear
{
studio "glasses.smd"
blank
}


This example has two body groups numbered 0 and 1. Group 0 uses a single mesh and group 1 uses 2, a model of a pair of glasses (state 0) and the built-in "no-polygons" model (state 1) which is used to "turn-off" the glasses.
<source lang=php>
$bodygroup chest
{
studio "chest_with_no_armor"
studio "chest_with_light_armor"
studio "chest_with_heavy_armor"
studio "chest_with_super_armor"
}
</source>


=== Multiple sets ===
{{note|Since body group polygons never share vertices with the base mesh in Source models, there need not be seams between properly-made components.}}
You can have multiple entries in a bodygroup, for example you could have 4 different sets of the chest, each with different styles:


$bodygroup chest
== Bodygroups in Level of Detail Meshes ==
{
studio "chest_with_no_armor.smd"
studio "chest_with_light_armor.smd"
studio "chest_with_heavy_armor.smd"
studio "chest_with_super_armor.smd"
}


You could also just put the armor pieces in their own group and always draw the underlying chest without armor, but it's less efficient and often there's no clean "base" set, such as if you're using bodygroups to define multiple heads.
Using [[LOD|Level of Detail]] meshes - ''especially for high-poly geometry'' - is '''highly recommended'''. Body groups can be used in <code>[[$lod]]</code> strings in the same method as normal geometry meshes:


The models used in bodygroups can span any number of bones.
<source lang=php>
$lod 12
{
replacemodel "chest_with_no_armor" "chest_with_no_armor_lod1"
replacemodel "chest_with_light_armor" "chest_with_light_armor_lod1"
replacemodel "chest_with_heavy_armor" "chest_with_heavy_armor_lod1"
replacemodel "chest_with_super_armor" "chest_with_super_armor_lod1"
}


== Switching groups in code ==
$lod 18
{
replacemodel "chest_with_no_armor" "chest_with_no_armor_lod2"
replacemodel "chest_with_light_armor" "chest_with_light_armor_lod2"
replacemodel "chest_with_heavy_armor" "chest_with_heavy_armor_lod2"
replacemodel "chest_with_super_armor" "chest_with_super_armor_lod2"
}
$shadowlod
{
replacemodel "chest_with_no_armor" "chest_with_no_armor_lod2"
replacemodel "chest_with_light_armor" "chest_with_light_armor_lod2"
replacemodel "chest_with_heavy_armor" "chest_with_heavy_armor_lod2"
replacemodel "chest_with_super_armor" "chest_with_super_armor_lod2"
}
</source>


To change a body group's state call <code>CBaseAnimating::SetBodygroup( int iGroup, int iValue )</code> in server code. For example, this would randomly give 1 out of 5 characters glasses:
== Programming ==


SetBodygroup( 1, ( RandomInt( 1, 5 ) == 1 )?1:0 );
To change a body group's state:


Bodygroups are limited to 32 bits of combinations, which is a total of 4,294,967,296 combinations.  If you used the above eyewear and chest examples, the total combinations would be eyewear x chest, or 2 x 4, or a total of 8 combinations. Just multiply all your bodygroup combinations together to make sure your total is less than the max.  Weapons by default are limited to 256 combinations, though it's just a network limit which is easy for your mod to change.  See:
<source lang=cpp>
int BodyGroup_Sights = FindBodygroupByName("sights"); // calculate this value once
SetBodygroup( BodyGroup_Sights , 1 ); // laser dot
</source>


BEGIN_NETWORK_TABLE_NOBASE(CBaseViewModel, DT_BaseViewModel)
By default, <code>[[CBaseAnimating]]</code> supports 4,294,967,296 combinations (32 bits), and <code>[[CBaseViewModel]]</code> supports 256 (8 bits). You can raise either of these by editing the relevant [[SendProp]] for <code>m_nBody</code>.
...
<b>SendPropInt (SENDINFO(m_nBody), 8),</b>


==See also==
To calculate how many combinations you need, multiply the size of all your bodygroups together. The examples on this page total 3 * 4 = 12...but add two more groups the same size and you're up at 144. The figure grows exponentially.
* [[Multiple_Skins_for_a_Single_Model | Skins]]
* DOD Player Models make extensive use of Bodygroups.


[[Category:Modeling]]
==Switching bodygroup via $Sequence==
It is possible to swap bodygroups during [[$sequence|sequences]], using the following event:
* AE_CL_BODYGROUP_SET_VALUE <frame> "<bodyGroupName> <body>" {{note|So far only tested in {{l4d2}} and {{tf2}}. ''Seems'' to be fine but certain functions in the game can restart it to default making it somewhat "buggy".}}
* AE_CL_ENABLE_BODYGROUP <frame> "<bodyGroupName>"
* AE_CL_DISABLE_BODYGROUP <frame> "<bodyGroupName>"
 
 
Examples:
  $bodygroup "travel"
  {
  studio "delorean_Notravel"
  studio "Delorean_Yestravel"
  studio "Delorean_brokentravel"
  }
  $sequence "charger_escape_b" {
  "racecar_anims/charger_escape_b"
  { event '''AE_CL_BODYGROUP_SET_VALUE 0  "travel 0"''' }  // On frame 0  Sets model to show body 0 (first variant) of the "Travel" Bodygroup. Being "delorean_Notravel.smd"
  { event '''AE_CL_BODYGROUP_SET_VALUE 50  "travel 1"''' }  // On frame 50  Sets model to show body 1 of the same bodygroup. Being "Delorean_Yestravel.smd"
  { event '''AE_CL_BODYGROUP_SET_VALUE 220 "travel 2"''' }  // On frame 220 Sets model to show body 2 of the same bodygroup. Being "Delorean_brokentravel"
  }
 
  $bodygroup "Bodygroup_1"
  {
  blank // Disabled state
  studio "myBodyGroup" // Enabled  state
  }
  $sequence "Sequence_1" {
  "anims/Thing_1"
  { event '''AE_CL_ENABLE_BODYGROUP 10 "Bodygroup_1"''' }  // On Frame 10 Enables bodygroup_1
  }
   
  $sequence "Sequence_2" {
  "anims/Thing_2"
  { event '''AE_CL_DISABLE_BODYGROUP 50 "Bodygroup_1"''' }  // On Frame 50 Disables bodygroup_1 
  }

Latest revision as of 21:09, 16 July 2025

English (en)Русский (ru)Translate (Translate)

$bodygroup is a QC command available in all Source Source games. It defines a group of meshes that can be turned on or off, or changed entirely. Server code can change their state.

Note.pngNote:Body groups cannot change skeletons or collision models.

Example

This body group allows a weapon to have iron sights, laser sights, or no sights at all:

$bodygroup sights
{
	studio "ironsights"
	studio "laser_dot"
	blank
}

This body group defines the entire chest region of the model, which spans multiple bones:

$bodygroup chest
{
	studio "chest_with_no_armor"
	studio "chest_with_light_armor"
	studio "chest_with_heavy_armor"
	studio "chest_with_super_armor"
}
Note.pngNote:Since body group polygons never share vertices with the base mesh in Source models, there need not be seams between properly-made components.

Bodygroups in Level of Detail Meshes

Using Level of Detail meshes - especially for high-poly geometry - is highly recommended. Body groups can be used in $lod strings in the same method as normal geometry meshes:

$lod 12
{
	replacemodel "chest_with_no_armor" "chest_with_no_armor_lod1"
	replacemodel "chest_with_light_armor" "chest_with_light_armor_lod1"
	replacemodel "chest_with_heavy_armor" "chest_with_heavy_armor_lod1"
	replacemodel "chest_with_super_armor" "chest_with_super_armor_lod1"
}

$lod 18
{
	replacemodel "chest_with_no_armor" "chest_with_no_armor_lod2"
	replacemodel "chest_with_light_armor" "chest_with_light_armor_lod2"
	replacemodel "chest_with_heavy_armor" "chest_with_heavy_armor_lod2"
	replacemodel "chest_with_super_armor" "chest_with_super_armor_lod2"
}
$shadowlod
{
	replacemodel "chest_with_no_armor" "chest_with_no_armor_lod2"
	replacemodel "chest_with_light_armor" "chest_with_light_armor_lod2"
	replacemodel "chest_with_heavy_armor" "chest_with_heavy_armor_lod2"
	replacemodel "chest_with_super_armor" "chest_with_super_armor_lod2"
}

Programming

To change a body group's state:

int BodyGroup_Sights = FindBodygroupByName("sights"); // calculate this value once
SetBodygroup( BodyGroup_Sights , 1 ); // laser dot

By default, CBaseAnimating supports 4,294,967,296 combinations (32 bits), and CBaseViewModel supports 256 (8 bits). You can raise either of these by editing the relevant SendProp for m_nBody.

To calculate how many combinations you need, multiply the size of all your bodygroups together. The examples on this page total 3 * 4 = 12...but add two more groups the same size and you're up at 144. The figure grows exponentially.

Switching bodygroup via $Sequence

It is possible to swap bodygroups during sequences, using the following event:

  • AE_CL_BODYGROUP_SET_VALUE <frame> "<bodyGroupName> <body>"
    Note.pngNote:So far only tested in Left 4 Dead 2 and Team Fortress 2. Seems to be fine but certain functions in the game can restart it to default making it somewhat "buggy".
  • AE_CL_ENABLE_BODYGROUP <frame> "<bodyGroupName>"
  • AE_CL_DISABLE_BODYGROUP <frame> "<bodyGroupName>"


Examples:

 $bodygroup "travel"
 {
 	studio "delorean_Notravel"
 	studio "Delorean_Yestravel"
 	studio "Delorean_brokentravel"
 }
 $sequence "charger_escape_b" {
 	"racecar_anims/charger_escape_b"
 	{ event AE_CL_BODYGROUP_SET_VALUE 0   "travel 0" }  // On frame 0   Sets model to show body 0 (first variant) of the "Travel" Bodygroup. Being "delorean_Notravel.smd"
 	{ event AE_CL_BODYGROUP_SET_VALUE 50  "travel 1" }  // On frame 50  Sets model to show body 1 of the same bodygroup. Being "Delorean_Yestravel.smd"
 	{ event AE_CL_BODYGROUP_SET_VALUE 220 "travel 2" }  // On frame 220 Sets model to show body 2 of the same bodygroup. Being "Delorean_brokentravel"
 }
 $bodygroup "Bodygroup_1" 
 {
 	blank			 // Disabled state
 	studio "myBodyGroup" // Enabled  state
 }
 $sequence "Sequence_1" {
 	"anims/Thing_1"
 	{ event AE_CL_ENABLE_BODYGROUP 10 "Bodygroup_1" }  // On Frame 10 Enables bodygroup_1 
 }
   
 $sequence "Sequence_2" {
 	"anims/Thing_2"
 	{ event AE_CL_DISABLE_BODYGROUP 50 "Bodygroup_1" }  // On Frame 50 Disables bodygroup_1  
 }