Приветствую Вас 1-класс | RSS Главная | Каталог статей | Регистрация | Вход
Меню сайта

Категории раздела
Программирование [7]
Моделирование [8]
Маппинг [67]
Текстурирование [10]

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Мини чат

Главная » Статьи » Программирование

weapon_gauss
Гаусс
Сегодня мы займёмся созданием гауссовой винтовки :) Иными словами Гауссовки :) для оружия применим более рациональное название TauCannon.
 
ВНИМАНИЕ : модели к туториалу качать тут
Итак, создадим 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Так, теперь идём опять в 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 );
 
 floatx, 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_ttr;
 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 И всёже, WallJump? :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 ){
 //Качка экрана
 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 set 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 goingto 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 );
 }
 returntrue;
}
 
 
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.wavmoddir\sound\weapons\gauss\electro2.wavmoddir\sound\weapons\gauss\electro3.wav
 
Если возникнут проблемы, обращаемся на форум
Категория: Туториалы по программированию (HL2) | Автор: Lolmen (24.07.2007)
Категория: Программирование | Добавил: HellMapper (04.05.2009)
Просмотров: 1412 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Имя *:
Email *:
Код *:
Форма входа

Группа Steam

Наша кнопка

Поиск

Друзья сайта


  • Официальный блог


  • YIIbIpu-TEAM


  • DETLER-TEAM



  • Copyright WEDGe © 2024