Конференции   |   Вход   |   Участники   |   Календарь   |   Поиск Сообщения за день   |   Все разделы прочитаны   |   Правила

Вернуться   Global Half-Life | Форум > Конференция Panther Studios > Half-Life SDK: Кодинг > [ Кодинг ] Туториалы

Ответ
 
Опции темы
Kerard
User
Kerard вне форума
 
Регистрация: 23.11.2022
Сообщений: 16
Arrow Винтовка Генри

Небольшое руководство по созданию многозарядной винтовки.
Решил внести свой вклад в развитие этого сайта.
Код снайперской винтовки уже есть, но она с отъемным магазином. Поэтому я решил сделать руководство по созданию магазинной винтовки с заряжанием по одному патрону. Винтовка не снайперская, но переделать ее в снайперскую не составит труда. Всем фанатам Дикого Запада посвящается! Хотя при желании, если немного подправить код, она подойдет и для Второй Мировой.
Итак, я решил показать вам, как сделать магазинную винтовку с заряжанием по одному патрону. За образец возьму винтовку Генри образца 1860 года. Почему ее? Она мне просто нравится. Хотя, при желании этот код, как уже говорилось выше, подойдет для любой неавтоматической винтовки с заряжанием по одному патрону – надо просто изменить количество патронов. Поскольку винтовки со скобой Генри часто выпускались под револьверный патрон, а также, чтобы избавить вас от лишнего геморроя, мы не будем создавать новый тип боеприпасов, а сделаем ее на основе патронов 357 Magnum.
Итак, начали.
Для начала создаем на сервере файл henry.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.
*
****/
#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"


enum henry_e 
{
    
HENRY_IDLE1 = 0,
    
HENRY_FIRE1,
    
HENRY_RELOAD,
    
HENRY_PUMP,
    
HENRY_START_RELOAD,
    
HENRY_DRAW,
    
HENRY_IDLE2,
    
HENRY_IDLE3
};

LINK_ENTITY_TO_CLASS( weapon_henry, CHenry );

int CHenry::GetItemInfo(ItemInfo *p)
{
    
p->pszName = STRING(pev->classname);
    
p->pszAmmo1 = "357";
    
p->iMaxAmmo1 = HENRY_MAX_CARRY;
    
p->pszAmmo2 = NULL;
    
p->iMaxAmmo2 = -1;
    
p->iMaxClip = HENRY_MAX_CLIP;
    
p->iFlags = 0;
    
p->iSlot = 2;
    
p->iPosition = 3;
    
p->iId = m_iId = WEAPON_HENRY;
    
p->iWeight = PYTHON_WEIGHT;

    return 
1;
}

int CHenry::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 CHenry::Spawn( )
{
    
pev->classname = MAKE_STRING("weapon_henry"); // hack to allow for old names
    
Precache( );
    
m_iId = WEAPON_HENRY;
    
SET_MODEL(ENT(pev), "models/w_henry.mdl");

    
m_iDefaultAmmo = HENRY_DEFAULT_GIVE;

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


void CHenry::Precache( void )
{
    
PRECACHE_MODEL("models/v_henry.mdl");
    
PRECACHE_MODEL("models/w_henry.mdl");
    
PRECACHE_MODEL("models/p_henry.mdl");

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

    
PRECACHE_SOUND ("weapons/357_cock1.wav");
    
PRECACHE_SOUND ("weapons/henry_shot1.WAV");
    
PRECACHE_SOUND ("weapons/henry_shot2.WAV");

    
m_usFireHenry = PRECACHE_EVENT( 1, "events/henry.sc" );
}

BOOL CHenry::Deploy( )
{
#ifdef CLIENT_DLL
    
if ( bIsMultiplayer() )
#else
    
if ( g_pGameRules->IsMultiplayer() )
#endif
    
{
        
// enable laser sight geometry.
        
pev->body = 1;
    }
    else
    {
        
pev->body = 0;
    }

    return 
DefaultDeploy( "models/v_henry.mdl", "models/p_henry.mdl", HENRY_DRAW, "henry", UseDecrement(), pev->body );
}

void CHenry::PrimaryAttack()
{
    
// don't fire underwater
    
if (m_pPlayer->pev->waterlevel == 3)
    {
        
PlayEmptySound( );
        
m_flNextPrimaryAttack = 0.15;
        return;
    }

    if (
m_iClip <= 0)
    {
        if (!
m_fFireOnEmpty)
            
Reload( );
        else
        {
            
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM);
            
m_flNextPrimaryAttack = 0.15;
        }

        return;
    }

    
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
    
m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;

    
m_iClip--;

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

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


    
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );

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

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

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

    
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usFireHenry, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );

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

    if (
m_iClip != 0)
        
m_flPumpTime = gpGlobals->time + 0.5;

    
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.1;
    if (
m_iClip != 0)
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
    else
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75;
    
m_fInSpecialReload = 0;
}




void CHenry::Reload( void )
{
    if (
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == HENRY_MAX_CLIP)
        return;

    
// don't reload until recoil is done
    
if (m_flNextPrimaryAttack > UTIL_WeaponTimeBase())
        return;

    
// check to see if we're ready to reload
    
if (m_fInSpecialReload == 0)
    {
        
SendWeaponAnim( HENRY_START_RELOAD );
        
m_fInSpecialReload = 1;
        
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.6;
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6;
        
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0;
        return;
    }
    else if (
m_fInSpecialReload == 1)
    {
        if (
m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
            return;
        
// was waiting for gun to move to side
        
m_fInSpecialReload = 2;

        
SendWeaponAnim( HENRY_RELOAD );

        
m_flNextReload = UTIL_WeaponTimeBase() + 0.8;
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.8;
    }
    else
    {
        
// Add them to the clip
        
m_iClip += 1;
        
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 1;
        
m_fInSpecialReload = 1;
    }
}


void CHenry::WeaponIdle( void )
{
    
ResetEmptySound( );

    
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

    if ( 
m_flPumpTime && m_flPumpTime < gpGlobals->time )
    {
        
m_flPumpTime = 0;
    }

    if (
m_flTimeWeaponIdle <  UTIL_WeaponTimeBase() )
    {
        if (
m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
        {
            
Reload( );
        }
        else if (
m_fInSpecialReload != 0)
        {
            if (
m_iClip != 15 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
            {
                
Reload( );
            }
            else
            {
                
// reload debounce has timed out
                
SendWeaponAnim( HENRY_PUMP );
                
                
m_fInSpecialReload = 0;
                
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.6;
            }
        }
        else
    {
    
int iAnim;
    
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
    if (
flRand <= 0.5)
    {
        
iAnim = HENRY_IDLE1;
        
m_flTimeWeaponIdle = (70.0/30.0);
    }
    else if (
flRand <= 0.7)
    {
        
iAnim = HENRY_IDLE2;
        
m_flTimeWeaponIdle = (70.0/30.0);
    }
    else
    {
        
iAnim = HENRY_IDLE3;
        
m_flTimeWeaponIdle = (88.0/30.0);
    }

    
int bUseScope = FALSE;
#ifdef CLIENT_DLL
    
bUseScope = bIsMultiplayer();
#else
    
bUseScope = g_pGameRules->IsMultiplayer();
#endif
    
    
SendWeaponAnim( iAnim, UseDecrement() ? 1 : 0, bUseScope );
        }
    }
}



class 
CHenryAmmo : public CBasePlayerAmmo
{
    
void Spawn( void )
    { 
        
Precache( );
        
SET_MODEL(ENT(pev), "models/w_357ammobox.mdl");
        
CBasePlayerAmmo::Spawn( );
    }
    
void Precache( void )
    {
        
PRECACHE_MODEL ("models/w_357ammobox.mdl");
        
PRECACHE_SOUND("items/9mmclip1.wav");
    }
    
BOOL AddAmmo( CBaseEntity *pOther ) 
    { 
        if (
pOther->GiveAmmo( AMMO_357BOX_GIVE, "357", _357_MAX_CARRY ) != -1)
        {
            
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
            return 
TRUE;
        }
        return 
FALSE;
    }
};
LINK_ENTITY_TO_CLASS( ammo_henry, CHenryAmmo );


#endif 
В этом коде все адаптировано под прилагаемую ниже модель, но при желании можно адаптировать его под нужную вам модель.

Последний раз редактировалось Kerard; 30.12.2022 в 13:56.
#1 Старый 18.12.2022, 17:59 Ответить с цитированием
Kerard
User
Kerard вне форума
 
Регистрация: 23.11.2022
Сообщений: 16
Red face

Теперь открываем файл weapons.h и пишем туда:

После:
С / С++:
#define M203_GRENADE_MAX_CARRY    10 
Пишем:
С / С++:
#define HENRY_MAX_CARRY            30 
После:
С / С++:
#define SNARK_MAX_CLIP            WEAPON_NOCLIP 
Пишем:
С / С++:
#define HENRY_MAX_CLIP            15 
После:
С / С++:
#define HIVEHAND_DEFAULT_GIVE        8 
Пишем:
С / С++:
#define HENRY_DEFAULT_GIVE            15 

После строчки:
С / С++:
#define WEAPON_SNARK        15 
Это:
С / С++:
#define WEAPON_HENRY            16 
Далее, в самом конце после снарков пишем:
С / С++:
class CHenry : public CBasePlayerWeapon
{
public:
    
void Spawn( void );
    
void Precache( void );
    
int iItemSlot( ) { return 3; }
    
int GetItemInfo(ItemInfo *p);
    
int AddToPlayer( CBasePlayer *pPlayer );

    
void PrimaryAttack( void );
    
BOOL Deploy( );
    
void Reload( void );
    
void WeaponIdle( void );
    
int m_fInReload;
    
float m_flNextReload;
    
int m_iShell;

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

private:
    
unsigned short m_usFireHenry;
}; 
В weapons.cpp в разделе void W_Precache(void) пишем:
С / С++:
// henry
UTIL_PrecacheOtherWeapon( "weapon_henry" ); 
Далее в player.cpp в разделе case101 пишем:
С / С++:
GiveNamedItem( "weapon_henry" ); 
Переходим в клиент.

В файле hl_weapons.cpp после:
С / С++:
CSqueak g_Snark; 
Пишем:
С / С++:
CHenry g_Henry; 
Затем после:
С / С++:
    HUD_PrepEntity( &g_Snark    , &player ); 
Пишем:
С / С++:
HUD_PrepEntity( &g_Henry    , &player ); 
И наконец после:
С / С++:
case WEAPON_SNARK:
            
pWeapon = &g_Snark;
            break; 
Пишем:
С / С++:
        case WEAPON_HENRY:
            
pWeapon = &g_Henry;
            break; 
Добавлено через 31 секунду
Открываем теперь ev_hldm.cppи после:

С / С++:
void EV_SnarkFire( struct event_args_s *args  ); 
Пишем:
С / С++:
void EV_FireHenry( struct event_args_s *args  ); 
Спускаемся ниже. После:
С / С++:
//======================
//        PHYTON END 
//         ( .357 )
//====================== 
Пишем:
С / С++:
//======================
//       HENRY START 
//======================
void EV_FireHenry( event_args_t *args )
{
    
int idx;
    
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 );

    
AngleVectors( angles, forward, right, up );

    if ( 
EV_IsLocal( idx ) )
    {
            
// Add muzzle flash to current weapon model
        
EV_MuzzleFlash();
        
gEngfuncs.pEventAPI->EV_WeaponAnimation( HENRY_FIRE1, 1 );

        
V_PunchAxis( 0, -10.0 );
    }

    switch( 
gEngfuncs.pfnRandomLong( 0, 1 ) )
    {
    case 
0:
        
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/henry_shot1.WAV", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
        break;
    case 
1:
        
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/henry_shot2.WAV", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
        break;
    }

    
EV_GetGunPosition( args, vecSrc, origin );
    
    
VectorCopy( forward, vecAiming );

    
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_357, 0, 0, args->fparam1, args->fparam2 );
}
//======================
//       HENRY END 
//====================== 
Теперь открываем файл hl_events.cpp

После:
С / С++:
void EV_SnarkFire( struct event_args_s *args ); 
Пишем:
С / С++:
void EV_FireHenry( struct event_args_s *args  ); 
И в самом конце:
С / С++:
gEngfuncs.pfnHookEvent( "events/henry.sc",    EV_FireHenry ); 
И наконец после:
С / С++:
enum gauss_e {
    
GAUSS_IDLE = 0,
    
GAUSS_IDLE2,
    
GAUSS_FIDGET,
    
GAUSS_SPINUP,
    
GAUSS_SPIN,
    
GAUSS_FIRE,
    
GAUSS_FIRE2,
    
GAUSS_HOLSTER,
    
GAUSS_DRAW
}; 
Пишем:
С / С++:
enum henry_e {
    
HENRY_IDLE1 = 0,
    
HENRY_FIRE1,
    
HENRY_RELOAD,
    
HENRY_PUMP,
    
HENRY_START_RELOAD,
    
HENRY_DRAW,
    
HENRY_IDLE2,
    
HENRY_IDLE3
}; 
Компилируем.

Затем создаем файл henry.sc. Если влом, он есть в архиве ниже.
И наконец в halflife.fgd в разделе // weapons пишем:
Цитата:
@PointClass base(Weapon, Targetx) studio("models/w_henry.mdl") = weapon_henry : "Henry" []
Всё.

Архив со всем необходимым:
Вложения
Тип файла: rar HenryRifle.rar (765.6 Кб, 88158 просмотров)

Последний раз редактировалось Kerard; 30.03.2023 в 15:01.
#2 Старый 18.12.2022, 18:01 Ответить с цитированием
Shadow762
Быдлокодер
 
Аватар для Shadow762
Shadow762 вне форума
 
Регистрация: 22.11.2015
Проживает: Гиде-то
Сообщений: 51
Профиль Steam
По умолчанию

Цитата:
Обновленный архив, поскольку наш уважаемый админ отказался дать возможность удалять и редактировать сообщения.
Не сердись, возможность есть, просто ограниченная по времени
Все в порядке)
__________________
#3 Старый 19.12.2022, 20:02 Ответить с цитированием
sektant91
User
 
Аватар для sektant91
sektant91 вне форума
 
Регистрация: 03.12.2022
Проживает: Астана
Сообщений: 5
По умолчанию

Kerard
Цитата:
Небольшое руководство по созданию многозарядной винтовки.
Посмотрел модель - аж захотелось вестерн какой-нибудь начать делать в стиле Wanted!
Модель, кстати, сам делал?
Если да, то очень даже солидно. Выстрелы, перезарядка.
Цитата:
Решил внести свой вклад в развитие этого сайта
За это спасибо от меня лично. Знаю этот сайт еще с тех пор, когда он был hl-faction.ru, затем halflife.zone
И вот сейчас, глобальный Half-Life.

Я не силен в программировании, поверхностно знаю моделирование и немного картострой.
Но, как я вижу, туториал хороший.

Продолжай в том же духе!
А я попробую помочь создателям с пополнением коллекции модов

Добавлено через 3 минуты
Kerard, P.S, не обижай админа, благодаря ему у нас есть этот сайт, а главное - форум
P.S.S, вон что он сделал с сайтом своих обидчиков
__________________
DVD kolleksıoneri
#4 Старый 20.12.2022, 00:25 Ответить с цитированием
Kerard
User
Kerard вне форума
 
Регистрация: 23.11.2022
Сообщений: 16
По умолчанию

Цитата:
Модель, кстати, сам делал?
Сам.
Спасибо за добрые слова)
#5 Старый 20.12.2022, 11:59 Ответить с цитированием
Shadow762
Быдлокодер
 
Аватар для Shadow762
Shadow762 вне форума
 
Регистрация: 22.11.2015
Проживает: Гиде-то
Сообщений: 51
Профиль Steam
По умолчанию

Цитата:
Kerard, P.S, не обижай админа, благодаря ему у нас есть этот сайт, а главное - форум
P.S.S, вон что он сделал с сайтом своих обидчиков
какие ужасные вещи Вы говорите)
Там не обидчики никакие, просто тот "человек" получил по заслугам)

Цитата:
Модель, кстати, сам делал?
у Kerard'а все модели авторские.
__________________
#6 Старый 20.12.2022, 19:25 Ответить с цитированием
Kerard
User
Kerard вне форума
 
Регистрация: 23.11.2022
Сообщений: 16
По умолчанию

Чтобы переделать винтовку в снайперскую нужно вписать в файл henry.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.
*
****/
#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"


enum henry_e 
{
    
HENRY_IDLE1 = 0,
    
HENRY_FIRE1,
    
HENRY_RELOAD,
    
HENRY_PUMP,
    
HENRY_START_RELOAD,
    
HENRY_DRAW,
    
HENRY_IDLE2,
    
HENRY_IDLE3
};

LINK_ENTITY_TO_CLASS( weapon_henry, CHenry );

int CHenry::GetItemInfo(ItemInfo *p)
{
    
p->pszName = STRING(pev->classname);
    
p->pszAmmo1 = "357";
    
p->iMaxAmmo1 = HENRY_MAX_CARRY;
    
p->pszAmmo2 = NULL;
    
p->iMaxAmmo2 = -1;
    
p->iMaxClip = HENRY_MAX_CLIP;
    
p->iFlags = 0;
    
p->iSlot = 1;
    
p->iPosition = 2;
    
p->iId = m_iId = WEAPON_HENRY;
    
p->iWeight = PYTHON_WEIGHT;

    return 
1;
}

int CHenry::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 CHenry::Spawn( )
{
    
pev->classname = MAKE_STRING("weapon_henry"); // hack to allow for old names
    
Precache( );
    
m_iId = WEAPON_HENRY;
    
SET_MODEL(ENT(pev), "models/w_henry.mdl");

    
m_iDefaultAmmo = HENRY_DEFAULT_GIVE;

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


void CHenry::Precache( void )
{
    
PRECACHE_MODEL("models/v_henry.mdl");
    
PRECACHE_MODEL("models/w_henry.mdl");
    
PRECACHE_MODEL("models/p_henry.mdl");

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

    
PRECACHE_SOUND ("weapons/357_reload1.wav");
    
PRECACHE_SOUND ("weapons/357_cock1.wav");
    
PRECACHE_SOUND ("weapons/henry_shot1.WAV");
    
PRECACHE_SOUND ("weapons/henry_shot2.WAV");

    
m_usFireHenry = PRECACHE_EVENT( 1, "events/henry.sc" );
}

BOOL CHenry::Deploy( )
{
#ifdef CLIENT_DLL
    
if ( bIsMultiplayer() )
#else
    
if ( g_pGameRules->IsMultiplayer() )
#endif
    
{
        
// enable laser sight geometry.
        
pev->body = 1;
    }
    else
    {
        
pev->body = 0;
    }

    return 
DefaultDeploy( "models/v_henry.mdl", "models/p_henry.mdl", HENRY_DRAW, "henry", UseDecrement(), pev->body );
}


void CHenry::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;
    }
    else if ( 
m_pPlayer->pev->fov != 10 )
    {
        
m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 10;
        
m_fInZoom = 1;
    }
    
    
pev->nextthink = UTIL_WeaponTimeBase() + 0.1;
    
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
}


void CHenry::PrimaryAttack()
{
    
// don't fire underwater
    
if (m_pPlayer->pev->waterlevel == 3)
    {
        
PlayEmptySound( );
        
m_flNextPrimaryAttack = 0.15;
        return;
    }

    if (
m_iClip <= 0)
    {
        if (!
m_fFireOnEmpty)
            
Reload( );
        else
        {
            
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM);
            
m_flNextPrimaryAttack = 0.15;
        }

        return;
    }

    
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
    
m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH;

    
m_iClip--;

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

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


    
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );

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

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

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

    
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usFireHenry, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 );

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

    if (
m_iClip != 0)
        
m_flPumpTime = gpGlobals->time + 0.5;

    
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.1;
    if (
m_iClip != 0)
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
    else
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75;
    
m_fInSpecialReload = 0;
}




void CHenry::Reload( void )
{
    if (
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 || m_iClip == HENRY_MAX_CLIP)
        return;

    
// don't reload until recoil is done
    
if (m_flNextPrimaryAttack > UTIL_WeaponTimeBase())
        return;

    if ( 
m_pPlayer->pev->fov != 0 )
    {
        
SecondaryAttack();
    }

    
// check to see if we're ready to reload
    
if (m_fInSpecialReload == 0)
    {
        
SendWeaponAnim( HENRY_START_RELOAD );
        
m_fInSpecialReload = 1;
        
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.6;
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6;
        
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0;
        return;
    }
        if ( 
m_pPlayer->pev->fov != 0 )
    {
        
SecondaryAttack();
    }
    else if (
m_fInSpecialReload == 1)
    {
        if (
m_flTimeWeaponIdle > UTIL_WeaponTimeBase())
            return;
        
// was waiting for gun to move to side
        
m_fInSpecialReload = 2;

        
SendWeaponAnim( HENRY_RELOAD );

        
m_flNextReload = UTIL_WeaponTimeBase() + 0.8;
        
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.8;
    }
    else
    {
        
// Add them to the clip
        
m_iClip += 1;
        
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 1;
        
m_fInSpecialReload = 1;
    }
}


void CHenry::WeaponIdle( void )
{
    
ResetEmptySound( );

    
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

    if ( 
m_flPumpTime && m_flPumpTime < gpGlobals->time )
    {
        
m_flPumpTime = 0;
    }

    if (
m_flTimeWeaponIdle <  UTIL_WeaponTimeBase() )
    {
        if (
m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
        {
            
Reload( );
        }
        else if (
m_fInSpecialReload != 0)
        {
            if (
m_iClip != 15 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
            {
                
Reload( );
            }
            else
            {
                
// reload debounce has timed out
                
SendWeaponAnim( HENRY_PUMP );
                
                
m_fInSpecialReload = 0;
                
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.6;
            }
        }
    else
    {
    
int iAnim;
    
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
    if (
flRand <= 0.5)
    {
        
iAnim = HENRY_IDLE1;
        
m_flTimeWeaponIdle = (70.0/30.0);
    }
    else if (
flRand <= 0.7)
    {
        
iAnim = HENRY_IDLE2;
        
m_flTimeWeaponIdle = (70.0/30.0);
    }
    else
    {
        
iAnim = HENRY_IDLE3;
        
m_flTimeWeaponIdle = (88.0/30.0);
    }

    
int bUseScope = FALSE;
#ifdef CLIENT_DLL
    
bUseScope = bIsMultiplayer();
#else
    
bUseScope = g_pGameRules->IsMultiplayer();
#endif
    
    
SendWeaponAnim( iAnim, UseDecrement() ? 1 : 0, bUseScope );
        }
    }
}



class 
CHenryAmmo : public CBasePlayerAmmo
{
    
void Spawn( void )
    { 
        
Precache( );
        
SET_MODEL(ENT(pev), "models/w_357ammobox.mdl");
        
CBasePlayerAmmo::Spawn( );
    }
    
void Precache( void )
    {
        
PRECACHE_MODEL ("models/w_357ammobox.mdl");
        
PRECACHE_SOUND("items/9mmclip1.wav");
    }
    
BOOL AddAmmo( CBaseEntity *pOther ) 
    { 
        if (
pOther->GiveAmmo( AMMO_357BOX_GIVE, "357", _357_MAX_CARRY ) != -1)
        {
            
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
            return 
TRUE;
        }
        return 
FALSE;
    }
};
LINK_ENTITY_TO_CLASS( ammo_henry, CHenryAmmo );


#endif 

Добавлено через 4 минуты

А в файле weapons.h пишем указанный выше код, но после:
С / С++:
void PrimaryAttack( void ); 
Пишем:
С / С++:
void SecondaryAttack( void ); 
И все. Снайперская винтовка готова.

Последний раз редактировалось Kerard; 18.01.2023 в 12:37.
#7 Старый 30.12.2022, 13:50 Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

На основе Vbulletin