Регистрация - или - Войти
WhoopservatoryWhoopservatory

Создатель, не обращая внимания на банальную сюжетную завязку, нагло поломал два стереотипа. Первый: «Старый забытый особ...

Outpost 16Outpost 16

First Person Shooter...

7/02/2010

weapon_sniperrifle с оптическим прицелом


  • Описание
  • Ссылка и установка

Исходный код снайперки

weapon_sniperrifle с оптическим прицелом


Автор / ы урока : Ku2zoff
Просмотров : 745 ( +2 )
Скачиваний : 0
Прислал / (а) : Streit
Дата создания : 07.04.2011 17:43:22
Источник : http://www.hlfx.ru/forum
Рейтинг :
 ( 3 ) 
Поделиться :


Имеются следующие переводы : | русский |

Как я и обещал, я выложил снайперку (weapon_sniperrifle) с оптическим прицелом. Вот она: Добавим в проект файл rifle.cpp

Code: rifle.cpp

/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
*
*
*
* This weapon written by Ku2zoff
*
*
****/
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "weapons.h"
#include "monsters.h"
#include "player.h"
#include "gamerules.h"
#include "shake.h"

#include "nodes.h"
#include "soundent.h"

enum sniperrifle_e {
   SNIPERRIFLE_DRAW = 0,
   SNIPERRIFLE_SLOWIDLE,
   SNIPERRIFLE_FIRE1,
   SNIPERRIFLE_FIRELASTROUND,
   SNIPERRIFLE_RELOAD,
   SNIPERRIFLE_RELOAD2,
   SNIPERRIFLE_SLOWIDLEEMPTY,
   SNIPERRIFLE_HOLSTER,
};

LINK_ENTITY_TO_CLASS( weapon_sniperrifle, CSniperrifle );

int CSniperrifle::GetItemInfo(ItemInfo *p)
{
   p->pszName = STRING(pev->classname);
   p->pszAmmo1 = "338";
   p->iMaxAmmo1 = _338_MAX_CARRY;
   p->pszAmmo2 = NULL;
   p->iMaxAmmo2 = -1;
   p->iMaxClip = SNIPERRIFLE_MAX_CLIP;
   p->iFlags = 0;
   p->iSlot = 2;
   p->iPosition = 3;
   p->iId = m_iId = WEAPON_SNIPERRIFLE;
   p->iWeight = SNIPERRIFLE_WEIGHT;

   return 1;
}

int CSniperrifle::AddToPlayer( CBasePlayer *pPlayer )
{
   if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
   {
     MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
     WRITE_BYTE( m_iId );
     MESSAGE_END();
     return TRUE;
   }
   return FALSE;
}
void CSniperrifle::Spawn( )
{
   pev->classname = MAKE_STRING("weapon_sniperrifle"); // hack to allow for old names
   Precache( );
   m_iId = WEAPON_SNIPERRIFLE;
   SET_MODEL(ENT(pev), "models/w_sniper.mdl");

   m_iDefaultAmmo = SNIPERRIFLE_DEFAULT_GIVE;

   FallInit();// get ready to fall down.
}


void CSniperrifle::Precache( void )
{
   PRECACHE_MODEL("models/v_sniper.mdl");
   PRECACHE_MODEL("models/w_sniper.mdl");
   PRECACHE_MODEL("models/p_sniper.mdl");

   PRECACHE_MODEL("models/w_sniper_clip.mdl");
   PRECACHE_SOUND("items/9mmclip1.wav");

   PRECACHE_SOUND ("weapons/sniper_cock1.wav");
   PRECACHE_SOUND ("weapons/sniper_fire1.wav");
   PRECACHE_SOUND ("weapons/sniper_zoomout.wav");
   PRECACHE_SOUND ("weapons/sniper_zoomin.wav");

   m_usFireSniper = PRECACHE_EVENT( 1, "events/sniper.sc" );
}

BOOL CSniperrifle::Deploy( )
{
   return DefaultDeploy( "models/v_sniper.mdl", "models/p_sniper.mdl", SNIPERRIFLE_DRAW, "bow", UseDecrement() );
}


void CSniperrifle::Holster( int skiplocal /* = 0 */ )
{
   m_fInReload = FALSE;// cancel any reload in progress.

   if ( m_fInZoom )
   {
     SecondaryAttack();
   }
   m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
   m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
   SendWeaponAnim( SNIPERRIFLE_HOLSTER );
}

void CSniperrifle::SecondaryAttack( void )
{
   if ( m_pPlayer->pev->fov != 0 )
   {
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0; // 0 means reset to default fov
     m_fInZoom = 0;
     #ifndef CLIENT_DLL
       UTIL_ScreenFade( m_pPlayer, Vector(0,0,0), 0.5, 0.25, 255, FFADE_IN );
     #endif
     EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/sniper_zoomout.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF));
   }
   else if ( m_pPlayer->pev->fov != 15 )
   {
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 15;
     m_fInZoom = 1;
     #ifndef CLIENT_DLL
       UTIL_ScreenFade( m_pPlayer, Vector(0,0,0), 0.5, 0.25, 255, FFADE_IN );
     #endif
     EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/sniper_zoomin.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF));
   }
   pev->nextthink = UTIL_WeaponTimeBase() + 0.1;
   m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0;
}

void CSniperrifle::PrimaryAttack( void )
{
   Shoot( 0.0001, 1.5, TRUE );
}

void CSniperrifle::Shoot( float flSpread , float flCycleTime, BOOL fUseAutoAim )
{
   if (m_pPlayer->pev->waterlevel == 3)
   {
     EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/sniper_cock1.wav", 0.8, ATTN_NORM);
     m_flNextPrimaryAttack = 0.15;
     return;
   }
   if (m_iClip <= 0)
   {
     if (m_fFireOnEmpty)
     {
       EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/sniper_cock1.wav", 0.8, ATTN_NORM);
       m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2;
     }
     return;
   }

   m_iClip--;

   m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;

   int flags;

   #if defined( CLIENT_WEAPONS )
     flags = FEV_NOTHOST;
   #else
     flags = 0;
   #endif

   // player "shoot" animation
   m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

   m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
   m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;

   Vector vecSrc = m_pPlayer->GetGunPosition( );
   Vector vecAiming;

   if ( fUseAutoAim )
   {
     vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
   }
   else
   {
     vecAiming = gpGlobals->v_forward;
   }

   Vector vecDir;
   vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, Vector( flSpread, flSpread, flSpread ), 8192, BULLET_PLAYER_338, 0, 0, m_pPlayer->pev, m_pPlayer->random_seed );

   PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), fUseAutoAim ? m_usFireSniper : m_usFireSniper, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, ( m_iClip == 0 ) ? 1 : 0, 0 );

   m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flCycleTime;

   if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
   // HEV suit - indicate out of ammo condition
   m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);

   m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}

void CSniperrifle::Reload( void )
{
   if ( m_fInZoom )
   {
     SecondaryAttack();
   }

   if ( m_pPlayer->ammo_338 <= 0 )
     return;

   if ( m_pPlayer->pev->fov != 0 )
   {
     m_fInZoom = FALSE;
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0; // 0 means reset to default fov
   }

   if (m_iClip == 0)
     DefaultReload( 10, SNIPERRIFLE_RELOAD, 3.9 );
   else
     DefaultReload( 10, SNIPERRIFLE_RELOAD2, 2.7 );

}


void CSniperrifle::WeaponIdle( void )
{
   m_pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES ); // get the autoaim vector but ignore it; used for autoaim crosshair in DM

   if ( m_flTimeWeaponIdle < UTIL_WeaponTimeBase() )
   {
     float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
     if (flRand <= 0.75)
     {
       if (m_iClip)
       {
         SendWeaponAnim( SNIPERRIFLE_SLOWIDLE );
       }
       else
       {
         SendWeaponAnim( SNIPERRIFLE_SLOWIDLEEMPTY );
       }
       m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 60.0 / 12.0;
     }

   }
}

class CSniperrifleAmmo : public CBasePlayerAmmo
{
   void Spawn( void )
   {
     Precache( );
     SET_MODEL(ENT(pev), "models/w_sniper_clip.mdl");
     CBasePlayerAmmo::Spawn( );
   }
   void Precache( void )
   {
     PRECACHE_MODEL ("models/w_sniper_clip.mdl");
     PRECACHE_SOUND("items/9mmclip1.wav");
   }
   BOOL AddAmmo( CBaseEntity *pOther )
   {
     if (pOther->GiveAmmo( AMMO_SNIPERRIFLECLIP_GIVE, "338", _338_MAX_CARRY ) != -1)
     {
       EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
       return TRUE;
     }
     return FALSE;
   }
};
LINK_ENTITY_TO_CLASS( ammo_338, CSniperrifleAmmo );

#endif

Потом открываем game.cpp и аналогично, как было с ножом, добавляем в него:

Code:

// Rifle
cvar_t sk_plr_snpr_bullet1 = {"sk_plr_snpr_bullet1","0"};
cvar_t sk_plr_snpr_bullet2 = {"sk_plr_snpr_bullet2","0"};
cvar_t sk_plr_snpr_bullet3 = {"sk_plr_snpr_bullet3","0"};

Затем спускаемся ниже и добавляем:

Code:

// Rifle
CVAR_REGISTER ( &sk_plr_snpr_bullet1 );// {"sk_plr_bullet1","0"};
CVAR_REGISTER ( &sk_plr_snpr_bullet2 );// {"sk_plr_bullet2","0"};
CVAR_REGISTER ( &sk_plr_snpr_bullet3 );// {"sk_plr_bullet3","0"};

После этого открываем gamerules.cpp и дописываем:

Code:

// Rifle
gSkillData.plrDmgSniper = GetSkillCvar( "sk_plr_snpr_bullet");

Потом в multiplay_gamerules.cpp добавляем:

Code:

// Rifle
gSkillData.plrDmgSniper = 100;//значения могут быть любыми, это убойная сила винтовки в мультиплеере

Если вы хотите, чтобы винтовку можно было получить с помощью команды impulse 101, то откройте player.cpp и сделайте следующее:

Code:

case 101:
   gEvilImpulse101 = TRUE;
   GiveNamedItem( "item_suit" );
   GiveNamedItem( "item_battery" );
   GiveNamedItem( "weapon_crowbar" );
   GiveNamedItem( "weapon_9mmhandgun" );
   GiveNamedItem( "ammo_9mmclip" );
   GiveNamedItem( "weapon_shotgun" );
   GiveNamedItem( "ammo_buckshot" );
   GiveNamedItem( "weapon_9mmAR" );
   GiveNamedItem( "ammo_9mmAR" );
   GiveNamedItem( "ammo_ARgrenades" );
   GiveNamedItem( "weapon_handgrenade" );
   GiveNamedItem( "weapon_tripmine" );
   GiveNamedItem( "weapon_knife" );
   GiveNamedItem( "weapon_sniperrifle" );//новая строчка
   #ifndef OEM_BUILD

Затем в файле skill.h добавьте:

Code:

float plrDmgSniper;

После в weapons.cpp в функцию void W_Precache(void) добавьте

Code:

// Rifle
UTIL_PrecacheOtherWeapon( "weapon_sniperrifle" );
UTIL_PrecacheOther( "ammo_338" );

Потом надо добавить новые значения в weapons.h:

Code:

#define WEAPON_SNARK 15
#define WEAPON_KNIFE 16
#define WEAPON_SNIPERRIFLE 17//Новая строчка

Ниже:

Code:

#define SNARK_WEIGHT -10
#define KNIFE_WEIGHT 10
#define SNIPERRIFLE_WEIGHT 10//Новая строчка

Затем ещё ниже:

Code:

#define TRIPMINE_MAX_CARRY 8
#define SNARK_MAX_CARRY 15
#define HORNET_MAX_CARRY 10
#define M203_GRENADE_MAX_CARRY 10
#define _338_MAX_CARRY 30//Максимум патронов для винтовки

И затем ещё ниже:

Code:

#define SATCHEL_MAX_CLIP WEAPON_NOCLIP
#define TRIPMINE_MAX_CLIP WEAPON_NOCLIP
#define SNARK_MAX_CLIP WEAPON_NOCLIP
#define SNIPERRIFLE_MAX_CLIP 10//Количество патронов в магазине у винтовки

Потом ещё ниже:

Code:

#define TRIPMINE_DEFAULT_GIVE 1
#define SNARK_DEFAULT_GIVE 5
#define HIVEHAND_DEFAULT_GIVE 10
#define SNIPERRIFLE_DEFAULT_GIVE 10//Патроны в магазине только что поднятой винтовки

Далее, разумеется, ещё ниже:

Code:

#define AMMO_RPGCLIP_GIVE RPG_MAX_CLIP
#define AMMO_URANIUMBOX_GIVE 20
#define AMMO_SNARKBOX_GIVE 5
#define AMMO_SNIPERRIFLECLIP_GIVE SNIPERRIFLE_MAX_CLIP//Сколько патронов в только что поднятой обойме

И, наконец в самом низу файла нужно вставить вот это:

Code:

class CSniperrifle : public CBasePlayerWeapon
{
   public:
   void Spawn( void );
   void Precache( void );
    int iItemSlot( void ) { return 2; }
   int GetItemInfo(ItemInfo *p);
   int AddToPlayer( CBasePlayer *pPlayer );
   void PrimaryAttack( void );
   void SecondaryAttack( void );
   BOOL Deploy( void );
   void Holster( int skiplocal = 0 );
   void Reload( void );
   void WeaponIdle( void );
   void Shoot( float flSpread, float flCycleTime, BOOL fUseAutoAim );
   float m_flSoundDelay;

   BOOL m_fInZoom;// don't save this.

   virtual BOOL UseDecrement( void )
   {
     #if defined( CLIENT_WEAPONS )
       return TRUE;
     #else
       return FALSE;
     #endif
   }

   private:
   unsigned short m_usFireSniper;
};

Так как винтовка это огнестрельное оружие, надо провести ещё несколько операций, для полной её работоспособности:

Открывем файл cbase.h и добавляем:

Code:

int ammo_9mm;
int ammo_357;
int ammo_bolts;
int ammo_buckshot;
int ammo_rockets;
int ammo_uranium;
int ammo_hornets;
int ammo_argrens;
int ammo_338;//Если мы создали для винтовки новые патроны, то придётся повозиться, иначе будут косяки с перезарядкой

После идём в client.cpp и в функции void UpdateClientData делаем так:

Code:

cd->ammo_rockets = pl->ammo_rockets;
cd->ammo_cells = pl->ammo_uranium;
cd->vuser2.x = pl->ammo_hornets;
cd->vuser2.y = pl->ammo_338;//Если это не сделать то время от времени у винтовки не будет рисоваться анимация перезарядки

!!!Внимание!!! параметр cd→vuser2.y обязательно должен отличаться от уже имеющихся cd→ammo_rockets, cd→vuser2.x и других подобных им

После этого идём в combat.cpp и добавляем в функцию Vector CBaseEntity::FireBulletsPlayer вот это:

Code:

case BULLET_PLAYER_BUCKSHOT:
// make distance based!
   pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgBuckshot, vecDir, &tr, DMG_BULLET);
   break;

case BULLET_PLAYER_357:
   pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET);
   break;

case BULLET_PLAYER_338:
   pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgSniper, vecDir, &tr, DMG_BULLET); //Вот она, убойная сила винтовки
   break;

После этого открываем player.cpp и дописываем в функцию void CBasePlayer::TabulateAmmo() это:

Code:

ammo_rockets = AmmoInventory( GetAmmoIndex( "rockets" ) );
ammo_uranium = AmmoInventory( GetAmmoIndex( "uranium" ) );
ammo_hornets = AmmoInventory( GetAmmoIndex( "Hornets" ) );
ammo_338 = AmmoInventory( GetAmmoIndex( "338" ) );//Патроны снайперки

После спускаемся к коду impulse 101 и дописываем:

Code:

#ifndef OEM_BUILD
   GiveNamedItem( "weapon_357" );
   GiveNamedItem( "ammo_357" );
   GiveNamedItem( "weapon_crossbow" );
   GiveNamedItem( "ammo_crossbow" );
   GiveNamedItem( "weapon_egon" );
   GiveNamedItem( "weapon_gauss" );
   GiveNamedItem( "ammo_gaussclip" );
   GiveNamedItem( "weapon_rpg" );
   GiveNamedItem( "ammo_rpgclip" );
   GiveNamedItem( "weapon_satchel" );
   GiveNamedItem( "weapon_snark" );
   GiveNamedItem( "weapon_hornetgun" );
   GiveNamedItem( "ammo_338" );//Получаем патроны для винтовки при повторном вводе impulse 101
#endif

После этого нам надо вернуться в weapons.h и добавить:

Code:

typedef enum
{
   BULLET_NONE = 0,
   BULLET_PLAYER_9MM, // glock
   BULLET_PLAYER_MP5, // mp5
   BULLET_PLAYER_357, // python
   BULLET_PLAYER_BUCKSHOT, // shotgun
   BULLET_PLAYER_CROWBAR, // crowbar swipe
   BULLET_PLAYER_338,//Для винтовки

   BULLET_MONSTER_9MM,
   BULLET_MONSTER_MP5,
   BULLET_MONSTER_12MM,
} Bullet;

С сервером всё, переходим на клиентскую сторону. Примечание редактора: не забудьте и на клиент, в папку хл, добавить файл rifle.cpp пунктом Add Files to Folder… в контекстном меню. В ev_hldm.cpp добавляем:

Code:

void EV_EgonStop( struct event_args_s *args );
void EV_HornetGunFire( struct event_args_s *args );
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );
void EV_Knife( struct event_args_s *args );
void EV_FireSniper( struct event_args_s *args );//Новая строчка

Потом спускаемся вниз и добавляем новый event:

Code:

//======================
// RIFLE START
//======================
enum sniperrifle_e {
   SNIPERRIFLE_DRAW = 0,
   SNIPERRIFLE_SLOWIDLE,
   SNIPERRIFLE_FIRE1,
   SNIPERRIFLE_FIRELASTROUND,
   SNIPERRIFLE_RELOAD,
   SNIPERRIFLE_RELOAD2,
   SNIPERRIFLE_SLOWIDLEEMPTY,
   SNIPERRIFLE_HOLSTER,
};

void EV_FireSniper( event_args_t *args )
{
   int idx;
   int empty;
   vec3_t origin;
   vec3_t angles;
   vec3_t velocity;

   vec3_t vecSrc, vecAiming;
   vec3_t up, right, forward;
   float flSpread = 0.01;

   idx = args->entindex;
   VectorCopy( args->origin, origin );
   VectorCopy( args->angles, angles );
   VectorCopy( args->velocity, velocity );
   empty = args->bparam1;

   AngleVectors( angles, forward, right, up );


   if ( EV_IsLocal( idx ) )
   {
     // Add muzzle flash to current weapon model
     EV_MuzzleFlash();
     gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? SNIPERRIFLE_FIRELASTROUND : SNIPERRIFLE_FIRE1, 2 );

     V_PunchAxis( 0, -20.0 );
   }

   gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sniper_fire1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );


   EV_GetGunPosition( args, vecSrc, origin );

   VectorCopy( forward, vecAiming );

   EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_338, 0, 0, args->fparam1, args->fparam2 );
}
//======================
// RIFLE END
//======================

Потом идём в файл view.cpp

Code:

{ "models/p_shotgun.mdl", "models/v_shotgun.mdl" },
{ "models/p_squeak.mdl", "models/v_squeak.mdl" },
{ "models/p_tripmine.mdl", "models/v_tripmine.mdl" },
{ "models/p_satchel_radio.mdl", "models/v_satchel_radio.mdl" },
{ "models/p_satchel.mdl", "models/v_satchel.mdl" },
{ "models/p_knife.mdl", "models/v_knife.mdl" },
{ "models/p_sniper.mdl", "models/v_sniper.mdl" },//Новая строчка

После открываем hl_events.cpp

Code:

void EV_HornetGunFire( struct event_args_s *args );
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );
void EV_Knife( struct event_args_s *args );
void EV_FireSniper( struct event_args_s *args );//Новая строчка

Затем спускаемся ниже:

Code:

gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
gEngfuncs.pfnHookEvent( "events/knife.sc", EV_Knife );
gEngfuncs.pfnHookEvent( "events/sniper.sc", EV_FireSniper );//Новая строчка

И последний файл клиента hl_weapons.cpp

Code:

CHgun g_HGun;
CHandGrenade g_HandGren;
CSatchel g_Satchel;
CTripmine g_Tripmine;
CSqueak g_Snark;
CKnife g_Knife;
CSniperrifle g_Sniperrifle;//Новая строчка

Затем ниже в функции void HUD_InitClientWeapons( void )

Code:

HUD_PrepEntity( &g_HGun , &player );
HUD_PrepEntity( &g_HandGren , &player );
HUD_PrepEntity( &g_Satchel , &player );
HUD_PrepEntity( &g_Tripmine , &player );
HUD_PrepEntity( &g_Snark , &player );
HUD_PrepEntity( &g_Knife , &player );
HUD_PrepEntity( &g_Sniperrifle , &player );//Новая строчка

Ещё ниже к подобным параметрам пишем:

Code:

case WEAPON_SNIPERRIFLE:
   pWeapon = &g_Sniperrifle;
   break;

На этом кодинг винтовки закончен. Начинаем работу с оптическим прицелом. Добавляем в клиент zoom.cpp

Code: zoom.cpp

#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
#include "hud_servers.h"
#include "vgui_int.h"
#include "vgui_TeamFortressViewport.h"
#include "triangleapi.h"
#include "r_studioint.h"
#include "com_model.h"


#include <string.h>
#include <stdio.h>

extern engine_studio_api_t IEngineStudio;

void DrawQuad(float xmin, float ymin, float xmax, float ymax)
{
   //top left
   gEngfuncs.pTriAPI->TexCoord2f(0,0);
   gEngfuncs.pTriAPI->Vertex3f(xmin, ymin, 0);
   //bottom left
   gEngfuncs.pTriAPI->TexCoord2f(0,1);
   gEngfuncs.pTriAPI->Vertex3f(xmin, ymax, 0);
   //bottom right
   gEngfuncs.pTriAPI->TexCoord2f(1,1);
   gEngfuncs.pTriAPI->Vertex3f(xmax, ymax, 0);
   //top right
   gEngfuncs.pTriAPI->TexCoord2f(1,0);
   gEngfuncs.pTriAPI->Vertex3f(xmax, ymin, 0);
}

DECLARE_MESSAGE(m_Zoom, ZoomHUD)

int CHudZoom::Init()
{
   m_iHudMode = 0;
   HOOK_MESSAGE(ZoomHUD);

   m_iFlags |= HUD_ACTIVE;

   gHUD.AddHudElem(this);
   return 1;
}

int CHudZoom::VidInit()
{
   m_hBottom_Left = SPR_Load("sprites/weapon_sniperrifle/sniper_bottom_left.spr");
   m_hBottom_Right = SPR_Load("sprites/weapon_sniperrifle/sniper_bottom_right.spr");
   m_hTop_Left = SPR_Load("sprites/weapon_sniperrifle/sniper_top_left.spr");
   m_hTop_Right = SPR_Load("sprites/weapon_sniperrifle/sniper_top_right.spr");
   m_hBlack = SPR_Load("sprites/weapon_sniperrifle/sniper_black.spr");
   m_iHudMode = 0;
   return 1;
}

int CHudZoom::MsgFunc_ZoomHUD (const char *pszName, int iSize, void *pbuf )
{
   BEGIN_READ( pbuf, iSize );
   m_iHudMode = READ_BYTE();
   return 1;
}

int CHudZoom::Draw(float flTime)
{
   if(!IEngineStudio.IsHardware() || !m_hBottom_Left || !m_hBottom_Right || !m_hTop_Left || !m_hTop_Right ) return 0;

   if(!m_iHudMode) return 0;//draw scope

   gEngfuncs.pTriAPI->RenderMode(kRenderTransColor);
   gEngfuncs.pTriAPI->Brightness(1.0);
   gEngfuncs.pTriAPI->Color4ub(255, 255, 255, 255);
   gEngfuncs.pTriAPI->CullFace(TRI_NONE);
   float left = (ScreenWidth - ScreenHeight)/2;
   float right = left + ScreenHeight;
   float centerx = ScreenWidth/2;
   float centery = ScreenHeight/2;


   gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer( m_hTop_Left ), 0);
   gEngfuncs.pTriAPI->Begin(TRI_QUADS);
   DrawQuad(left, 0, centerx, centery);
   gEngfuncs.pTriAPI->End();

   gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer( m_hTop_Right ), 0);
   gEngfuncs.pTriAPI->Begin(TRI_QUADS);
   DrawQuad(centerx, 0, right, centery);
   gEngfuncs.pTriAPI->End();

   gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer( m_hBottom_Right ), 0);
   gEngfuncs.pTriAPI->Begin(TRI_QUADS);
   DrawQuad(centerx, centery, right, ScreenHeight);
   gEngfuncs.pTriAPI->End();

   gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer( m_hBottom_Left ), 0);
   gEngfuncs.pTriAPI->Begin(TRI_QUADS);
   DrawQuad(left, centery, centerx, ScreenHeight);
   gEngfuncs.pTriAPI->End();

   gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer( m_hBlack ), 0);
   gEngfuncs.pTriAPI->Begin(TRI_QUADS);
   DrawQuad(0, 0, (left + 1), ScreenHeight);
   gEngfuncs.pTriAPI->End();

   gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer( m_hBlack ), 0);
   gEngfuncs.pTriAPI->Begin(TRI_QUADS);
   DrawQuad((right - 1), 0, ScreenWidth, ScreenHeight);
   gEngfuncs.pTriAPI->End();

   return 1;
}
В файле hud.cpp в функцию void CHud

Init( void ) добавляем:

Code:

m_StatusBar.Init();
m_DeathNotice.Init();
m_AmmoSecondary.Init();
m_TextMessage.Init();
m_StatusIcons.Init();

m_Zoom.Init();//новая строчка

GetClientVoiceMgr()->Init(&g_VoiceStatusHelper, (vgui:anel**)&gViewPort);
Потом, по такому же принципу в функцию void CHud

VidInit( void ) добавляем:

Code:

m_Menu.VidInit();
m_AmmoSecondary.VidInit();
m_TextMessage.VidInit();
m_StatusIcons.VidInit();

m_Zoom.VidInit();//Новая строчка

GetClientVoiceMgr()->VidInit();

После этого в hud.h создаём новый класс:

Code:

class CHudZoom: public CHudBase
{
   public:
   int Init( void );
   int VidInit( void );
   int Draw(float flTime);
   int MsgFunc_ZoomHUD(const char *pszName, int iSize, void *pbuf );
   int m_iHudMode;
   private:
   HSPRITE m_hBottom_Left;
   HSPRITE m_hBottom_Right;
   HSPRITE m_hTop_Left;
   HSPRITE m_hTop_Right;
   HSPRITE m_hBlack;
};

Ниже в описании самого класса CHud добавляем:

Code:

CHudSayText m_SayText;
CHudMenu m_Menu;
CHudAmmoSecondary m_AmmoSecondary;
CHudTextMessage m_TextMessage;
CHudStatusIcons m_StatusIcons;
CHudZoom m_Zoom;//новая строчка
Затем открываем hud_redraw.cpp и в функции int CHud

Redraw после

Code:

if (m_flShotTime && m_flShotTime < flTime)
{
   gEngfuncs.pfnClientCmd("snapshot\n");
   m_flShotTime = 0;
}

m_iIntermission = intermission;

добавляем:

Code:

if(m_Zoom.m_iHudMode > 0)
{
   m_Zoom.Draw( flTime );
   return 1;
}

Потом идём в ev_hldm.h и там аналогично добавляем:

Code:

BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_338, //добавляем наши патроны

С клиентом всё, идём на серверную сторону.

Открываем player.cpp и пишем:

Code:

extern void CopyToBodyQue(entvars_t* pev);
extern void respawn(entvars_t *pev, BOOL fCopyCorpse);
extern Vector VecBModelOrigin(entvars_t *pevBModel );
extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer );
extern int gmsgZoom;//Новая строчка

Затем чуть ниже:

Code:

int gmsgTextMsg = 0;
int gmsgSetFOV = 0;
int gmsgShowMenu = 0;
int gmsgGeigerRange = 0;
int gmsgTeamNames = 0;
int gmsgZoom = 0;//Новая строчка

Потом ещё ниже:

Code:

gmsgAmmoX = REG_USER_MSG("AmmoX", 2);
gmsgTeamNames = REG_USER_MSG( "TeamNames", -1 );
gmsgStatusText = REG_USER_MSG("StatusText", -1);
gmsgStatusValue = REG_USER_MSG("StatusValue", 3);
gmsgZoom = REG_USER_MSG( "ZoomHud", 1);//Новая строчка

Теперь нам надо задать условие, при котором на экране будет отображаться оптический прицел. Прокрутим вниз до функции void CBasePlayer :: UpdateClientData( void )

и добавим в неё:

Code:

if ( m_iFOV != 0 && m_iFOV != 20 && m_iFOV != 40 )
{
   MESSAGE_BEGIN( MSG_ONE, gmsgZoom, NULL, pev );
   WRITE_BYTE(1);
   MESSAGE_END();
}

Если вы хотите, чтобы оптический прицел рисовался не только у снайперки, но и у арбалета и револьвера, то уберите условия m_iFOV != 20 и m_iFOV != 40 (20 это арбалет, а 40 это револьвер) И не забывайте стирать лишние &&

В этой же функции замените условие

Code:

if ( m_iFOV != m_iClientFOV )
{
   MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
   WRITE_BYTE( m_iFOV );
   MESSAGE_END();

   // cache FOV change at end of function, so weapon updates can see that FOV has changed
}

На вот это:

Code:

if ( m_iFOV != m_iClientFOV )
{
   MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
   WRITE_BYTE( m_iFOV );
   MESSAGE_END();

   MESSAGE_BEGIN( MSG_ONE, gmsgZoom, NULL, pev );
   WRITE_BYTE(0);
   MESSAGE_END();

   // cache FOV change at end of function, so weapon updates can see that FOV has changed
}

Нам ведь нужно чтобы оптический прицел отключался.

В конец файла skill.cfg добавьте

Code:

sk_plr_snpr_bullet1 "100"
sk_plr_snpr_bullet2 "100"
sk_plr_snpr_bullet3 "100"

На этом всё, не забудте создать файл sniper.sc в папке events вашего мода.

P.S. Спасибо, Дядя Миша, за тутор по оптическому прицелу



Похожие1. Добавление ножа из Op4 - Добавление ножа из Op4
2. weapon_flamethrower - Играя в Халф-Лайф, вы не задумывались над тем, что в нем чего-то не хватает? Чего-то очень близкого, родного, горячего...
3. Создание нового ствола - Создание нового ствола с новыми патронами
4. Trigger_PlayerFreeez - Trigger_PlayerFreeez (остановка игрока)
5. Удалённый контроль зарядника - Всегда хотелось, чтобы зарядник в хл был управляемым.
6. Создание кооперативного прохождения - Данный тутор покажет как сделать в вашем моде кооператив.
7. субтитры из паранойи - субтитры из паранойи.
8. Как сделать вортигонта из HL1 другом - Моя первая статья
Ссылки на объект
Полная ссылка на текущем языке :
Короткая ссылка :
Ссылка на превью-картинку :
Ссылка на картинку в полном размере :
Ссылка для вашего форума или сайта
BB код ссылка:
BB код ссылка с картинкой :
BB код картинки :
HTML код ссылка:
HTML код ссылка с картинкой :
HTML код картинки :
Вы не можете комментировать, т.к. вы не зарегистрированы.
    Рождественский пак By TeMM!)))0
    Sven Co-opРождественский пак By TeMM!)))0
    Motoko Kunasagi (GitS FA SACO)
    Resident Evil 6Motoko Kunasagi (GitS FA SACO)
    Ada Wong Hot Replacement
    Ada Wong Hot Replacement
    Ada Wong Joins The Evening Express (v.2.0)
    Ada Wong Joins The Evening Express (v.2.0)