Laserweapon
January 2024
You can help by adding links to this article from other relevant articles.
January 2024
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.
How to make a Laser Pistol!
Intro
We will make changes in four files:
- weapon_pistol.cpp - contains the code that makes the pistol work
- hl2_gamerules.cpp - contains code that determines what the engine does
- weapon_pistol.txt - this is the weapon script for the pistol
- skill.cfg
weapon_pistol.cpp
First we need to add some #include
directives to get access to the functions and classes that we will need to make a laser. The first file we need is beam_shared.h, which contains a great deal of code relevant to using beams. The other file we need is ammodef.h.
To include these files, change the line that reads #include "gamestats.h"
to:
#include "gamestats.h"
#include "beam_shared.h" /* We will use some of the functions declared this later... */
#include "ammodef.h" /* This is needed for the tracing done later */
// This determines the sprite used by the laser beam
#define PHYSCANNON_BEAM_SPRITE "sprites/orangelight1.vmt"
#define PHYSCANNON_BEAM_SPRITE
. We use this macro wherever we want to refer to the sprite used to draw the laser beam. Later, if we want to change the sprite that gets used, all we have to do is change "sprites/orangelight1.vmt" to something else.The next thing that we need to do is to declare two functions, DrawBeam
and DoImpactEffect
. DrawBeam
will actually draw a laser beam for us (once we define it). DoImpactEffect
is special because it gets called automatically by the game engine. We are allowed to define it so that it does something for us. We will define it to create an electrical explosion wherever the laser hits. These two functions will be defined later.
- Under public, below
DECLARE_SERVERCLASS()
, add the following:
void DrawBeam( const Vector &startPos, const Vector &endPos, float width );
void DoImpactEffect( trace_t &tr, int nDamageType );
Next, we need to add a variable. Whenever we add a variable, we also must add it to the weapon's DATADESC section. This will allow the variable's content to be stored and loaded in saved games, keeping states consistent between game sessions.
Under private, below DECLARE_ACTTABLE()
, add the following:
int m_nBulletType;
Then, below BEGIN_DATADESC( CWeaponPistol )
add:
DEFINE_FIELD( m_nBulletType, FIELD_INTEGER ),
The next step is to change the declaration of the PrimaryAttack
function so that it receives more information from the game engine about what is happening when the pistol is attacking. Locate the following:
void PrimaryAttack( void );
and change it to
void PrimaryAttack( trace_t &tr, int nDamageType, CBaseCombatCharacter *pOperator );
Remember that variable we added earlier (m_nBulletType
)? Like any other variable, we ought to initialize it in the weapon's constructor. The code for the constructor starts like this:
CWeaponPistol::CWeaponPistol( void )
{
m_flSoonestPrimaryAttack = gpGlobals->curtime;
To make sure that that variable gets initialized when the weapon is created, change the above to look like this:
CWeaponPistol::CWeaponPistol( void )
{
m_flSoonestPrimaryAttack = gpGlobals->curtime;
m_nBulletType = -1;
The PrimaryAttack
function is called every time the weapon attacks. We need to change it to match the the change we made above. We also need to add code to fire a laser. First, locate the following:
void CWeaponPistol::PrimaryAttack( void )
and change it to
void CWeaponPistol::PrimaryAttack( trace_t &tr, int nDamageType, CBaseCombatCharacter *pOperator )
Next, find the following in the PrimaryAttack
function:
m_iPrimaryAttacks++;
gamestats->Event_WeaponFired( pOwner, true, GetClassname() );
and add the following code below it:
Vector vecShootOrigin, vecShootDir;
vecShootOrigin = pOperator->Weapon_ShootPosition();
DrawBeam( vecShootOrigin, tr.endpos, 15.5 );
The above code calls our DrawBeam function (defined next) with two vectors and a float. The first vector specifies where the beam should start, the second specifies where it ends. The second vector comes from the tr
parameter to PrimaryAttack
. It represents the location of whatever was is in the line of fire of the pistol. So DrawBeam
will draw a laser beam from the barrel to wherever the pistol is aiming, with a beam width of 15.5.
Finally, we have to define the DrawBeam
and DoImpactEffect
functions.
//-----------------------------------------------------------------------------
// Purpose:
// Input : &startPos - where the beam should begin
// &endPos - where the beam should end
// width - what the diameter of the beam should be (units?)
//-----------------------------------------------------------------------------
void CWeaponPistol::DrawBeam( const Vector &startPos, const Vector &endPos, float width )
{
//Tracer down the middle
UTIL_Tracer( startPos, endPos, 0, TRACER_DONT_USE_ATTACHMENT, 6500, false, "GaussTracer" );
//Draw the main beam shaft
CBeam *pBeam = CBeam::BeamCreate( PHYSCANNON_BEAM_SPRITE, 15.5 );
// It starts at startPos
pBeam->SetStartPos( startPos );
// This sets up some things that the beam uses to figure out where
// it should start and end
pBeam->PointEntInit( endPos, this );
// This makes it so that the laser appears to come from the muzzle of the pistol
pBeam->SetEndAttachment( LookupAttachment("Muzzle") );
pBeam->SetWidth( width );
// pBeam->SetEndWidth( 0.05f );
// Higher brightness means less transparent
pBeam->SetBrightness( 255 );
pBeam->SetColor( 255, 185+random->RandomInt( -16, 16 ), 40 );
pBeam->RelinkBeam();
// The beam should only exist for a very short time
pBeam->LiveForTime( 0.1f );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &tr - used to figure out where to do the effect
// nDamageType - ???
//-----------------------------------------------------------------------------
void CWeaponPistol::DoImpactEffect( trace_t &tr, int nDamageType )
{
//Draw our beam
DrawBeam( tr.startpos, tr.endpos, 15.5 );
if ( (tr.surface.flags & SURF_SKY) == false )
{
CPVSFilter filter( tr.endpos );
te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
m_nBulletType = GetAmmoDef()->Index("GaussEnergy");
UTIL_ImpactTrace( &tr, m_nBulletType );
}
}
hl2_gamerules.cpp
Now that we have finished changing the pistol code, we need to change some engine code so that the laser pistol works as expected. Locate the following:
def.AddAmmoType("Pistol", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_pistol", "sk_npc_dmg_pistol", "sk_max_pistol", BULLET_IMPULSE(200, 1225), 0 );
The line shown above sets up some information that the game engine uses to determine how getting shot by the pistol affects whatever is being shot. Change it to look like the following:
def.AddAmmoType("Pistol", DMG_DISSOLVE, TRACER_NONE, "sk_plr_dmg_pistol", "sk_npc_dmg_pistol", "sk_max_pistol", BULLET_IMPULSE(200, 1225), 0 );
Changing DMG_BULLET
to DMG_DISSOLVE
changes what happens when an enemy is killed by this weapon. In this case, when an enemy is killed, it dissolves as if it was killed by the AR2 secondary fire. Changing TRACER_LINE_AND_WHIZ
to TRACER_NONE
gets rid of the tracer effect that can be seen when firing the pistol.
weapon_pistol.txt
This file is located in your mod folder, under scripts.
The path to this folder is usually something like C:\Program Files\Steam\steamapps\SourceMods\<your mod name>\scripts\
We are almost finished with our awesome laser pistol. However, if we ran our code now, we wouldn't see a "Laser Pistol" in our weapons menu. Instead we would still see a "9mm Handgun" or something like that. To fix this, we have to change a single line in the pistol's weapon script.
Change the following:
"printname" "#HL2_Pistol"
to
"printname" "LASER PISTOL"
This changes the name of the weapon as it appears in the HUD
skill.cfg
This file is located in your mod folder, under cfg.
The path to this folder is usually something like C:\Program Files\Steam\steamapps\SourceMods\<your mod name>\cfg\
We have one more edit to make. The pistol doesn't fire bullets anymore, it fires laser beams. Those little 9mm bullets should probably do less damage than a laser. Therefore, we should change the amount of damage that the laser pistol does.
Change this:
sk_plr_dmg_pistol "5"
sk_npc_dmg_pistol "3"
sk_max_pistol "148"
to this:
sk_plr_dmg_pistol "20"
sk_npc_dmg_pistol "15"
sk_max_pistol "148"
A message from the original author
I hope this helps u a bit
Speedlly (Scubic)
this weapon (or a part of it) is going to play a role in the game that were maken (Cubic Life)