Sign up - or - Login

Recover password
×

To recover your password, you must enter the username or e-mail that you used during the registration. After that, a mail with a security code will be sent to your inbox.

Your username or e-mail :

Escape from the DarknessEscape from the Darkness

Мод о побеге из Чёрной Мезы учёного по имени Алекс Джонс....

22/12/2002
Kreedz ClimbingKreedz Climbing

Сетевой мод для любителей преодолевать препятствия на время....

22/12/2008
Stat ( goldsrc map sources ), pcs.

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


  • Description
  • HOW TO INSTALL

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

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


Author/s of tutorial : Ku2zoff
Views : 2300 ( +1 )
Downloads : 0
Uploader : Streit
Created : 04/07/2011 8:43:22 PM
Source : http://www.hlfx.ru/forum
Rating :
 ( 3.67 ) 
Share :


Following translations are available : | russian |

Как я и обещал, я выложил снайперку (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 
#include 

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. Спасибо, Дядя Миша, за тутор по оптическому прицелу



Similar1. И снова наследование классов :) - Казалось бы тема наследования классов давно избита, ан нет всё ещё существуют вопросы, правда про чуть боле сложное наследование.
2. Динамическое освещение - этой статье будет описан способ добавления динамических вспышек света, которые можно использовать для еффекта молнии
3. Замедление игрока - Довольно забавно наблюдать, как игрок одинаково быстро бегает как с монтировкой в руках, так и с тяжелой базукой, хотя логичнее, что держа в руках сей девайс, он будет бегать медленнее
4. Создание кооперативного прохождения - Данный тутор покажет как сделать в вашем моде кооператив.
3037 06/24/2018, 11:25:31 AM commented :
#1
у меня вылетает игра после того как взял в руки оружие
You cannot comment, because you are not logged-in.
    Чикен из чикен гана
    Half-LifeЧикен из чикен гана
    Astrea: Six Sided Oracles (Раздача в EpicGamesStore)
    Astrea: Six Sided Oracles (Раздача в EpicGamesStore)
    Train Sim World 2: Sherman Hill: Cheyenne - Laramie Route Add-On
    Train Sim World 2: Sherman Hill: Cheyenne - Laramie Route Add-On
    Black Desert (Раздача в Steam)
    Black Desert (Раздача в Steam)