Четверг, 18.04.2024, 09:04
Приветствую Вас Guest | RSS
Главная страница | Статьи | Регистрация | Вход
Меню сайта

Случайный рисунок

Категории каталога
Туториалы по маппингу (HL2) [68]
Туториалы по маппингу для Half-Life
Туториалы по текстурированию (HL2) [10]
Туторы по текстурированию для Half-Life
Туториалы по моделированию (HL2) [9]
Туторы по моделированию для Half-Life
Туториалы по программированию (HL2) [53]
Туторы по прагроммированию для Half-life
Другие туториалы (HL1 и HL2) [4]
Туторы которые не вошли в другие категории
Half-Life 2 Beta [1]
Статьи о npc и weapon в бете Half-Life 2, а так же мануалы и FAQ.
Туториалы по маппингу (HL1) [14]
Туторы по маппингу для Half-Life 1
Туториалы по текстурированию (HL1) [1]
Туторы по текстурированию для Half-Life 1
Туториалы по моделированию (HL1) [1]
Туторы по моделированию для Half-Life 1
Туториалы по программированию (HL1) [30]
Туторы по программированию для Half-Life 1

Наш опрос
Очистить ли форум от всех сообщений и начать всё с чистого листа?
Всего ответов: 561

Начало » Статьи » Туториалы по программированию (HL2)

Гаусс

Сегодня мы займёмся созданием гауссовой винтовки :) Иными словами Гауссовки :) для оружия применим более рациональное название Tau Cannon.

ВНИМАНИЕ : модели к туториалу качать тут

Итак, создадим tau_cannon.h чтобы он был в moddir/src/dlls/hl2_dll И туда отпостим :
 
//========= Copyright © 2002-2008, Lolmen & Valve, All rights reserved. ============
//
// Purpose: Tau Cannon Super gun
//
//==================================================================================

#include "basehlcombatweapon.h"

#ifndef WEAPON_GAUSS_H
#define WEAPON_GAUSS_H
#ifdef _WIN32
#pragma once
#endif

#include "te_particlesystem.h"
#include "effect_dispatch_data.h"

#define GAUSS_BEAM_SPRITE "sprites/laserbeam.vmt"

#define GAUSS_CHARGE_TIME 0.2f
#define MAX_GAUSS_CHARGE 16
#define MAX_GAUSS_CHARGE_TIME 3
#define DANGER_GAUSS_CHARGE_TIME 10


//=============================================================================
// Tau cannon
//=============================================================================

class CWeaponTauCannon : public CBaseHLCombatWeapon
{
 DECLARE_DATADESC();
public:
 DECLARE_CLASS( CWeaponTauCannon, CBaseHLCombatWeapon );

 CWeaponTauCannon( void ); // Конструктор

 DECLARE_SERVERCLASS();

 void Spawn( void );
 void Precache( void );
 void PrimaryAttack( void );
 void SecondaryAttack( void );
 void AddViewKick( void );

 bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );

 void ItemPostFrame( void );

 float GetFireRate( void ) { return 0.2f; } // Скорострельность

 virtual const Vector &GetBulletSpread( void ) // Конус разброса
 {
 static Vector cone = VECTOR_CONE_1DEGREES; 
 return cone;
 }

protected:

 void Fire( void );
 void ChargedFire( void );
 float GetFullChargeTime( void );
 void StartFire( void );
 void StopChargeSound( void );

 void DrawBeam( const Vector &startPos, const Vector &endPos, float width, bool useMuzzle = false );
 void IncreaseCharge( void );
 bool ShouldDrawWaterImpacts( const trace_t &shot_trace ); // Lolmen : Добавим брызг по воде

private:
 EHANDLE m_hViewModel;
 float m_flNextChargeTime;
 CSoundPatch *m_sndCharge;

 float m_flChargeStartTime;
 bool m_bCharging;
 bool m_bChargeIndicated;

 DECLARE_ACTTABLE();
};

#endif // WEAPON_GAUSS_H
HТак, теперь идём опять в moddir/src/dlls/hl2_dll создаём там tau_cannon.cpp 
//========= Copyright © 2002-2008, Lolmen & Valve, All rights reserved. ============
//
// Purpose: Tau Cannon Super gun
//
//==================================================================================

#include "cbase.h"
#include "player.h"
#include "gamerules.h"
#include "basehlcombatweapon.h"
#include "decals.h"
#include "beam_shared.h"
#include "AmmoDef.h"
#include "IEffects.h"
#include "engine/IEngineSound.h"
#include "in_buttons.h"
#include "soundenvelope.h"
#include "soundent.h"
#include "shake.h"
#include "explode.h"
#include "tau_cannon.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------

IMPLEMENT_SERVERCLASS_ST( CWeaponTauCannon, DT_WeaponTauCannon )
END_SEND_TABLE()

LINK_ENTITY_TO_CLASS( weapon_gauss, CWeaponTauCannon ); // обединения имени энити с этим классом
PRECACHE_WEAPON_REGISTER( weapon_gauss ); // имя тектового файла в scripts.txt

acttable_t CWeaponTauCannon::m_acttable[] = 
{
 { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, true },
};

IMPLEMENT_ACTTABLE( CWeaponTauCannon );

//---------------------------------------------------------
// Save/Restore
//---------------------------------------------------------
BEGIN_DATADESC( CWeaponTauCannon )

 DEFINE_FIELD( m_hViewModel, FIELD_EHANDLE ),
 DEFINE_FIELD( m_flNextChargeTime, FIELD_TIME ),
 DEFINE_FIELD( m_flChargeStartTime, FIELD_TIME ),
 DEFINE_FIELD( m_bCharging, FIELD_BOOLEAN ),
 DEFINE_FIELD( m_bChargeIndicated, FIELD_BOOLEAN ),

 DEFINE_SOUNDPATCH( m_sndCharge ),

END_DATADESC()


extern ConVar sk_plr_dmg_gauss; // Ссылка на обьект
extern ConVar sk_plr_max_dmg_gauss; // Ссылка на обьект

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CWeaponTauCannon::CWeaponTauCannon( void )
{
 m_hViewModel = NULL;
 m_flNextChargeTime = 0;
 m_flChargeStartTime = 0;
 m_sndCharge = NULL;
 m_bCharging = false;
 m_bChargeIndicated = false;
 m_bReloadsSingly = false;
 m_bFiresUnderwater = false;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponTauCannon::Precache( void )
{
 enginesound->PrecacheSound( "weapons/gauss/chargeloop.wav" );
 BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponTauCannon::Spawn( void )
{
 BaseClass::Spawn();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponTauCannon::Fire( void )
{
 CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
 
 if ( !pOwner ){ return; }

 m_bCharging = false;

 if ( m_hViewModel == NULL )
 {
 CBaseViewModel *vm = pOwner->GetViewModel();

 if ( vm )
 {
 m_hViewModel.Set( vm );
 }
 }

 Vector startPos = pOwner->Weapon_ShootPosition();
 Vector aimDir = pOwner->GetAutoaimVector( AUTOAIM_5DEGREES );

 Vector vecUp, vecRight;
 VectorVectors( aimDir, vecRight, vecUp );

 float x, y, z;

 // Гауссовский разброс
 do {
 x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5);
 y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5);
 z = x*x+y*y;
 } while (z > 1);

 aimDir = aimDir + x * GetBulletSpread().x * vecRight + y * GetBulletSpread().y * vecUp;

 Vector endPos = startPos + ( aimDir * MAX_TRACE_LENGTH );
 
 // Тестируем дистанцию выстрела
 trace_t tr;
 UTIL_TraceLine( startPos, endPos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );
 
 ClearMultiDamage();

 CBaseEntity *pHit = tr.m_pEnt;
 
 CTakeDamageInfo dmgInfo( this, pOwner, sk_plr_dmg_gauss.GetFloat(), DMG_SHOCK );

 if ( pHit != NULL )
 {
 CalculateBulletDamageForce( &dmgInfo, m_iPrimaryAmmoType, aimDir, tr.endpos );
 pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr );
 }
 // Проверяем на наличие воды по пути луча
 ShouldDrawWaterImpacts( tr );

 if ( tr.DidHitWorld() ) // Рикошет
 {
 float hitAngle = -DotProduct( tr.plane.normal, aimDir );

 if ( hitAngle < 0.5f )
 {
 Vector vReflection;
 
 vReflection = 2.0 * tr.plane.normal * hitAngle + aimDir;
 
 startPos = tr.endpos;
 endPos = startPos + ( vReflection * MAX_TRACE_LENGTH );
 
 //Draw beam to reflection point
 DrawBeam( tr.startpos, tr.endpos, 1.6, true );

 CPVSFilter filter( tr.endpos );
 te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );

 UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" );

 //Find new reflection end position
 UTIL_TraceLine( startPos, endPos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );

 if ( tr.m_pEnt != NULL )
 {
 dmgInfo.SetDamageForce( GetAmmoDef()->DamageForce(m_iPrimaryAmmoType) * vReflection );
 dmgInfo.SetDamagePosition( tr.endpos );
 tr.m_pEnt->DispatchTraceAttack( dmgInfo, vReflection, &tr );
 }

 //Connect reflection point to end
 DrawBeam( tr.startpos, tr.endpos, 0.4 );
 }
 else
 {
 DrawBeam( tr.startpos, tr.endpos, 1.6, true );
 }
 }
 else
 {
 DrawBeam( tr.startpos, tr.endpos, 1.6, true );
 }

 ApplyMultiDamage();

 UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" ); // след на стене

 CPVSFilter filter( tr.endpos );
 te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );

 m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f;

 AddViewKick();

 // Регистрация всппышки света для AI
 pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
}

//-----------------------------------------------------------------------------
// Purpose: Накопительный выстрел
//-----------------------------------------------------------------------------
void CWeaponTauCannon::ChargedFire( void )
{
 CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
 
 if ( !pOwner ){ return; }

 bool penetrated = false;

 // Играем шоковые выстрелы
 WeaponSound( SINGLE );
 WeaponSound( SPECIAL2 );

 SendWeaponAnim( ACT_VM_SECONDARYATTACK );
 StopChargeSound();

 m_bCharging = false;
 m_bChargeIndicated = false;

 m_flNextPrimaryAttack = gpGlobals->curtime + 0.2f;
 m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f;

 // Посмотрим откуда выйдет выстрел...
 Vector startPos= pOwner->Weapon_ShootPosition();
 Vector aimDir = pOwner->GetAutoaimVector( AUTOAIM_5DEGREES );
 Vector endPos = startPos + ( aimDir * MAX_TRACE_LENGTH );
 
 trace_t tr;
 UTIL_TraceLine( startPos, endPos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );
 ShouldDrawWaterImpacts( tr ); // Проверка на наличие воды
 ClearMultiDamage();

 // Насколько много урона надо нанести
 float flChargeAmount = ( gpGlobals->curtime - m_flChargeStartTime ) / MAX_GAUSS_CHARGE_TIME;

 // Скрепляем
 if ( flChargeAmount > 1.0f ){ flChargeAmount = 1.0f; }

 // Определение количества урона
 float flDamage = sk_plr_dmg_gauss.GetFloat() + ( ( sk_plr_max_dmg_gauss.GetFloat() - sk_plr_dmg_gauss.GetFloat() ) * flChargeAmount );

 CBaseEntity *pHit = tr.m_pEnt;
 if ( tr.DidHitWorld() )
 {
 // Пробуем пробить стену
 UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" );
 UTIL_DecalTrace( &tr, "RedGlowFade" );

 CPVSFilter filter( tr.endpos );
 te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
 Vector vStore = tr.endpos;
 Vector testPos = tr.endpos + ( aimDir * 48.0f );

 UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );
 
 if ( !tr.allsolid )
 { 
 UTIL_DecalTrace( &tr, "RedGlowFade" ); 
 penetrated = true;
 // И рисуем обратную деколь
 trace_t backward_tr;
 UTIL_TraceLine( tr.endpos, vStore, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &backward_tr );
 if ( backward_tr.DidHit() ){ 
 UTIL_ImpactTrace( &backward_tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" ); }

 }
 }
 else if ( pHit != NULL )
 {
 CTakeDamageInfo dmgInfo( this, pOwner, flDamage, DMG_SHOCK );
 CalculateBulletDamageForce( &dmgInfo, m_iPrimaryAmmoType, aimDir, tr.endpos );

 // Наносим прямой удар по всему что на пути
 pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr );
 }

 ApplyMultiDamage();

 UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" );

 QAngle viewPunch;

 viewPunch.x = random->RandomFloat( -4.0f, -8.0f );
 viewPunch.y = random->RandomFloat( -0.25f, 0.25f );
 viewPunch.z = 0;

 pOwner->ViewPunch( viewPunch ); // качаем экран игрока

 DrawBeam( startPos, tr.endpos, 9.6, true ); // рисуем луч
 // Подбросим игрока немного вверх? Такого в SP нету :D И всёже, Wall Jump? :D
 Vector recoilForce = pOwner->GetAbsVelocity() - pOwner->GetAutoaimVector( 0 ) * ( flDamage * 5.0f );
 recoilForce[2] += 128.0f; 
 pOwner->SetAbsVelocity( recoilForce ); // отдача на тело игрока

 CPVSFilter filter( tr.endpos );
 te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
 if ( penetrated )
 {
 // при проникновении через стену дамаг
 RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL );

 // Выходим из стены и пошли искать дырку для деколи
 UTIL_TraceLine( tr.endpos, endPos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );

 UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" );
 UTIL_DecalTrace( &tr, "RedGlowFade" ); 
 // и после проникновение на кончике луча дамаг
 RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL );
 }

 // Оповещаем AI о выстреле
 pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
}

//-----------------------------------------------------------------------------
// Purpose: Рисуем лучик
//-----------------------------------------------------------------------------
void CWeaponTauCannon::DrawBeam( const Vector &startPos, const Vector &endPos, float width, bool useMuzzle )
{
 CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
 
 if ( pOwner == NULL )
 return;

 //Check to store off our view model index
 if ( m_hViewModel == NULL )
 {
 CBaseViewModel *vm = pOwner->GetViewModel();

 if ( vm )
 {
 m_hViewModel.Set( vm );
 }
 }

 // Главный лучевой след
 CBeam *pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, width );
 
 if ( useMuzzle )
 {
 pBeam->PointEntInit( endPos, m_hViewModel );
 pBeam->SetEndAttachment( 1 );
 pBeam->SetWidth( width / 4.0f );
 pBeam->SetEndWidth( width );
 }
 else
 {
 pBeam->SetStartPos( startPos );
 pBeam->SetEndPos( endPos );
 pBeam->SetWidth( width );
 pBeam->SetEndWidth( width / 4.0f );
 }

 pBeam->SetBrightness( 255 );
 pBeam->SetColor( 255, 145+random->RandomInt( -16, 16 ), 0 );
 pBeam->RelinkBeam();
 pBeam->LiveForTime( 0.1f );

 // Искры вокруг луча
 for ( int i = 0; i < 3; i++ )
 {
 pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, (width/2.0f) + i );
 
 if ( useMuzzle )
 {
 pBeam->PointEntInit( endPos, m_hViewModel );
 pBeam->SetEndAttachment( 1 );
 }
 else
 {
 pBeam->SetStartPos( startPos );
 pBeam->SetEndPos( endPos );
 }
 
 pBeam->SetBrightness( random->RandomInt( 64, 255 ) );
 pBeam->SetColor( 255, 255, 150+random->RandomInt( 0, 64 ) );
 pBeam->RelinkBeam();
 pBeam->LiveForTime( 0.1f );
 pBeam->SetNoise( 1.6f * i );
 pBeam->SetEndWidth( 0.1f );
 }
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponTauCannon::PrimaryAttack( void )
{
 CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
 
 if ( !pOwner ){ return; }

 WeaponSound( SINGLE );
 WeaponSound( SPECIAL2 );
 
 SendWeaponAnim( ACT_VM_PRIMARYATTACK );
 
 pOwner->DoMuzzleFlash();

 m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();

 pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );

 Fire();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponTauCannon::IncreaseCharge( void )
{
 CBasePlayer *pOwner = ToBasePlayer( GetOwner() );

 if ( m_flNextChargeTime > gpGlobals->curtime || !pOwner ){ return; }

 // Сверим время накопления
 if ( ( gpGlobals->curtime - m_flChargeStartTime ) > MAX_GAUSS_CHARGE_TIME )
 {
 // Предупредим игрока что он на максимальной стадии накопления
 if ( m_bChargeIndicated == false )
 {
 WeaponSound( SPECIAL2 );
 m_bChargeIndicated = true;
 }

 if ( ( gpGlobals->curtime - m_flChargeStartTime ) > DANGER_GAUSS_CHARGE_TIME )
 {
 // Раним игрока за то, что он передержал
 WeaponSound( SPECIAL2 );
 
 // Добавим DMG_CRUSH потому что не хотим никакой физической силы
 pOwner->TakeDamage( CTakeDamageInfo( this, this, 25, DMG_SHOCK | DMG_CRUSH ) );
 
 color32 gaussDamage = {255,128,0,128};
 UTIL_ScreenFade( pOwner, gaussDamage, 0.2f, 0.2f, FFADE_IN ); // подсветим жкран

 m_flNextChargeTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 2.5f );
 }

 return;
 }

 // Вычитаем силу
 pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
 // Контролируем подачу тона звука
 int pitch = ( gpGlobals->curtime - m_flChargeStartTime ) * ( 150 / GetFullChargeTime() ) + 100;
 if ( pitch > 250 ){ pitch = 250; }
 if ( m_sndCharge != NULL )
 {
 (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndCharge, pitch, 0 );
 }

 // Убедимся что можем высвободить силу
 if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
 {
 ChargedFire();
 return;
 }

 m_flNextChargeTime = gpGlobals->curtime + GAUSS_CHARGE_TIME;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponTauCannon::SecondaryAttack( void )
{
 CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
 
 if ( !pOwner || pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ){ return; }
 // Не стреляем под водой
 if ( pOwner->GetWaterLevel() == 3 )
 {
 EmitSound( "Weapon_Gauss.Zap1" );
 SendWeaponAnim( ACT_VM_IDLE );
 m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
 return;
 }
 if ( !m_bCharging )
 {
 // Начинаем раскруточную анимацию
 SendWeaponAnim( ACT_VM_PULLBACK );
 
 // Начинаем повторяющийся звук
 if ( !m_sndCharge )
 {
 CPASAttenuationFilter filter( this );
 m_sndCharge = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "weapons/gauss/chargeloop.wav", ATTN_NORM );
 }

 if ( m_sndCharge != NULL )
 {
 (CSoundEnvelopeController::GetController()).Play( m_sndCharge, 1.0f, 50 );
 (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndCharge, 250, 3.0f );
 }

 m_flChargeStartTime = gpGlobals->curtime;
 m_bCharging = true;
 m_bChargeIndicated = false;

 // Вычитаем патроны
 pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
 }

 IncreaseCharge();
}

//-----------------------------------------------------------------------------
// Purpose: Дефолтная качка экрана
//-----------------------------------------------------------------------------
void CWeaponTauCannon::AddViewKick( void )
{
 //Get the view kick
 CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );

 if ( pPlayer == NULL )
 return;

 QAngle viewPunch;

 viewPunch.x = random->RandomFloat( -0.5f, -0.2f );
 viewPunch.y = random->RandomFloat( -0.5f, 0.5f );
 viewPunch.z = 0;

 pPlayer->ViewPunch( viewPunch );
}

//-----------------------------------------------------------------------------
// Purpose: Покадровый чекер
//-----------------------------------------------------------------------------
void CWeaponTauCannon::ItemPostFrame( void )
{
 CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );

 if ( !pPlayer ){ return; }

 if ( pPlayer->m_afButtonReleased & IN_ATTACK2 )
 {
 if ( m_bCharging ){ ChargedFire(); }
 }
 
 BaseClass::ItemPostFrame();
}

//-----------------------------------------------------------------------------
// Purpose: Останавливаем раскруточный звук
//-----------------------------------------------------------------------------
void CWeaponTauCannon::StopChargeSound( void )
{
 if ( m_sndCharge != NULL )
 {
 (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndCharge, 0.1f );
 }
}

//-----------------------------------------------------------------------------
// Purpose: Сворачивание оружия в кобуру
// Input  : *pSwitchingTo - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CWeaponTauCannon::Holster( CBaseCombatWeapon *pSwitchingTo )
{
 StopChargeSound(); // останавливаем звук раскрутки
 m_bCharging = false;
 m_bChargeIndicated = false;

 return BaseClass::Holster( pSwitchingTo );
}
//-----------------------------------------------
// Purpose: Время на раскрутку
//-----------------------------------------------
float CWeaponTauCannon::GetFullChargeTime( void )
{
 if ( g_pGameRules->IsMultiplayer() )
 {
 return 1.5;
 }
 else
 {
 return 4;
 }
}
//----------------------------------------------------------------------------------
// Purpose: Добавляет брызги на воду при стрельбе по оной 
//----------------------------------------------------------------------------------
#define FSetBit(iBitVector, bits) ((iBitVector) |= (bits)) // LOLMEN : Set some bits to bit vec
#define FBitSet(iBitVector, bit) ((iBitVector) & (bit)) // LOLMEN : Do that bit setted in bit vec?
#define TraceContents( vec ) ( enginetrace->GetPointContents( vec ) ) // LOLMEN : Do some test?
#define WaterContents( vec ) ( FBitSet( TraceContents( vec ), CONTENTS_WATER|CONTENTS_SLIME ) ) // Lolmen : For water

bool CWeaponTauCannon::ShouldDrawWaterImpacts( const trace_t &shot_trace )
{
 //FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good
 // right now anyway...

 // We must start outside the water
 if ( WaterContents( shot_trace.startpos ) )
 return false;

 // We must end inside of water
 if ( !WaterContents( shot_trace.endpos ) )
 return false;

 trace_t waterTrace;

 UTIL_TraceLine( shot_trace.startpos, shot_trace.endpos, (CONTENTS_WATER|CONTENTS_SLIME), UTIL_GetLocalPlayer(), COLLISION_GROUP_NONE, &waterTrace );


 if ( waterTrace.fraction < 1.0f )
 {
 CEffectData data;

 data.m_fFlags = 0;
 data.m_vOrigin = waterTrace.endpos;
 data.m_vNormal = waterTrace.plane.normal;
 data.m_flScale = random->RandomFloat(2.0,4.0f); // Lolmen : Регулируйте размер кругов/брызг тут

 // See if we hit slime
 if ( FBitSet( waterTrace.contents, CONTENTS_SLIME ) )
 {
 FSetBit( data.m_fFlags, FX_WATER_IN_SLIME );
 }
 
 CPASFilter filter( data.m_vOrigin ); 
 te->DispatchEffect( filter, 0.0, data.m_vOrigin, "watersplash", data ); 
 }
 return true;
}

C серверной частью закончили, теперь займёмся клиентской...

зайдем в moddir\src\cl_dll\hl2_hud\ и откроем там c_weapon__stubs_hl2.cpp

В нём вы увидите список оружия, так сразу закомментируем строчку вот так:

 

 

//STUB_WEAPON_CLASS( weapon_gauss, WeaponGaussGun, C_BaseHLCombatWeapon ); STUB_WEAPON_CLASS( weapon_cubemap, WeaponCubemap, C_BaseCombatWeapon );

 

И куданить например после:

 

STUB_WEAPON_CLASS( weapon_357, Weapon357, C_BaseHLCombatWeapon );
 
Вставим строчечку:
 
STUB_WEAPON_CLASS( weapon_gauss, WeaponTauCannon, C_BaseHLCombatWeapon );
 
 

Так, теперь есть файл который и на клиенсткой и на серверной части, hl2_gamerules.cpp в нём найдём

 

CAmmoDef *GetAmmoDef()

 

После этой строчки будет идти список типов патронов доступных в игре... Впишем туда после

 

def.AddAmmoType("GaussEnergy", DMG_SHOCK, TRACER_NONE, "sk_jeep_gauss_damage", "sk_jeep_gauss_damage", "sk_max_gauss_round", BULLET_IMPULSE(650, 8000), 0 );

 

вот это:

 

def.AddAmmoType("Uranium", DMG_SHOCK | DMG_ENERGYBEAM, TRACER_NONE, "sk_plr_dmg_gauss", "sk_npc_dmg_gauss", "sk_max_gauss_round", BULLET_IMPULSE(650, 8000), 0 );

 

Это необходимо, чтобы багги не конфликтовал с ручным гауссом.

также там-же найдём :

 

ConVar sk_max_gauss_round ( "sk_max_gauss_round", "300", FCVAR_REPLICATED );

 

И перед, впишем:

 

ConVar sk_plr_dmg_gauss( "sk_plr_dmg_gauss", "0" ); ConVar sk_npc_dmg_gauss( "sk_plr_dmg_gauss", "0" ); ConVar sk_plr_max_dmg_gauss( "sk_plr_max_dmg_gauss", "0" );

 

Эти переменные будем контролировать из skill.cfg который должен храниться в moddir/cfg

Дальше, нам хотелось бы заюзать коробочки с патронами для гаусса... Откроем moddir\src\dlls\hl2_dll\item_ammo.cpp

И разместим там где-нить после строчки :

 

LINK_ENTITY_TO_CLASS( item_rpg_round, CItem_RPG_Round );

 

Такое:

 

#define AMMO_GAUSS_GIVE 20
#define AMMO_GAUSS_MODEL "models/w_gaussammo.mdl" // УКАЖИТЕ вашу модель для коробочки тут

class CItem_GaussAmmo : public CItem
{
public:
 DECLARE_CLASS( CItem_GaussAmmo, CItem );

 void Spawn( void )
 { 
 Precache();
 SetModel( AMMO_GAUSS_MODEL );
 BaseClass::Spawn();
 }
 void Precache( void )
 {
 engine->PrecacheModel( AMMO_GAUSS_MODEL );
 }
 bool MyTouch( CBasePlayer *pPlayer )
 {
 if ( ITEM_GiveAmmo( pPlayer, AMMO_GAUSS_GIVE, "Uranium" ) )
 {
 if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
 {
 UTIL_Remove(this); 
 } 
 return true;
 }
 return false;
 }
};
LINK_ENTITY_TO_CLASS( item_ammo_gauss, CItem_GaussAmmo ); // Название инить
LINK_ENTITY_TO_CLASS( item_gauss_ammo, CItem_GaussAmmo ); // Название инить

Агась :D А игрока проэквипить забыли? Ну помните impulse 101? :D Так, тогда лезем в player.cpp и ищем там: case 101: и там уже по вашему усмотрению... А по моему добавим там:

 

GiveAmmo( 150, "Uranium" ); GiveNamedItem( "weapon_gauss" );

 

Так теперь идём в действительную папку с модом, залазим там в scripts, и создаём текстовик weapon_gauss.txt вот с такими внутренностями :

 

// Gauss Gun

WeaponData
{
 // Weapon fdata is loaded by both the Game and Client DLLs.
 "printname" "Tau Cannon" // Сделайте имя в resources если надо и юзайте #ResourcesName
 "viewmodel" "models/weapons/v_gauss.mdl" 
 "playermodel" "models/weapons/w_gauss.mdl" 
 "anim_prefix" "gauss"
 "bucket" "4" // --- \|/--------------
 "bucket_position" "5" // Отрегулируйте положиение в слоте

 "clip_size" "-1"
 "default_clip" "20"

 "primary_ammo" "Uranium"
 "secondary_ammo" "None"

 "weight" "2"
 "item_flags" "0"

 // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)
 SoundData
 {
 "single_shot" "Weapon_Gauss.Single"
 "special1" "Weapon_Gauss.Special1"
 "special2" "Weapon_Gauss.Special2" 
 }

 // Weapon Sprite data is loaded by the Client DLL.
 TextureData
 {
 "weapon"
 {
 "file" "sprites/w_icons1"
 "x" "128"
 "y" "64"
 "width" "128"
 "height" "64"
 }
 "weapon_s"
 {
 "file" "sprites/w_icons1b"
 "x" "128"
 "y" "64"
 "width" "128"
 "height" "64"
 }
 "ammo"
 {
 "file" "sprites/a_icons1"
 "x" "55"
 "y" "130"
 "width" "73"
 "height" "20"
 }
 "crosshair"
 {
 "file" "sprites/crosshairs"
 "x" "0"
 "y" "48"
 "width" "24"
 "height" "24"
 }
 "autoaim"
 {
 "file" "sprites/crosshairs"
 "x" "0"
 "y" "48"
 "width" "24"
 "height" "24"
 }
 }
}

Еще придётся где-то разжиться и положить три electro звука, вот по таким путям:

 

moddir\sound\weapons\gauss\electro1.wav moddir\sound\weapons\gauss\electro2.wav moddir\sound\weapons\gauss\electro3.wav

 

Если возникнут проблемы, обращаемся на форум

 



Источник: http://wiki.hl2.ru/index.php?title=%D0%93%D0%B0%D1%83%D1%81%D1%81
Категория: Туториалы по программированию (HL2) | Добавил: DetLeR (24.07.2007) | Автор: lolmen
Просмотров: 2322 | Комментарии: 2 | Рейтинг: 5.0 |

Всего комментариев: 2
2 Strider  
1
Кстати спс за тутор, использовал

1 $H@D0W  
1
Ошибка в консольных командах :
вместо
ConVar sk_npc_dmg_gauss( "sk_plr_dmg_gauss", "0" );
нужно
ConVar sk_npc_dmg_gauss( "sk_npc_dmg_gauss", "0" );

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Кто в Онлайн

Друзья сайта

Баннеры

  Сайт CrazyArts   Black   Сообщество сайтов о Half-Life   Самый   Только   Все   hl2 top 100     Rambler's Top100  

игры
игры

  Каталог сайтов Планета Топ 100 - Planet Top 100       ТОП ЛУЧШИХ ИГРОВЫХ САЙТОВ           Detroit Team Site :: Моды от Detroit Team, видео, новости.   Naruto-kun[Звезда Наруто]  


The idea of dising: Homie7