Viewmodel Blood Splatter Overlay: Difference between revisions
m (Replaced "WL_Feet" with "WL_Waist", so the blood doesn't instantly clean when touching *any* water. Now it only does it when fully underwater + added a note to the external links section.) |
GamerDude27 (talk | contribs) m (Link to "material proxies" page) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[File:viewmodel blood proxy system.jpg|440px|thumb|right|<center>'''Example'''</center>]] | |||
== Introduction == | == Introduction == | ||
In this tutorial, we'll be setting up a simple material proxy system that we can use to overlay a blood detail texture onto our viewmodel based on close-quarters combat. | In this tutorial, we'll be setting up a simple [[Material_proxies|material proxy system]] that we can use to overlay a blood detail texture onto our viewmodel based on close-quarters combat. | ||
The final results that can be made from this are, for example, hands and weapons covered in goo, acid, blood, water, animated raindrop water normals, and many more visual design elements. | The final results that can be made from this are, for example, hands and weapons covered in goo, acid, blood, water, animated raindrop water normals, and many more visual design elements. | ||
Line 7: | Line 9: | ||
== Requirements == | == Requirements == | ||
* A | * A {{src13|3.1}} engine branch mod. | ||
* Beginner/Intermediate knowledge of C++. | * Beginner/Intermediate knowledge of C++. | ||
* Knowledge and familiarity with textures and materials. | * Knowledge and familiarity with textures and materials. | ||
Line 22: | Line 24: | ||
Which you'll put into | Which you'll put into {{path|<src code directory>/src/game/client/}} | ||
=== c_baseplayer.h === | === c_baseplayer.h === | ||
In | In {{path|src/game/client/c_baseplayer|h}}, inside the <code>public:</code> section, add the following line: | ||
< | <syntaxhighlight lang=cpp> | ||
bool m_bShouldDrawBloodOverlay; | bool m_bShouldDrawBloodOverlay; | ||
</ | </syntaxhighlight> | ||
=== c_baseplayer.cpp === | === c_baseplayer.cpp === | ||
In | In {{path|src/game/client/c_baseplayer|cpp}}, below <code>RecvPropString( RECVINFO(m_szLastPlaceName) ),</code> add: | ||
< | <syntaxhighlight lang=cpp> | ||
RecvPropBool( RECVINFO( m_bShouldDrawBloodOverlay ) ), | RecvPropBool( RECVINFO( m_bShouldDrawBloodOverlay ) ), | ||
</ | </syntaxhighlight> | ||
Then in the constructor, below <code>ListenForGameEvent( "base_player_teleported" );</code>, add: | Then in the constructor, below <code>ListenForGameEvent( "base_player_teleported" );</code>, add: | ||
< | <syntaxhighlight lang=cpp> | ||
m_bShouldDrawBloodOverlay = false; | m_bShouldDrawBloodOverlay = false; | ||
</ | </syntaxhighlight> | ||
=== player.h === | === player.h === | ||
In | In {{path|src/game/server/player|h}}, inside the <code>public:</code> section, add the following line: | ||
< | <syntaxhighlight lang=cpp> | ||
CNetworkVar( bool, m_bShouldDrawBloodOverlay ); // Have we been hit or have blood splatted on us? | CNetworkVar( bool, m_bShouldDrawBloodOverlay ); // Have we been hit or have blood splatted on us? | ||
</ | </syntaxhighlight> | ||
=== player.cpp === | === player.cpp === | ||
In | In {{path|src/game/server/player|cpp}}, somewhere inside of <code>BEGIN_DATADESC( CBasePlayer )</code>, add: | ||
< | <syntaxhighlight lang=cpp> | ||
DEFINE_FIELD( m_bShouldDrawBloodOverlay, FIELD_BOOLEAN ), | DEFINE_FIELD( m_bShouldDrawBloodOverlay, FIELD_BOOLEAN ), | ||
</ | </syntaxhighlight> | ||
Inside the constructor and below <code>m_bitsDamageType = 0;</code>, add: | Inside the constructor and below <code>m_bitsDamageType = 0;</code>, add: | ||
< | <syntaxhighlight lang=cpp> | ||
m_bShouldDrawBloodOverlay = false; | m_bShouldDrawBloodOverlay = false; | ||
</ | </syntaxhighlight> | ||
Then inside <code>IMPLEMENT_SERVERCLASS_ST( CBasePlayer, DT_BasePlayer )</code>, below <code>SendPropString (SENDINFO(m_szLastPlaceName) ),</code>, add: | Then inside <code>IMPLEMENT_SERVERCLASS_ST( CBasePlayer, DT_BasePlayer )</code>, below <code>SendPropString (SENDINFO(m_szLastPlaceName) ),</code>, add: | ||
< | <syntaxhighlight lang=cpp> | ||
SendPropBool( SENDINFO(m_bShouldDrawBloodOverlay) ), | SendPropBool( SENDINFO(m_bShouldDrawBloodOverlay) ), | ||
</ | </syntaxhighlight> | ||
=== basecombatcharacter.cpp === | === basecombatcharacter.cpp === | ||
In | In {{path|src/game/server/basecombatcharacter|cpp}}, inside the <code>OnTakeDamage_Alive( const CTakeDamageInfo &info )</code> function above <code>return 1;</code>, add: | ||
< | <syntaxhighlight lang=cpp> | ||
// Handle the viewmodel blood splatter overlay effect here: | // Handle the viewmodel blood splatter overlay effect here: | ||
if ( ( info.GetDamageType() & ( DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB | DMG_BUCKSHOT ) ) ) | if ( ( info.GetDamageType() & ( DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB | DMG_BUCKSHOT ) ) ) | ||
Line 85: | Line 87: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
== The Materials == | == The Materials == | ||
Line 91: | Line 93: | ||
=== Viewmodel VMTs === | === Viewmodel VMTs === | ||
Now you'll have to edit every single viewmodel '''.vmt''' to include the following snippet of code: | Now you'll have to edit every single viewmodel [[VMT|'''.vmt''']] to include the following snippet of code: | ||
< | <syntaxhighlight lang="text" highlight=5-15> | ||
"VertexLitGeneric" | "VertexLitGeneric" | ||
{ | { | ||
Line 109: | Line 111: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
Notice how we're calling for | Notice how we're calling for {{path|materials/detail/blood_detail|vtf}}, this is the blood detail texture that gets placed on top of our viewmodel. | ||
== Conclusion == | == Conclusion == | ||
Now all that remains is making your blood detail texture for this. Still, for convenience/testing sake, you can download the included placeholder texture found in the "External links" section below. | Now all that remains is making your blood detail texture for this. Still, for convenience/testing sake, you can download the included placeholder texture found in the [[#External links|"External links"]] section below. | ||
And that's all there is to it. If set up correctly, you should now be able to see the blood splatter texture on your viewmodel based on the snippet of code we placed into | And that's all there is to it. If set up correctly, you should now be able to see the blood splatter texture on your viewmodel based on the snippet of code we placed into {{path|basecombatcharacter|cpp}}. | ||
== Additional Functionality (Optional) == | == Additional Functionality (Optional) == | ||
If you want to be able to clean off the blood by going into water, head over to | If you want to be able to clean off the blood by going into water, head over to {{path|player|cpp}} and find the <code>WaterMove()</code> function. | ||
Inside it, at the bottom, but before <code>UpdateUnderwaterState();</code> add this: | Inside it, at the bottom, but before <code>UpdateUnderwaterState();</code> add this: | ||
< | <syntaxhighlight lang=cpp> | ||
if ( GetWaterLevel() > WL_Waist ) | if ( GetWaterLevel() > WL_Waist ) | ||
m_bShouldDrawBloodOverlay = false; | m_bShouldDrawBloodOverlay = false; | ||
</ | </syntaxhighlight> | ||
And if you want to be able to clean off the blood when consuming a health kit, find the <code>TakeHealth( float flHealth, int bitsDamageType )</code> function and add this inside of it: | And if you want to be able to clean off the blood when consuming a health kit, find the <code>TakeHealth( float flHealth, int bitsDamageType )</code> function and add this inside of it: | ||
< | <syntaxhighlight lang=cpp> | ||
m_bShouldDrawBloodOverlay = false; | m_bShouldDrawBloodOverlay = false; | ||
</ | </syntaxhighlight> | ||
== External links == | == External links == | ||
[https://mega.nz/file/ | [https://mega.nz/file/Z4FWiCqZ#XADDJemzg94BkV6B-6EAdYlUIv2Es0yx4mSIde4ZA8o Download BloodDetailTexture.rar] - A placeholder blood detail texture by [[User:GamerDude27|Ian B.]] | ||
[[Category:Programming]] | [[Category:Programming]] | ||
[[Category:Tutorials]] | [[Category:Tutorials]] | ||
[[Category:Free source code]] | [[Category:Free source code]] |
Latest revision as of 12:03, 28 September 2025
Introduction
In this tutorial, we'll be setting up a simple material proxy system that we can use to overlay a blood detail texture onto our viewmodel based on close-quarters combat.
The final results that can be made from this are, for example, hands and weapons covered in goo, acid, blood, water, animated raindrop water normals, and many more visual design elements.
Requirements
- A Source 2013 engine branch mod.
- Beginner/Intermediate knowledge of C++.
- Knowledge and familiarity with textures and materials.
What You Will Learn
- Creating a new material proxy system using the $detail parameter.
- Creating an overlay of blood onto a viewmodel after shooting flesh or blood materials (NPCs included, of course) at close quarters.
The Implementation
Before starting, we'll need this file:
Which you'll put into <src code directory>/src/game/client/
c_baseplayer.h
In src/game/client/c_baseplayer.h
, inside the public:
section, add the following line:
bool m_bShouldDrawBloodOverlay;
c_baseplayer.cpp
In src/game/client/c_baseplayer.cpp
, below RecvPropString( RECVINFO(m_szLastPlaceName) ),
add:
RecvPropBool( RECVINFO( m_bShouldDrawBloodOverlay ) ),
Then in the constructor, below ListenForGameEvent( "base_player_teleported" );
, add:
m_bShouldDrawBloodOverlay = false;
player.h
In src/game/server/player.h
, inside the public:
section, add the following line:
CNetworkVar( bool, m_bShouldDrawBloodOverlay ); // Have we been hit or have blood splatted on us?
player.cpp
In src/game/server/player.cpp
, somewhere inside of BEGIN_DATADESC( CBasePlayer )
, add:
DEFINE_FIELD( m_bShouldDrawBloodOverlay, FIELD_BOOLEAN ),
Inside the constructor and below m_bitsDamageType = 0;
, add:
m_bShouldDrawBloodOverlay = false;
Then inside IMPLEMENT_SERVERCLASS_ST( CBasePlayer, DT_BasePlayer )
, below SendPropString (SENDINFO(m_szLastPlaceName) ),
, add:
SendPropBool( SENDINFO(m_bShouldDrawBloodOverlay) ),
basecombatcharacter.cpp
In src/game/server/basecombatcharacter.cpp
, inside the OnTakeDamage_Alive( const CTakeDamageInfo &info )
function above return 1;
, add:
// Handle the viewmodel blood splatter overlay effect here:
if ( ( info.GetDamageType() & ( DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB | DMG_BUCKSHOT ) ) )
{
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if ( pPlayer == this )
pPlayer->m_bShouldDrawBloodOverlay = true;
pPlayer = ToBasePlayer( info.GetAttacker() );
if ( pPlayer && ( this->BloodColor() != BLOOD_COLOR_MECH ) )
{
if ( pPlayer->GetAbsOrigin().DistTo( this->GetAbsOrigin() ) < 200.0f )
pPlayer->m_bShouldDrawBloodOverlay = true;
}
}
The Materials
Viewmodel VMTs
Now you'll have to edit every single viewmodel .vmt to include the following snippet of code:
"VertexLitGeneric"
{
...
"$detail" "detail/blood_detail"
"$detailblendmode" "2"
"$detailblendfactor" "0.0"
"$detailscale" "1.0"
"Proxies"
{
"BloodyTexture"
{
}
}
}
Notice how we're calling for materials/detail/blood_detail.vtf
, this is the blood detail texture that gets placed on top of our viewmodel.
Conclusion
Now all that remains is making your blood detail texture for this. Still, for convenience/testing sake, you can download the included placeholder texture found in the "External links" section below.
And that's all there is to it. If set up correctly, you should now be able to see the blood splatter texture on your viewmodel based on the snippet of code we placed into basecombatcharacter.cpp
.
Additional Functionality (Optional)
If you want to be able to clean off the blood by going into water, head over to player.cpp
and find the WaterMove()
function.
Inside it, at the bottom, but before UpdateUnderwaterState();
add this:
if ( GetWaterLevel() > WL_Waist )
m_bShouldDrawBloodOverlay = false;
And if you want to be able to clean off the blood when consuming a health kit, find the TakeHealth( float flHealth, int bitsDamageType )
function and add this inside of it:
m_bShouldDrawBloodOverlay = false;
External links
Download BloodDetailTexture.rar - A placeholder blood detail texture by Ian B.