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 :

The Event in Village (Случай в Деревне)The Event in Village (Случай в Деревне)

Зима. Мороз. Поздний вечер…...

13/05/2009
Stat ( tutorials ), pcs.

Создание нового ствола с новыми патронами


  • Description
  • HOW TO INSTALL

Создание нового ствола

Создание нового ствола с новыми патронами


Author/s of tutorial : Ghoul [BB]
Views : 1771 ( +1 )
Downloads : 0
Uploader : Streit
Created : 04/07/2011 8:38:50 PM
Source : http://www.half-life.ru/forum
Rating :
 ( 0 ) 
Share :


Following translations are available : | russian |

По многочисленным просьбам, как пришедшим на мой адрес, так и на этом форуме: "А как тебе удалось сделать стока стволов, да и как вообще можно проделать такое и т.д." я подробно опишу, как добавить новое оружие, с новым типом боеприпаса к нему. Будут затронуты как клиентная, так и серверная части..

Проверено на СДК 2.2, на коем и базируется мой мод. Я не гарантирую работу и 100% совместимость данного тутора на какой-либо другой модификации, в особенности это касается системы Spirit, со всеми ее эдишнами и билдами!

Итак, приступим. Серверная часть.

func_break.cpp, в классе *CBreakable:SpawnObjects[] добавляем под аналогичными образцами строку:

Code:

"weapon_awp",

Это дает нам выпадение оружия при разбивании ящиков на карте, если установлено число, соотв. позиции оружия в этом листе.. (для мапперов)

weapons.cpp, функция W_Precache(void) Прекэшим наше оружие.

Code:

UTIL_PrecacheOtherWeapon( "weapon_awp" );

Далее переходим в weapons.h, к аналогичным функциям стандартного оружия:

Code:

#define WEAPON_awp 16 //(ваш порядковый номер, у меня он 16)

Чуть ниже, среди похожих функций другого оружия:

Code:

class Cawp : public CBasePlayerWeapon
{
   public:
   void Spawn( void );
   void Precache( void );
   int iItemSlot( void ) { return 0; }
   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 );
   int m_iShell;


   BOOL m_fInZoom;

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

   private:
   unsigned short m_usawp;
};

Здесь мы обозначили все действия, которые оружие должно совершать. Они содержатся в самом файле оружия.

С сервером все, переходим к клиенту.

Находим hl_events.cpp, и регистрируем там используемый оружием эвент: в самом верху, под аналогичными функциями

Code:

void EV_Fireawp( struct event_args_s *args );

Далее, в конце файла:

Code:

gEngfuncs.pfnHookEvent( "events/awp.sc", EV_Fireawp );

Тут все. Переходим к hl_weapons.cpp. Под CMP5 g_Mp5; ставим

Code:

Cawp g_awp;

Спускаемся ниже, ищем HUD_PrepEntity( &g_Mp5, &player ); и ставим ниже

Code:

HUD_PrepEntity( &g_awp, &player );

Еще ниже найдем:

Code:

case WEAPON_MP5:
   pWeapon = &g_Mp5;
   break;

и вставим под ним:

Code:

case WEAPON_awp:
   pWeapon = &g_awp;
   break;

Фуух, вроде все! Перейдем к ev_hldm.cpp, где создадим само оружие (вернее, его эффекты - анимация, вспышка, вытряхивание гильз)

Найдем похожий случай для МП5:

Code:

void EV_FireMP5( struct event_args_s *args );

И добавим ниже

Code:

void EV_Fireawp( struct event_args_s *args );

Далее ищем void EV_FireMP5( event_args_t *args )

И под этим, после строк коммента

Code:

//======================
// MP5 END
//======================

Вставляем:

Code:

//======================
// AWP START
//======================
enum awp_e
{
   AWP_DRAW,
   AWP_IDLE1,
   AWP_FIRE1,
   AWP_FIRE2,
   AWP_RELOAD1,
   AWP_RELOAD2,
   AWP_RELOAD3,
   AWP_IDLE2,
   AWP_HOLSTER
};

void EV_Fireawp( 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 );

   dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight (0);
   dl->origin.x = origin.x;
   dl->origin.y = origin.y;
   dl->origin.z = origin.z;
   dl->radius = gEngfuncs.pfnRandomFloat( 330, 370 );
   dl->color.r = 210;
   dl->color.g = 200;
   dl->color.b = 60;
   dl->die = gEngfuncs.GetClientTime() + 0.06;

   if ( EV_IsLocal( idx ) )
   {
     EV_MuzzleFlash();
     gEngfuncs.pEventAPI->EV_WeaponAnimation( AWP_FIRE1 + gEngfuncs.pfnRandomLong(0,1), 2 );
     V_PunchAxis( 0, -10.0 );
   }

   gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/awp1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );//звук выстрела
   EV_GetGunPosition( args, vecSrc, origin );
   VectorCopy( forward, vecAiming );
   EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_338Magnum, 1, &tracerCount[idx-1], args->fparam1, args->fparam2 );//вылет пули
}

//======================
// AWP END
//======================

Ну вот и все. Не забываем добавить на сервере в проект wpn_awp.cpp. Но! Мы ж еще хотим, чтобы для нового оружия были новые боеприпасы, со своим уроном и т.п. Исправим!

Создание нового типа патронов. На сервере.

Откроем cbase.h, и под int ammo_9mm; поставим

Code:

int ammo_338Magnum;

Потом откроем client.cpp, под строкой

Code:

cd->vuser1.x = pl->ammo_9mm;

Втавим свою:

Code:

cd->vuser1.y = pl->ammo_338Magnum;

Потом в player.cpp, в void CBasePlayer::TabulateAmmo() { поставим

Code:

ammo_338Magnum = AmmoInventory( GetAmmoIndex( "338Magnum" ) );

Вот и все с патронами.

Новый тип пуль делается по аналогии… Примечание редактора: на этом заканчивался оригинальный текст данного тутора, но поскольку в коде оружия использованы пули BULLET_PLAYER_338Magnum которых нет в обычном хл, я написал продолжение к этому тутору которое добавляет этот тип пуль.

На сервере:

В combat.cpp:

Code:

case BULLET_PLAYER_BUCKSHOT:
   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_338Magnum: //Новые строчки
   pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg358Magnum, vecDir, &tr, DMG_BULLET);
   break;

В weapons.cpp :

Code:

case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357:
case BULLET_PLAYER_338Magnum: //Новая строка

В weapons.h:

Code:

BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_338Magnum, //Новая строка

В skill.h:

Code:

float plrDmgSatchel;
float plrDmgTripmine;
float plrDmg358Magnum; //Новая строка

В game.cpp :

Code:

// Tripmine
cvar_t sk_plr_tripmine1 = {"sk_plr_tripmine1","0"};
cvar_t sk_plr_tripmine2 = {"sk_plr_tripmine2","0"};
cvar_t sk_plr_tripmine3 = {"sk_plr_tripmine3","0"};

//Новые строки
cvar_t sk_plr_358Magnum1 = {"sk_plr_358Magnum1","0"};
cvar_t sk_plr_358Magnum2 = {"sk_plr_358Magnum2","0"};
cvar_t sk_plr_358Magnum3 = {"sk_plr_358Magnum3","0"};

Далее:

Code:

// Tripmine
CVAR_REGISTER ( &sk_plr_tripmine1 );// {"sk_plr_tripmine1","0"};
CVAR_REGISTER ( &sk_plr_tripmine2 );// {"sk_plr_tripmine2","0"};
CVAR_REGISTER ( &sk_plr_tripmine3 );// {"sk_plr_tripmine3","0"};

// Новые строчки
CVAR_REGISTER ( &sk_plr_358Magnum1 );
CVAR_REGISTER ( &sk_plr_358Magnum2 );
CVAR_REGISTER ( &sk_plr_358Magnum3 );

В gamerules.cpp

Code:

// Tripmine
gSkillData.plrDmgTripmine = GetSkillCvar( "sk_plr_tripmine");

// Новые строчки
gSkillData.plrDmg358Magnum = GetSkillCvar( "sk_plr_358Magnum");

Теперь переходим на клиент

В ev_hldm.cpp

Code:

case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357:
case BULLET_PLAYER_338Magnum://новая строка

Далее:

Code:

case BULLET_PLAYER_357:

   EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
   EV_HLDM_DecalGunshot( &tr, iBulletType );

   break;

case BULLET_PLAYER_338Magnum://новые строки

   EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
   EV_HLDM_DecalGunshot( &tr, iBulletType );

   break;

В ev_hldm.h :

Code:

BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_338Magnum,//новая строка

Теперь в skill.cfg вставляем в самый конец:

Code:

sk_plr_358Magnum1 "100"
sk_plr_358Magnum2 "100"
sk_plr_358Magnum3 "100"

Не забудьте создать файл awp.sc в папке events (содержимое можно скопировать из mp5.sc) Сам исходник Слонобоя (этот файл нужно добавить на сервер и на клиент) :

Code: wpn_awp.cpp

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

enum awp_e
{
   AWP_DRAW,
   AWP_IDLE1,
   AWP_FIRE1,
   AWP_FIRE2,
   AWP_RELOAD1,
   AWP_RELOAD2,
   AWP_RELOAD3,
   AWP_IDLE2,
   AWP_HOLSTER
};

LINK_ENTITY_TO_CLASS( weapon_awp, Cawp );

void Cawp::Spawn( )
{
   pev->classname = MAKE_STRING("weapon_awp");
   Precache( );
   SET_MODEL(ENT(pev), "models/w_awp.mdl");
   m_iId = WEAPON_awp;

   m_iDefaultAmmo = 10;

   FallInit();
}

void Cawp::Precache( void )
{
   PRECACHE_MODEL("models/v_awp.mdl");
   PRECACHE_MODEL("models/p_awp.mdl");
   PRECACHE_MODEL("models/w_awp.mdl");

   PRECACHE_SOUND ("weapons/awp1.wav");
   PRECACHE_SOUND ("weapons/zoom.wav");

   m_usawp = PRECACHE_EVENT( 1, "events/awp.sc" );
}

int Cawp::GetItemInfo(ItemInfo *p)
{
   p->pszName = STRING(pev->classname);
   p->pszAmmo1 = "338Magnum";
   p->iMaxAmmo1 = 30;
   p->pszAmmo2 = NULL;
   p->iMaxAmmo2 = -1;
   p->iMaxClip = 10;
   p->iSlot = 0;
   p->iPosition = 1;
   p->iFlags = 0;
   p->iId = m_iId = WEAPON_awp;
   p->iWeight = 20;

   return 1;
}

int Cawp::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;
}

BOOL Cawp::Deploy( )
{
   return DefaultDeploy( "models/v_awp.mdl", "models/p_awp.mdl", AWP_DRAW, "mp5" );
}


void Cawp::PrimaryAttack()
{

   if (m_pPlayer->pev->waterlevel == 3)
   {
     PlayEmptySound( );
     m_flNextPrimaryAttack = 0.15;
     return;
   }

   if (m_iClip <= 0)
   {
     PlayEmptySound();
     m_flNextPrimaryAttack = 0.15;
     return;
   }

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

   m_iClip--;

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

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

   m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

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

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

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

   PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usawp, 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)
     m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);


   m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.8;
   m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
}

void Cawp::SecondaryAttack( void )
{
   if ( m_pPlayer->pev->fov ==8 )
   {
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
     m_fInZoom = 0;
   }
   else if ( m_pPlayer->pev->fov == 40 )
   {
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 8;
     m_fInZoom = 1;
   }
   else if ( m_pPlayer->pev->fov == 0 )
   {
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 40;
     m_fInZoom = 2;
   }

   m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
   EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/zoom.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF));//проиграть звук
}

void Cawp::Holster( int skiplocal )
{
   m_fInReload = FALSE;

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

   SendWeaponAnim(AWP_HOLSTER);
   m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
   m_flTimeWeaponIdle = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );

}

void Cawp::Reload( void )
{
   if (m_pPlayer->pev->fov != 0 )
   {
     m_pPlayer->pev->fov = m_pPlayer->m_iFOV = 0;
     m_fInZoom = 0;
   }

   DefaultReload( 10, AWP_RELOAD1, 2.8 );
}


void Cawp::WeaponIdle( void )
{
   m_pPlayer->UpdateClientData();
   ResetEmptySound( );

   m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

   if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
     return;

   int iAnim;
   switch ( RANDOM_LONG( 0, 1 ) )
   {
     case 0:
       iAnim = AWP_IDLE1;
       break;

     default:
     case 1:
       iAnim = AWP_IDLE2;
       break;
   }

   SendWeaponAnim( iAnim );

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

class CawpAmmoClip : public CBasePlayerAmmo
{
   void Spawn( void )
   {
     Precache( );
     SET_MODEL(ENT(pev), "models/w_chainammo.mdl");
     CBasePlayerAmmo::Spawn( );
   }
   void Precache( void )
   {
     PRECACHE_MODEL ("models/w_chainammo.mdl");
     PRECACHE_SOUND("items/9mmclip1.wav");
   }
   BOOL AddAmmo( CBaseEntity *pOther )
   {
     int bResult = (pOther->GiveAmmo( 10, "338Magnum", 30) != -1);
     if (bResult)
     {
       EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
     }
     return bResult;
   }
};
LINK_ENTITY_TO_CLASS( ammo_338Magnum, CawpAmmoClip );

Спрайты, модели и звуки файле .

Примечание редактора: в исходном коде данного тутора содержались логические глюки, которые не удалось исправить не переписав весь код тутора, по этому использовать этот тутор рекомендуется только в целях обучения кодингу, но не использования в моде.



Similar1. Создание нового оружия - В этом туторе не будет объяснено КАК сделать новое оружие, ибо для каждого оружия нужен свой код. Здесь просто будет приведена информация о тех нюансах без которых ваше оружие не будет работать
2. Как адаптировать код к модели - Допустим, вы сделали новую модель для автомата MP5, но порядок и кол-во анимаций не сходятся.
3. Добавление новых классов для монстр - Мы будем добавлять новый класс Блэк Опс из Оппосинг Форс
4. Наследование классов в С++ - В этом туторе я попытаюсь кратко рассказать про наследование классов в С++
5. Функции движка - как и для чего - Функции движка - как и для чего их использовать?
6. Создание кооперативного прохождения - Данный тутор покажет как сделать в вашем моде кооператив.
7. Water Splash - Добавляем брызги при выстреле по воде
8. Добавление эффектов блеска для энтити (entity) - Данная статья - перевод урока от OsirisGodoftheDead с ModDB...
You cannot comment, because you are not logged-in.
    Blacktail V2
    Resident Evil 4Blacktail V2
    Anti-Material Rifle [Rifle Semi Altomático]
    Resident Evil 4Anti-Material Rifle [Rifle Semi Altomático]
    DSR-1 Standard [Rifle Semi Altomático]
    Resident Evil 4DSR-1 Standard [Rifle Semi Altomático]
    Glock 19 Realistic [Handgun]
    Resident Evil 4Glock 19 Realistic [Handgun]