Shambler team
Статьи по программированию под движком Gold Source (игры Half-Life 1) и работе с SDK

Создание нового оружия

Это перевод статьи Persuter`a с http://articles.thewavelength.net/183/

В этом руководстве НЕ будет объяснено, КАК сделать принципиально новое оружие, ибо для каждого оружия нужен свой код. Здесь на примере копирования типа оружия просто будет приведена информация о тех нюансах, без которых ваше оружие не будет работать.

Оружие мы сделаем на базе mp5, которое будет называться просто — ExampleGun

Чтобы попасть в проект, открываем серверную часть — рабочий файл C++ hl.dsw

Для начала давайте напишем текст программы нашего оружия (пока не вставляя в проект), код у нас будет очень простой (фрагмент кода 1):


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

LINK_ENTITY_TO_CLASS( weapon_example, CExampleGun );

void CExampleGun::Spawn( )
{
pev->classname = MAKE_STRING("weapon_example"); // здесь имя объекта (энтити), которое надо будет вписать в файл .fgd
Precache( );
SET_MODEL(ENT(pev), "models/w_9mmAR.mdl"); // Тут должна быть модель вашего оружия
m_iId = WEAPON_EXAMPLE;

m_iDefaultAmmo = 50;

FallInit();

}


void CExampleGun::Precache( void )
{

// Тут вы прекешите звуки и модели для вашего оружия
PRECACHE_MODEL("models/v_9mmAR.mdl");
PRECACHE_MODEL("models/w_9mmAR.mdl");
PRECACHE_MODEL("models/p_9mmAR.mdl");

PRECACHE_SOUND("items/9mmclip1.wav");

PRECACHE_SOUND("items/clipinsert1.wav");
PRECACHE_SOUND("items/cliprelease1.wav");

PRECACHE_SOUND ("weapons/hks1.wav");
PRECACHE_SOUND ("weapons/hks2.wav"); PRECACHE_SOUND ("weapons/hks3.wav");

// это для хука вашего события клиентской стороны
m_usExampleFire = PRECACHE_EVENT( 1, "events/example.sc" );
}

int CExampleGun::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "9mm";
p->iMaxAmmo1 = 200;
p->iMaxClip = -1;
p->iSlot = 3;
// категория оружия в костюме игрока (помните также, что если здесь вы написали например 2, то в игре будет занята 3 категория, т. к. в коде исчисление начинается от нуля)
p->iPosition = 4;
// позиция в категории (то же самое, что и для категории - если вам надо занять 4 позицию, то пишите 3 в коде)
p->iFlags = 0;
p->iId = m_iId = WEAPON_EXAMPLE;
p->iWeight = MP5_WEIGHT;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;

return 1;
}

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

Когда код вашего оружия готов, открывайте файл под названием weapons.cpp, и примерно в районе строчки 340 сделайте UTIL_PrecacheOtherWeapon, после mp5 (фрагмент кода 2):

// glock
UTIL_PrecacheOtherWeapon( "weapon_9mmhandgun" );
UTIL_PrecacheOther( "ammo_9mmclip" );

// mp5
UTIL_PrecacheOtherWeapon( "weapon_9mmAR" );
UTIL_PrecacheOther( "ammo_9mmAR" );
UTIL_PrecacheOther( "ammo_ARgrenades" );

// Тут добавляете прекеш своего оружия
// example_weapon

UTIL_PrecacheOtherWeapon( "weapon_example" );

Сохраняете это как example.cpp и добавляете в проект

Затем откройте файл weapons.h, и в районе строчки 89 и создайте определение имени своего оружия после снарка (фрагмент кода 3)

#define WEAPON_TRIPMINE 13
#define WEAPON_SATCHEL 14
#define WEAPON_SNARK 15
#define WEAPON_EXAMPLE 16

Затем идите вниз этого же файла и добавьте класс своего оружия под снарками. Выглядеть он должен так (фрагмент кода 4):

class CExampleGun : public CBasePlayerWeapon
{
public:

void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 4; }
int GetItemInfo(ItemInfo *p);

void PrimaryAttack( void );
void SecondaryAttack( void );
BOOL Deploy( void );
void WeaponIdle( void );
int AddToPlayer( CBasePlayer* );

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

private:
unsigned short m_usExampleFire;

};

После этого если хотите, можете добавить ваше оружие в список тех, кто будет спавниться в разбиваемых объектах (func_breakable)
Для этого откройте func_break.cpp и в районе строчки 62 добавьте свое оружие в список оружий, появляющихся при разбивании объекта (фрагмент кода 5):

const char *CBreakable::pSpawnObjects[] =
{
NULL, // 0
"item_battery", // 1
"item_healthkit", // 2
"weapon_9mmhandgun", // 3
"ammo_9mmclip", // 4
"weapon_9mmAR", // 5
"ammo_9mmAR", // 6
"ammo_ARgrenades", // 7
"weapon_shotgun", // 8
"ammo_buckshot", // 9
"weapon_crossbow", // 10
"ammo_crossbow", // 11
"weapon_357", // 12
"ammo_357", // 13
"weapon_rpg", // 14
"ammo_rpgclip", // 15
"ammo_gaussclip", // 16
"weapon_handgrenade", // 17
"weapon_tripmine", // 18
"weapon_satchel", // 19
"weapon_snark", // 20
"weapon_hornetgun", // 21
"weapon_example", // 22 - ваше оружие
};

Так, с серверной частью мы покончили - теперь идём в клиент (cl_dll.dsw)

В клиенте для начала откроем папку hl и в неё добавим наш example.cpp. Затем идём в файл ev_hldm.cpp и добавляем в районе строчки 67 свое оружие (фрагмент кода 6):

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_ExampleFire( struct event_args_s *args );
// ваше оружие

Идите вниз и там введите определение вашего оружия (фрагмент кода 7):

CHandGrenade g_HandGren;
CSatchel g_Satchel;
CTripmine g_Tripmine;
CSqueak g_Snark;
CExampleGun g_ExampleGun // ваше оружие

Затем всё в том же файле идите в район строчки 637 и добавьте там свое оружие (фрагмент кода 8):

HUD_PrepEntity( &g_HandGren , &player );
HUD_PrepEntity( &g_Satchel , &player );
HUD_PrepEntity( &g_Tripmine , &player );
HUD_PrepEntity( &g_Snark , &player );
HUD_PrepEntity( &g_ExampleGun , &player ); // ваше оружие

И наконец спуститесь в район строчки 761 и добавьте (фрагмент кода 9):

case WEAPON_TRIPMINE:
pWeapon = &g_Tripmine;
break;
case WEAPON_SNARK:
pWeapon = &g_Snark;
break;
case WEAPON_EXAMPLE: // ваше оружие
pWeapon = &g_ExampleGun;
break;

Теперь идите в файл hl_events.cpp, и там в районе строчки 40 добавьте (фрагмент кода 10):

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_ExampleFire( struct event_args_s *args ); // ваше оружие

Это, как вы заметили, то же самое, что вы сделали в начале ev_hldm.cpp. Теперь спуститесь в район строчки 88 и добавьте (фрагмент кода 11):

gEngfuncs.pfnHookEvent( "events/egon_stop.sc", EV_EgonStop );
gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
gEngfuncs.pfnHookEvent( "events/example.sc", EV_ExampleFire ); // ваше оружие

Теперь вы можете смело компилировать. После компиляции идите в каталог со своим модом, где создайте папку events, если таковой нет. В events создайте файл example.sc (содержимое этого файла можете скопировать из sc файла для mp5, который находится в pak файле). Затем зайдите в папку sprites своего мода и создайте там weapon_example.txt (содержимое также можете скопировать из mp5 и затем исправлять, так как там нужно указать спрайты, которые будут в отображаться в интерфейсе игрока при подборе и т. д.)

Вот пожалуй и всё, что вам надо для создания оружия. Если хотите создавать новое оружие с новыми эффектами, то работайте с основным кодом оружия, который я написал самым первым.

Спасибо за внимание!

Mitoh

Существует более простая статья "Взлом оружия — Докидываем патронов" от Jaturkenjensirhiv о менее заковыристых вещах - изменении отдельных параметров оружия в коде [примечание от ОбаГлаза].


Комментарии к этой статье на http://articles.thewavelength.net/183/ :

Оставлен от [NL]Mox 05 января 2004 в 11:48:13
Я думаю, что это руководство не описало части про боеприпасы и наносимые повреждения... Но оно действительно сто́ящее, об этом много вопросов на форумах. Я стану ссылаться на эту страницу чаще.

Оставлен от Persuter 07 января 2004 в 20:07:02
Я не написал, как создать новые типы боеприпасов, правда, но это просто потому, что не все хотят это делать. (В самом деле, это часто не имеет значения для сегодняшней одержимости тактическими модами. :D) А что касается нанесения повреждений, я предполагаю, что Вы имеете в виду функции основной атаки и вторичной. Я сознательно не включал ни это, ни большинство исходного кода оружия, потому что это учебник о том, что нужно сделать, а не о настоящем программировании оружия.
P.S. Эта статья хорошо работает для SDK версии 2.3.

Оставлен от Bryan 12 марта 2004 в 17:31:41
Думаю, было бы очень полезно для остальных, если бы Вы прошлись по использованию боеприпасов и нанесению повреждений.

это очень хорошее руководство gj.

Оставлен от jim_the_coder 16 марта 2004 в 17:50:53
"(В самом деле, это часто не имеет значения для сегодняшней одержимости тактическими модами. :D)" Я думаю, что вы бы лучше разобрались, чем поощрять увеличение клонов CS!

Оставлен от Persuter 17 марта 2004 в 06:18:55
Хорошо, при всей серьезности не вижу никакой причины добавлять новые типы боеприпасов в эти дни.

Оставлен от meastro 31 мая 2004 в 17:20:43
Если Вы хотите руководство, которое это делает, я набросал программный код-руководство, заходите на www.wired-mod.tk. Там вот что:
Как спрограммировать Desert-eagle;
Старое меню как в CStrike + Исправление и
Глок с глушителем и оптическим прицелом.

Оставлен от Persuter 5 июня 2004 в 20:05:32
Не собираюсь портить Вам парад, но на вашем сайте нет такой статьи.

Оставлен от MIFUNE 4 мая 2005 в 23:39:06
Я пытался сделать что-то похожее на это в моем моде. Я пытался заставить оружие стрелять правой и левой ружбайкой (оно двуручное), если вы нажимаете правую или левую кнопку мыши, то даже когда это работает (скопировал-вставил код от MP5), я не могу заставить появляться вспышку маззлфлеша в правом пистолете, а гильзы выбрасываются только от правого пистолета и появляются в середине экрана !!!

в чём проблема?

...

2004 Shambler Team
  Counter.CO.KZ -     !
Hosted by uCoz