Importing CSS Weapons Into HL2: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (typos & minor tidy (still needs _lots_ of cleanup done))
(Rewrite Template:Lang to Template:LanguageBar. This action was performed by a bot.)
 
(19 intermediate revisions by 10 users not shown)
Line 1: Line 1:
{{cleanup}} {{tutpov}}
{{LanguageBar|Importing_CSS_Weapons_Into_HL2}}
{{cleanup}}{{pov}}


(There will be a video tutorial soon for implementing your own custom player models and importing weapons)
{{tip|The source code for a {{mapbase|4}} mod that achieves this is also available.}}
'''Update 9th Jan 14:''' Okay so I wrote this original monstrosity nearly 9 years ago (holy hell) and it was very much out of date and untidy, I've gone through and removed anything that is no longer useful and had a general tidy up. This now conforms with the latest 2013 SDK.


== Requirements ==


Update 10th Nov 07: I did actually finish that above video tutorial nearly 2 years ago, ill try to find it as it may still be useful to some people.
*A Source mod running on {{src13|3.1}} (or {{src07|3.1}})
*Knowledge of C++


= Model Editing =


So here's the solution, I'll try to make it as informative as possible:
{{Note|If your mod is based on the 2013 SDK, CSS model models will work out of the box without any model editing, just a little bit of coding is required to remove/fix the things in the other sections.}}


'''Requirements:'''
= Fine-Tuning the Model =


*Cannonfodder's [[Mdldecompiler|MDL Decompiler]]
Once you have both your v_ and w_ models set up you will need to assign the models to a weapon using its weapon script file. Locate your new weapons script file (e.g. {{file|weapon_357|txt}}) inside your mod's {{file|scripts/}} folder.
*Ability to Compile the Source SDK


== Importing the weapon ==
Now to fix the issue of CSS weapons only displaying on the left side of the screen we can do the following.


For this tutorial we're going to use the v_pist_deagle.mdl from Counter-Strike.
Inside the weapon script file, add these two lines:
<pre>
"BuiltRightHanded" "0"
"AllowFlipping"    "1"
</pre>


Start by installing the MDL Decompiler to your sourcesdk/bin directory which can be found in C:\Program Files\Steam\SteamApps\USERNAME\sourcesdk\bin if you installed to Steam to the default location.
This will send information to the Client regarding the {{command|cl_righthand}} command, which we will enable next.


Open the Source SDK via the Steam Games Menu and select your mod in the drop down list and open the Half Life Model Viewer, this tool will become very useful for checking you have the model installed correctly. Now you can close the SDK menu.  
In {{file|c_baseviewmodel|cpp}}, at around line 30, find the line that looks like this and simply comment out the <code>#ifdef</code> block like so:
<source lang=cpp highlight=1,3>
//#ifdef CSTRIKE_DLL
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
//#endif 
</source>


Install or Extract your CSS model to your Mod location the same way that you would install a custom model for Counter-Strike and then open MDL Decompiler, once open you can select the model you want to decompile, in this case 'v_pist_deagle.mdl' located in the models/weapons directory and then select the Output directory e.g. C:\Documents and Settings\Administrator\Desktop\Decompiled Models. Now select 'Extract' and you will receive two messages telling you that 1, the Model is loaded and 2, the smds have been dumped in your output directory, all is well.  
Then, go to line 173 and comment out these lines as follows:
<source lang=cpp highlight=1,9>
//#ifdef CSTRIKE_DLL
// If cl_righthand is set, then we want them all right-handed.
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
if ( pWeapon )
{
const FileWeaponInfo_t *pInfo = &pWeapon->GetWpnData();
return pInfo->m_bAllowFlipping && pInfo->m_bBuiltRightHanded != cl_righthand.GetBool();
}
//#endif
</source>
This will enable the <code>cl_righthand</code> ConVar to be activated and your weapon model will not display on the wrong side of the screen. Now just save and compile.


Go to your output directory and you will find your extracted files, one of these should be a .qc file named by default as mdldecompiler.qc. Open this file up and it should look something like this:
= Particle Muzzle Flashes =


$cd "C:\Documents and Settings\Administrator\Desktop\Decompiled Models"
If you aren't using particle muzzle flashes (which you really should be, they're very pretty!) you may have some issues with the old-style muzzle flashes when using CSS weapons. In that case, you can use the fix below.
$modelname "weapons\v_pist_deagle.mdl"
$model "studio" "ref.smd"
$cdmaterials "models\weapons\V_models\SnuffyColt\"
$cdmaterials "models\weapons\v_models\hands\"
$hboxset "default"
$hbox 0 "Bone L hand" -2.514  -0.983  -1.390  0.161  1.207  1.380
$hbox 0 "Bone L thumb mid" -1.018  -0.737  -0.657  0.197  0.324  0.474
$hbox 0 "L wrist rotate" -2.124  -1.749  -1.530  6.668  1.282  1.464
$hbox 0 "Bone R lowarm" -10.248  -1.668  -1.773  0.000  1.423  1.222
$hbox 0 "Bone R hand" -4.925  -0.924  -1.077  0.000  1.279  1.506
$hbox 0 "Grip" 0.000  -4.447  -1.064  4.508  0.000  0.078
$hbox 0 "Slide" 0.000  -4.235  -1.004  4.558  0.000  0.000
// Model uses material "v_hands.vmt"
// Model uses material "1911b_nogrip.vmt"
// Model uses material "1911.vmt"
$attachment "1" "Barrel" 0.00 -0.00 0.00 rotate 0.00 -0.00 0.00
$attachment "2" "Bullet" -0.90 0.26 0.00 rotate -90.00 0.00 0.00
$surfaceprop "default"
$illumposition -2.167 3.767 -7.538
$sequence idle1 "idle1" ACT_VM_IDLE 1 fps 16.00
$sequence shoot1 "shoot1" ACT_VM_PRIMARYATTACK 1 fps 27.00 {
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
}
$sequence shoot2 "shoot2" ACT_VM_PRIMARYATTACK 1 fps 27.00 {
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
}
$sequence shoot_empty "shoot_empty" ACT_VM_DRYFIRE 1 fps 27.00 {
  { event 5001 0 "21" }
}
$sequence reload "reload" ACT_VM_RELOAD 1 fps 35.00 {
  { event 5004 8 "weapons/deagle/clipout.wav" }
  { event 5004 45 "weapons/deagle/clipin.wav" }
  { event 5004 69 "weapons/deagle/1911slideforward.wav" }
}
$sequence draw "draw" ACT_VM_DRAW 1 fps 50.00 {
  { event 5004 18 "weapons/deagle/1911slideback.wav" }
  { event 5004 33 "weapons/deagle/1911slideforward.wav" }


There are a few things you need to do clean the file up a bit. We can delete all of the $hbox lines as they are not really needed.
In {{file|c_baseanimating|cpp}}, inside the <code>FireObsoleteEvent( ... )</code> function at around line 4197 (after the big switch statement), comment out the following marked code and insert this new piece of code (also marked) like so:
Once you have done this rename the $modelname "weapons\v_pist_deagle.mdl" line to what weapon you want it to replace in HL2 for example: $modelname "weapons\v_357.mdl". As for the $cd lines, you do not need to change this directory unless you have moved the original texture files for the model in question, im assuming you kept the directory the same. If not, just change it to suit where you folders are located. Ok, so now onto the more difficult parts. First of all we need to add rotate -90 in all of the $sequence lines like so:
<source lang=cpp highlight=3,8,10-22>
if ( iAttachment != -1 && m_Attachments.Count() > iAttachment )
{
/*
GetAttachment( iAttachment+1, attachOrigin, attachAngles );
int entId = render->GetViewEntity();
ClientEntityHandle_t hEntity = ClientEntityList().EntIndexToHandle( entId );
tempents->MuzzleFlash( attachOrigin, attachAngles, atoi( options ), hEntity, bFirstPerson );
*/


$sequence draw "draw" ACT_VM_DRAW 1 rotate -90 fps 50.00 {  
if ( input->CAM_IsThirdPerson() )
  { event 5004 18 "weapons/deagle/1911slideback.wav" }  
{
  { event 5004 33 "weapons/deagle/1911slideforward.wav" }  
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
pWeapon->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
}
else
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
CBaseViewModel *vm = pPlayer->GetViewModel();
vm->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
engine->GetViewAngles( attachAngles );
}
g_pEffects->MuzzleFlash( attachOrigin, attachAngles, 1.0, MUZZLEFLASH_TYPE_DEFAULT );
}
</source>


Repeat this for all of the $sequence lines and then we need to add a line to the sequences which include a firing sequence like this line for example:  
Go to {{file|fx|cpp}}, under the statement <code>pParticle->m_vecVelocity.Init();</code> in <code>FX_MuzzleEffect</code>, place the following code:
<source lang=cpp>
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
Vector velocity = pPlayer->GetLocalVelocity();
pParticle->m_vecVelocity += velocity;
</source>


$sequence shoot1 "shoot1" ACT_VM_PRIMARYATTACK 1 rotate -90 fps 27.00 {
= Recoil Animation Fix =
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
}
$sequence shoot2 "shoot2" ACT_VM_PRIMARYATTACK 1 rotate -90 fps 27.00 {
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }


We need to add to this line a muzzle flash sequence, this is relatively simple and shouldn't take to long. There are a few different muzzle flashes available to us but for this gun were going to take the muzzle flash from the .357 and apply it to the deagle, the muzzle flash script looks like this:
Ever seen the CSS recoil animation choking up while shooting at a high fire rate? This is how to fix that.


  { event AE_MUZZLEFLASH 0 "357 MUZZLE" }  
Open up the weapon(s) that use a CSS viewmodel (e.g. {{file|weapon_pistol|cpp}}). Then scroll down to the <code>GetPrimaryAttackActivity( void )</code> function and replace everything inside of it with the following:
<source lang=cpp>
return ACT_VM_PRIMARYATTACK;
</source>


We need to add this line at the bottom of each firing sequence:
= Shell Casing Ejection =


$sequence shoot1 "shoot1" ACT_VM_PRIMARYATTACK 1 rotate -90 fps 27.00 {
You'll probably notice that your newly imported CSS weapons don't eject any shell casings like your stock HL2 weapons, so let's fix that.
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
  { event AE_MUZZLEFLASH 0 "357 MUZZLE" }
}
$sequence shoot2 "shoot2" ACT_VM_PRIMARYATTACK 1 rotate -90 fps 27.00 {
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
  { event AE_MUZZLEFLASH 0 "357 MUZZLE" }


The .qc file is now ready to go and be compiled, for reference purposes your .qc file should now look this this:  
In your Client project {{file|src/game/client/}} add a new file called {{file|fx_cs_weaponfx|cpp}} and paste the following into it:
<source lang=cpp>
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Game-specific impact effect hooks
//
//=============================================================================//


$cd "C:\Documents and Settings\Administrator\Desktop\Decompiled Models"
#include "cbase.h"
$modelname "weapons\v_357.mdl"
#include "fx_impact.h"
$model "studio" "ref.smd"
#include "tempent.h"
$cdmaterials "models\weapons\V_models\SnuffyColt\"
#include "c_te_effect_dispatch.h"
$cdmaterials "models\weapons\v_models\hands\"
#include "c_te_legacytempents.h"
// Model uses material "v_hands.vmt"
// Model uses material "1911b_nogrip.vmt"
// Model uses material "1911.vmt"
$attachment "1" "Barrel" 0.00 -0.00 0.00 rotate 0.00 -0.00 0.00
$attachment "2" "Bullet" -0.90 0.26 0.00 rotate -90.00 0.00 0.00
$surfaceprop "default"
$illumposition -2.167 3.767 -7.538
$sequence idle1 "idle1" ACT_VM_IDLE 1 rotate -90 fps 16.00
$sequence shoot1 "shoot1" ACT_VM_PRIMARYATTACK 1 rotate -90 fps 27.00 {
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
  { event AE_MUZZLEFLASH 0 "357 MUZZLE" }
}
$sequence shoot2 "shoot2" ACT_VM_PRIMARYATTACK 1 rotate -90 fps 27.00 {
  { event 5001 0 "1" }
  { event AE_CLIENT_EFFECT_ATTACH 0 "EjectBrass_9mm 2 100" }
  { event AE_MUZZLEFLASH 0 "357 MUZZLE" }
}
$sequence shoot_empty "shoot_empty" ACT_VM_DRYFIRE 1 rotate -90 fps 27.00 {
  { event 5001 0 "21" }
}
$sequence reload "reload" ACT_VM_RELOAD 1 rotate -90 fps 35.00 {
  { event 5004 8 "weapons/deagle/clipout.wav" }
  { event 5004 45 "weapons/deagle/clipin.wav" }
  { event 5004 69 "weapons/deagle/1911slideforward.wav" }
}
$sequence draw "draw" ACT_VM_DRAW 1 rotate -90 fps 50.00 {
  { event 5004 18 "weapons/deagle/1911slideback.wav" }
  { event 5004 33 "weapons/deagle/1911slideforward.wav" }


To compile the .qc copy it to the sourcesdk/bin folder and open it with studiomdl.exe with should already be in the bin folder. A command prompt will appear and it will begin compiling the weapon into your mod.
//-----------------------------------------------------------------------------
// Purpose: Handle weapon effect callbacks
//-----------------------------------------------------------------------------
void CStrike_EjectBrass( int shell, const CEffectData &data )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();


Now you should check its working in the game, so to do this go back to the Half-Life Model Viewer and select 'File, Load Model' and select the 'v_357.mdl' found in the weapons folder as this is where we have compiled our custom weapon.
if ( !pPlayer )
return;


The model should load with gun textures but you'll notice that the hands are untextured and in a strangely appealing checkered pattern, but as funky as it is, this is because we haven't installed the hand textures yet. To do this extract the hands materials found in counter strike source shared.gcf using GCFScape and place the 'hand' folder into your mod directory (C:\Program Files\Steam\SteamApps\sourcemods\MODNAME\materials\models\weapons\hands) now refresh Model Viewer by pressing F5 and viola! The Hands are textured.
tempents->CSEjectBrass( data.m_vOrigin, data.m_vAngles, data.m_fFlags, shell, pPlayer );
}


-------------------------------------------
void CStrike_FX_EjectBrass_9mm_Callback( const CEffectData &data )
'''SECTION 2 - FINE TUNING THE MODEL'''
{
-------------------------------------------
CStrike_EjectBrass( CS_SHELL_9MM, data );
}


This section will explore fine tuning the model and getting rid of those pesky bugs!
void CStrike_FX_EjectBrass_57_Callback( const CEffectData &data )
{
CStrike_EjectBrass( CS_SHELL_57, data );
}


Now that your model is in game you will have noticed some 'bugs' with the model.. One very annoying bug is that the weapon seems to be stuck on the left hand side, but there is a simple and easy fix for this:
void CStrike_FX_EjectBrass_12Gauge_Callback( const CEffectData &data )
{
CStrike_EjectBrass( CS_SHELL_12GAUGE, data );
}


First things first open your weapon script file eg. weapon_357.txt found in your Mods Script directory (C:\Program Files\Steam\SteamApps\sourcemods\MODNAME\scripts)  
void CStrike_FX_EjectBrass_556_Callback( const CEffectData &data )
{
CStrike_EjectBrass( CS_SHELL_556, data );
}


When you open it you will find something that looks like this:
void CStrike_FX_EjectBrass_762Nato_Callback( const CEffectData &data )
{
CStrike_EjectBrass( CS_SHELL_762NATO, data );
}


// 357
void CStrike_FX_EjectBrass_338Mag_Callback( const CEffectData &data )
WeaponData
{
{
CStrike_EjectBrass( CS_SHELL_338MAG, data );
// Weapon data is loaded by both the Game and Client DLLs.
}
"printname"  "#HL2_357Handgun"
"viewmodel"  "models/weapons/v_357.mdl"
"playermodel"  "models/weapons/w_357.mdl"
"anim_prefix"  "python"
"bucket"  "1"
"bucket_position" "1"
"clip_size"  "6"
"default_clip"  "6"
"primary_ammo"  "357"
"secondary_ammo" "None"
"weight"  "7"
"item_flags"  "0"
"damage"  "75"
// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)  
SoundData
{  
  "empty"  "Weapon_Pistol.Empty"
  "single_shot" "Weapon_357.Single"
}
// Weapon Sprite data is loaded by the Client DLL.
TextureData
{
  "weapon"
  {
    "font"  "WeaponIcons"
    "character" "e"
  }  
  "weapon_s"
  {
    "font"  "WeaponIconsSelected"
    "character" "e"
  }
  "ammo"
  {
    "font"  "WeaponIcons"
    "character" "q"
  }
  "crosshair"
  {
    "font"  "Crosshairs"
    "character" "Q"
  }
  "autoaim"
  {
    "file"  "sprites/crosshairs"
    "x"  "0"
    "y"  "48"
    "width"  "24"
    "height" "24"
  }
}
Some small changes you can make are things such as the name of the weapon (as shown in the HUD) to do this just edit the "#HL2_357Handgun" line to
whatever your guns called. In this case "Desert Eagle". Other changes can include clip size, damage and bullet type. So just play with these settings
till you achieve your desired effect.


There are a few quick changes that you need to make, to fix the Left-Hand View Model problem there are 2 Steps you need to take; The first step can be done in the script file but the other requires you to edit the SDK code itself. The first step you need to make is add a few lines to the script above:
DECLARE_CLIENT_EFFECT( "EjectBrass_9mm", CStrike_FX_EjectBrass_9mm_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_12Gauge", CStrike_FX_EjectBrass_12Gauge_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_57", CStrike_FX_EjectBrass_57_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_556", CStrike_FX_EjectBrass_556_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_762Nato", CStrike_FX_EjectBrass_762Nato_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_338Mag", CStrike_FX_EjectBrass_338Mag_Callback );
</source>


Scroll down to where it says "item_flags" "0" and just below it add:  
Now head over to '''c_te_legacytempents.h''' and you'll find two instances of this block <code>#if defined( CSTRIKE_DLL ) || defined( SDK_DLL )</code>, and all you have to do is comment them out like so:
<source lang=cpp highlight=1,11,15,22>
//#if defined( CSTRIKE_DLL ) || defined( SDK_DLL )
enum
{
CS_SHELL_9MM = 0,
CS_SHELL_57,
CS_SHELL_12GAUGE,
CS_SHELL_556,
CS_SHELL_762NATO,
CS_SHELL_338MAG
};
//#endif


"BuiltRightHanded" "0"
...
"AllowFlipping" "1" 


This will allow the cl_righthand command to work (Set cl_righthand to 1). But before the cl_righthand command will be recognised by the game you must edit the Source Code; go to your Mods Src folder (C:\MODNAME\src\cl_dll) and open 'c_baseviewmodel.cpp' and scroll down to line 25 and find the line that looks like this:
//#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
struct model_t *m_pCS_9MMShell;
struct model_t *m_pCS_57Shell;
struct model_t *m_pCS_12GaugeShell;
struct model_t *m_pCS_556Shell;
struct model_t *m_pCS_762NATOShell;
struct model_t *m_pCS_338MAGShell;
//#endif
</source>


#ifdef CSTRIKE_DLL
And finally, head over to '''c_te_legacytempents.cpp''' where we'll comment out five more <code>#ifdef</code> blocks.
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
#endif 


And simply comment out the top and bottom lines like so:  
The first block will be in the <code>C_LocalTempEntity</code> constructor:
<source lang=cpp highlight=1,7>
//#if defined( CSTRIKE_DLL ) || defined (SDK_DLL )


// #ifdef CSTRIKE_DLL
#define TE_RIFLE_SHELL 1024
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
#define TE_PISTOL_SHELL 2048
// #endif 
#define TE_SHOTGUN_SHELL 4096


And go to line 173 and comment lines like this:
//#endif
<code>
</source>
// #ifdef CSTRIKE_DLL
// If cl_righthand is set, then we want them all right-handed.
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
if ( pWeapon )
{
const FileWeaponInfo_t *pInfo = &pWeapon->GetWpnData();
return pInfo->m_bAllowFlipping && pInfo->m_bBuiltRightHanded != cl_righthand.GetBool();
}
// #endif
</code>
This will allow the cl_righthand cvar to be used to change the weapon side. Now save and compile.


Ok, so the viewmodel bug is fixed. But theres still one more issue that needs to be resolved. Thats the sound issues; as you probably have realised the sounds are not that of the Deagle but instead are still the .357 sounds, there is a real easy way to fix this. Extract the games_sound_weapons.txt file from the CSS GCF (Its in the scripts folder) and Copy the text from inside the file. Open up the games_sound_weapons.txt from your mod and copy the text into the bottom of that file (DON'T OVERWRITE WHAT IS ALREADY THERE).
The second one will be in the <code>PlaySound ( C_LocalTempEntity *pTemp, float damp )</code> function:
<source lang=cpp highlight=1,20>
//#ifdef CSTRIKE_DLL


Now in your weapon_357.txt file you can change these lines:
case TE_PISTOL_SHELL:
{
soundname = "Bounce.PistolShell";
}
break;


// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)
case TE_RIFLE_SHELL:
SoundData
{
{  
soundname = "Bounce.RifleShell";
  "empty" "Weapon_Pistol.Empty"  
}
  "single_shot" "Weapon_357.Single"
break;


Find the relative sounds from the games_sound_weapons.txt file and replace the above lines with the deagle sounds like so:
case TE_SHOTGUN_SHELL:
{
soundname = "Bounce.ShotgunShell";
}
break;
//#endif
</source>


// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)  
The third one will be in the <code>LevelInit()</code> function:
SoundData
<source lang=cpp hightlight=1,8>
{
//#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
  "empty" "Default.ClipEmpty_Pistol"  
m_pCS_9MMShell = (model_t *)engine->LoadModel( "models/Shells/shell_9mm.mdl" );
  "single_shot" "Weapon_DEagle.Single"  
m_pCS_57Shell = (model_t *)engine->LoadModel( "models/Shells/shell_57.mdl" );
        }
m_pCS_12GaugeShell = (model_t *)engine->LoadModel( "models/Shells/shell_12gauge.mdl" );
m_pCS_556Shell = (model_t *)engine->LoadModel( "models/Shells/shell_556.mdl" );
m_pCS_762NATOShell = (model_t *)engine->LoadModel( "models/Shells/shell_762nato.mdl" );
m_pCS_338MAGShell = (model_t *)engine->LoadModel( "models/Shells/shell_338mag.mdl" );
//#endif
</source>


Make sure you've copied the sound directory from CSS GCF into your mod folder!
The fourth one will be in the <code>Init (void)</code> function, right below the last one:
<source lang=cpp highlight=1,8>
//#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
m_pCS_9MMShell = NULL;
m_pCS_57Shell = NULL;
m_pCS_12GaugeShell = NULL;
m_pCS_556Shell = NULL;
m_pCS_762NATOShell = NULL;
m_pCS_338MAGShell = NULL;
//#endif
</source>


That should do it! It should all be working... It may not be 100% Bugless but im sure some more tweaking would fix that.
And the last one will be in the <code>CSEjectBrass( ... )</code> function, at the bottom of the file:
<source lang=cpp highlight=1,31>
//#if defined ( CSTRIKE_DLL ) || defined ( SDK_DLL )


Enjoy!
switch( shellType )
-------------------------------------------
{
UPDATE: 10th November 2007
default:
-------------------------------------------
case CS_SHELL_9MM:
hitsound = TE_PISTOL_SHELL;
pModel = m_pCS_9MMShell;
break;
case CS_SHELL_57:
hitsound = TE_PISTOL_SHELL;
pModel = m_pCS_57Shell;
break;
case CS_SHELL_12GAUGE:
hitsound = TE_SHOTGUN_SHELL;
pModel = m_pCS_12GaugeShell;
break;
case CS_SHELL_556:
hitsound = TE_RIFLE_SHELL;
pModel = m_pCS_556Shell;
break;
case CS_SHELL_762NATO:
hitsound = TE_RIFLE_SHELL;
pModel = m_pCS_762NATOShell;
break;
case CS_SHELL_338MAG:
hitsound = TE_RIFLE_SHELL;
pModel = m_pCS_338MAGShell;
break;
}
//#endif
</source>


Hi, I wrote this article about 2 years ago now personally I use another method for importing CSS weapons which is by adding a completely
= Conclusion =
new weapon to the game instead of replacing the existing guns. That said, my new method requires some heavy coding so this tutorial is still
very useful for people who would rather do minimal coding.
 
I hoped this has helped people but Ive noticed over time people have edited certain bits to be wrong. Such as the .qc end result, this is now fixed
and the .qc example is correct.
 
Thank you!
 
FerretyBeast (ferretybeast@hotmail.co.uk)


And that's it for now, enjoy!


[[Category:Tutorials]]
[[Category:Tutorials]]

Latest revision as of 17:25, 18 July 2025

English (en)Русский (ru)Translate (Translate)
Broom icon.png
This article or section needs to be cleaned up to conform to a higher standard of quality.
For help, see the VDC Editing Help and Wikipedia cleanup process. Also, remember to check for any notes left by the tagger at this article's talk page.
Broom icon.png
This article or section should be converted to third person to conform to wiki standards.
Tip.pngTip:The source code for a Mapbase Mapbase mod that achieves this is also available.

Update 9th Jan 14: Okay so I wrote this original monstrosity nearly 9 years ago (holy hell) and it was very much out of date and untidy, I've gone through and removed anything that is no longer useful and had a general tidy up. This now conforms with the latest 2013 SDK.

Requirements

Model Editing

Note.pngNote:If your mod is based on the 2013 SDK, CSS model models will work out of the box without any model editing, just a little bit of coding is required to remove/fix the things in the other sections.

Fine-Tuning the Model

Once you have both your v_ and w_ models set up you will need to assign the models to a weapon using its weapon script file. Locate your new weapons script file (e.g. 🖿weapon_357.txt) inside your mod's 🖿scripts/ folder.

Now to fix the issue of CSS weapons only displaying on the left side of the screen we can do the following.

Inside the weapon script file, add these two lines:

"BuiltRightHanded" "0"
"AllowFlipping"    "1"

This will send information to the Client regarding the cl_righthand command, which we will enable next.

In 🖿c_baseviewmodel.cpp, at around line 30, find the line that looks like this and simply comment out the #ifdef block like so:

//#ifdef CSTRIKE_DLL 
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." ); 
//#endif

Then, go to line 173 and comment out these lines as follows:

//#ifdef CSTRIKE_DLL
	// If cl_righthand is set, then we want them all right-handed.
	CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
	if ( pWeapon )
	{
		const FileWeaponInfo_t *pInfo = &pWeapon->GetWpnData();
		return pInfo->m_bAllowFlipping && pInfo->m_bBuiltRightHanded != cl_righthand.GetBool();
	}
//#endif

This will enable the cl_righthand ConVar to be activated and your weapon model will not display on the wrong side of the screen. Now just save and compile.

Particle Muzzle Flashes

If you aren't using particle muzzle flashes (which you really should be, they're very pretty!) you may have some issues with the old-style muzzle flashes when using CSS weapons. In that case, you can use the fix below.

In 🖿c_baseanimating.cpp, inside the FireObsoleteEvent( ... ) function at around line 4197 (after the big switch statement), comment out the following marked code and insert this new piece of code (also marked) like so:

			if ( iAttachment != -1 && m_Attachments.Count() > iAttachment )
			{
				/*
				GetAttachment( iAttachment+1, attachOrigin, attachAngles );
				int entId = render->GetViewEntity();
				ClientEntityHandle_t hEntity = ClientEntityList().EntIndexToHandle( entId );
				tempents->MuzzleFlash( attachOrigin, attachAngles, atoi( options ), hEntity, bFirstPerson );
				*/

				if ( input->CAM_IsThirdPerson() )
				{
					C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
					pWeapon->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
				}
				else
				{
					C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
					CBaseViewModel *vm = pPlayer->GetViewModel();
					vm->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
					engine->GetViewAngles( attachAngles );
				}
				g_pEffects->MuzzleFlash( attachOrigin, attachAngles, 1.0, MUZZLEFLASH_TYPE_DEFAULT );
			}

Go to 🖿fx.cpp, under the statement pParticle->m_vecVelocity.Init(); in FX_MuzzleEffect, place the following code:

		C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
		Vector velocity = pPlayer->GetLocalVelocity();
		pParticle->m_vecVelocity += velocity;

Recoil Animation Fix

Ever seen the CSS recoil animation choking up while shooting at a high fire rate? This is how to fix that.

Open up the weapon(s) that use a CSS viewmodel (e.g. 🖿weapon_pistol.cpp). Then scroll down to the GetPrimaryAttackActivity( void ) function and replace everything inside of it with the following:

return ACT_VM_PRIMARYATTACK;

Shell Casing Ejection

You'll probably notice that your newly imported CSS weapons don't eject any shell casings like your stock HL2 weapons, so let's fix that.

In your Client project 🖿src/game/client/ add a new file called 🖿fx_cs_weaponfx.cpp and paste the following into it:

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Game-specific impact effect hooks
//
//=============================================================================//

#include "cbase.h"
#include "fx_impact.h"
#include "tempent.h"
#include "c_te_effect_dispatch.h"
#include "c_te_legacytempents.h"

//-----------------------------------------------------------------------------
// Purpose: Handle weapon effect callbacks
//-----------------------------------------------------------------------------
void CStrike_EjectBrass( int shell, const CEffectData &data )
{
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	if ( !pPlayer )
		return;

	tempents->CSEjectBrass( data.m_vOrigin, data.m_vAngles, data.m_fFlags, shell, pPlayer );
}

void CStrike_FX_EjectBrass_9mm_Callback( const CEffectData &data )
{
	CStrike_EjectBrass( CS_SHELL_9MM, data );
}

void CStrike_FX_EjectBrass_57_Callback( const CEffectData &data )
{
	CStrike_EjectBrass( CS_SHELL_57, data );
}

void CStrike_FX_EjectBrass_12Gauge_Callback( const CEffectData &data )
{
	CStrike_EjectBrass( CS_SHELL_12GAUGE, data );
}

void CStrike_FX_EjectBrass_556_Callback( const CEffectData &data )
{
	CStrike_EjectBrass( CS_SHELL_556, data );
}

void CStrike_FX_EjectBrass_762Nato_Callback( const CEffectData &data )
{
	CStrike_EjectBrass( CS_SHELL_762NATO, data );
}

void CStrike_FX_EjectBrass_338Mag_Callback( const CEffectData &data )
{
	CStrike_EjectBrass( CS_SHELL_338MAG, data );
}

DECLARE_CLIENT_EFFECT( "EjectBrass_9mm",		CStrike_FX_EjectBrass_9mm_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_12Gauge",	CStrike_FX_EjectBrass_12Gauge_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_57",			CStrike_FX_EjectBrass_57_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_556",		CStrike_FX_EjectBrass_556_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_762Nato",	CStrike_FX_EjectBrass_762Nato_Callback );
DECLARE_CLIENT_EFFECT( "EjectBrass_338Mag",		CStrike_FX_EjectBrass_338Mag_Callback );

Now head over to c_te_legacytempents.h and you'll find two instances of this block #if defined( CSTRIKE_DLL ) || defined( SDK_DLL ), and all you have to do is comment them out like so:

//#if defined( CSTRIKE_DLL ) || defined( SDK_DLL )
enum
{
	CS_SHELL_9MM = 0,
	CS_SHELL_57,
	CS_SHELL_12GAUGE,
	CS_SHELL_556,
	CS_SHELL_762NATO,
	CS_SHELL_338MAG
};
//#endif

...

//#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
	struct model_t			*m_pCS_9MMShell;
	struct model_t			*m_pCS_57Shell;
	struct model_t			*m_pCS_12GaugeShell;
	struct model_t			*m_pCS_556Shell;
	struct model_t			*m_pCS_762NATOShell;
	struct model_t			*m_pCS_338MAGShell;
//#endif

And finally, head over to c_te_legacytempents.cpp where we'll comment out five more #ifdef blocks.

The first block will be in the C_LocalTempEntity constructor:

//#if defined( CSTRIKE_DLL ) || defined (SDK_DLL )

#define TE_RIFLE_SHELL 1024
#define TE_PISTOL_SHELL 2048
#define TE_SHOTGUN_SHELL 4096

//#endif

The second one will be in the PlaySound ( C_LocalTempEntity *pTemp, float damp ) function:

//#ifdef CSTRIKE_DLL

		case TE_PISTOL_SHELL:
		{
			soundname = "Bounce.PistolShell";
		}
		break;

		case TE_RIFLE_SHELL:
		{
			soundname = "Bounce.RifleShell";
		}
		break;

		case TE_SHOTGUN_SHELL:
		{
			soundname = "Bounce.ShotgunShell";
		}
		break;
//#endif

The third one will be in the LevelInit() function:

//#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
	m_pCS_9MMShell		= (model_t *)engine->LoadModel( "models/Shells/shell_9mm.mdl" );
	m_pCS_57Shell		= (model_t *)engine->LoadModel( "models/Shells/shell_57.mdl" );
	m_pCS_12GaugeShell	= (model_t *)engine->LoadModel( "models/Shells/shell_12gauge.mdl" );
	m_pCS_556Shell		= (model_t *)engine->LoadModel( "models/Shells/shell_556.mdl" );
	m_pCS_762NATOShell	= (model_t *)engine->LoadModel( "models/Shells/shell_762nato.mdl" );
	m_pCS_338MAGShell	= (model_t *)engine->LoadModel( "models/Shells/shell_338mag.mdl" );
//#endif

The fourth one will be in the Init (void) function, right below the last one:

//#if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
	m_pCS_9MMShell		= NULL;
	m_pCS_57Shell		= NULL;
	m_pCS_12GaugeShell	= NULL;
	m_pCS_556Shell		= NULL;
	m_pCS_762NATOShell	= NULL;
	m_pCS_338MAGShell	= NULL;
//#endif

And the last one will be in the CSEjectBrass( ... ) function, at the bottom of the file:

//#if defined ( CSTRIKE_DLL ) || defined ( SDK_DLL )

	switch( shellType )
	{
	default:
	case CS_SHELL_9MM:
		hitsound = TE_PISTOL_SHELL;
		pModel = m_pCS_9MMShell;
		break;
	case CS_SHELL_57:
		hitsound = TE_PISTOL_SHELL;
		pModel = m_pCS_57Shell;
		break;
	case CS_SHELL_12GAUGE:
		hitsound = TE_SHOTGUN_SHELL;
		pModel = m_pCS_12GaugeShell;
		break;
	case CS_SHELL_556:
		hitsound = TE_RIFLE_SHELL;
		pModel = m_pCS_556Shell;
		break;
	case CS_SHELL_762NATO:
		hitsound = TE_RIFLE_SHELL;
		pModel = m_pCS_762NATOShell;
		break;
	case CS_SHELL_338MAG:
		hitsound = TE_RIFLE_SHELL;
		pModel = m_pCS_338MAGShell;
		break;
	}
//#endif

Conclusion

And that's it for now, enjoy!