Кодим оружие
Сегодня я расскажу вам как сделать простой Ak 47 с подробным описанием его функций и опций :) хз как вам на понятном языке обьяснить
сложные термены C++

Итак приступим…
Для того чтобы внедрить такое орудие убийства в ваш мод вам потребуется минимум знать как компилить проэкт в C++
И как туда добовлять cpp файл :)

Нус обьяснение самого тутора будет на примере кода.
И так для начала зайдём в Visual Studio и добавим в ваш проэкт с++ файл.
добавим его в Server.dll вот таким методом



И копируем туда этот код.
Прочитав сам код вы поймете как сделать простое оружие



// 15.02.06
// Кто кодил? Кодил Lolmen
// Как кодил? Сам! :D
// Весь код принадлежит протасову виталию и отправлен на изучение
// людьми сообщества Nashalife :)
// Вам разрешается его использовать по полной программе :)
#include «cbase.h» // засунем базу без неё никуда
#include «basehlcombatweapon.h» // определим какие свойства юзать бум юзать
#include «NPCevent.h» // для NPC
#include «basecombatcharacter.h» // для игрока
#include «AI_BaseNPC.h» // для AI
#include «player.h» // сам игрок
#include «game.h» // игра
#include «in_buttons.h» // для кнопок мыши
#include «AI_Memory.h» // для AI память
#include «soundent.h» // хз вродь звуки или чёто такое
// Обозначили все в своём классе
// Класс оружиеАк47 юзаем для него класс Автоматов :)
class CWeaponAK47: public CHLSelectFireMachineGun
{
DECLARE_DATADESC ();
public:
DECLARE_CLASS (CWeaponAK47, CHLSelectFireMachineGun);

CWeaponAK47();

DECLARE_SERVERCLASS ();

void Precache (void); // подгрузка
void AddViewKick (void); // как нас будет трясти при стрельбе
void SecondaryAttack (void); // вторичная атака
void ItemPostFrame (void); // оружие на каждый кадр
int GetMinBurst () { return 2; } // взять минимальный разброс
int GetMaxBurst () { return 6; } // взять максимальный разброс

virtual void Equip (CBaseCombatCharacter *pOwner); // когда NPC снабжен пушкой
bool Reload (void); // обозначим тип BOOL переключатель для перезарядки

float GetFireRate (void) { return 0.1f; } // скорость стрельбы
int CapabilitiesGet (void) { return bits_CAP_WEAPON_RANGE_ATTACK1; }

virtual const Vector& GetBulletSpread (void) // берем конус разброса
{
static const Vector cone = VECTOR_CONE_5DEGREES; // конус разброса от дула
return cone;
}

const WeaponProficiencyInfo_t *GetProficiencyValues (); // приоритеты

void Operator_HandleAnimEvent (animevent_t *pEvent, CBaseCombatCharacter *pOperator)
{
switch (pEvent->event)
{
case EVENT_WEAPON_SMG1: // Дает понять что мы юзаем опции SMG1 для NPC
{
Vector vecShootOrigin, vecShootDir; // дадим названия вкторам
QAngle angDiscard;
if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment (pEvent->options, vecShootOrigin, angDiscard)))
{
vecShootOrigin = pOperator->Weapon_ShootPosition (); // позиция откуда вылетают пули
}

CAI_BaseNPC *npc = pOperator->MyNPCPointer (); // найдём NPC
ASSERT (npc ≠ NULL); // если NPC нету то ждём его

vecShootDir = npc->GetActualShootTrajectory (vecShootOrigin); // куда NPC стрелять

WeaponSoundRealtime (SINGLE_NPC); // звук для NPC

CSoundEnt::InsertSound (SOUND_COMBAT, pOperator->GetAbsOrigin (), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator); // параметры звука
pOperator->FireBullets (1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED,
MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2, entindex (), 0); //чем будет NPC стрелять
pOperator->DoMuzzleFlash (); // Будет мерцать Вспышка от выстрелов
m_iClip1 = m_iClip1 — 1; // сколько патронов займем за один выстрел
}
break;

default:
BaseClass::Operator_HandleAnimEvent (pEvent, pOperator);
break;
}
}

DECLARE_ACTTABLE ();
};
// начали использовать функции из класса
IMPLEMENT_SERVERCLASS_ST (CWeaponAK47, DT_WeaponAK47)
END_SEND_TABLE ()

LINK_ENTITY_TO_CLASS (weapon_ak47, CWeaponAK47);
PRECACHE_WEAPON_REGISTER (weapon_ak47);

BEGIN_DATADESC (CWeaponAK47)

END_DATADESC ()
acttable_t CWeaponAK47::m_acttable[] = // Активности (Анимации для NPC)
{
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, true }, // Скажем NPC что ему при выстреле нужно юзать анимку от SMG1
};
IMPLEMENT_ACTTABLE (CWeaponAK47);

//=========================================================
CWeaponAK47::CWeaponAK47()
{
// Конструктор для калаша
m_fMinRange1 = 64;// нет минимальной дальности полёта пули.
m_fMaxRange1 = 1400; // максимальная дальность полёта пули;
}
//-----------------------------------------------------------------------------
// Что делаем?: Подгружаем
//-----------------------------------------------------------------------------
void CWeaponAK47::Precache (void)
{

// что подгружаем? ничего просто инициализируем подгрузку
// но ниче не грузим :)
BaseClass::Precache ();
}
//-----------------------------------------------------------------------------
// Что делаем?: даем NPC более длинный маштаб полета пули.
//-----------------------------------------------------------------------------
void CWeaponAK47::Equip (CBaseCombatCharacter *pOwner)
{
if (pOwner->Classify () == CLASS_PLAYER_ALLY) // если пушка у игрока то
{
m_fMaxRange1 = 3000; // максммальный полёт пули
}
else // потому что пока она не у игрока полёт пули равен
{
m_fMaxRange1 = 1400; // равен 1400
}

BaseClass::Equip (pOwner);
}
//-----------------------------------------------------------------------------
// Что делаем? Делаем все для перезарядки
//-----------------------------------------------------------------------------
bool CWeaponAK47::Reload (void)
{
bool fRet; // переключатель
float fCacheTime = m_flNextSecondaryAttack; // время для перезарядки

fRet = DefaultReload (GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD); // что перезаряжаем? обойму 1 обойму 2 и юзаем анимку перезарядки ACT_VM_RELOAD
if (fRet) // если переключатель fRet включён, то
{
// Перекрываем доступ к вторичной атаке чтобы небыло багов
// Неразрешено стрелять когда мы перезаряжаемся
m_flNextSecondaryAttack = GetOwner ()->m_flNextAttack = fCacheTime;

WeaponSound (RELOAD); // звук из скрипта проиграем RELOAD
}

return fRet; // возратим fRet
}
//-----------------------------------------------------------------------------
// Что делаем? Добовляем потясывание экрана при стрельбе
//-----------------------------------------------------------------------------
void CWeaponAK47::AddViewKick (void)
{
#define EASY_DAMPEN 0.5f // легкое подергивание
#define MAX_VERTICAL_KICK 15.0f //макс вертикальный наклон в градусах
#define SLIDE_LIMIT 3.0f // всю эту батву будем делать за столько то секунд

//Кого трясти будем?
CBasePlayer *pPlayer = ToBasePlayer (GetOwner ()); // игрока: D

if (pPlayer == NULL)
return; // если игрока у нас нету то и трясти не будем!

DoMachineGunKick (pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT); // а вот это уже инициализирует все что мы набрали
}
//-----------------------------------------------------------------
// Че делаем? Проверяем не нажали ли геймер по кнопке мыши :)
// Первичный огонь у пушки вызывается по дефолту его не трогаем
// А вот что делать, если мы нажали по правой мыше,
// которая у нас стоит в настройках как вторичная атака?
//-----------------------------------------------------------------
void CWeaponAK47::ItemPostFrame (void)
{
// Если геймер есть то все ока :)
CBasePlayer *pOwner = ToBasePlayer (GetOwner ());
// Если геймера нету то пипец ниче не делаем :)
if (pOwner == NULL)
return;
// Если геймер нажал кнопку ATTACK2(подефолту правая кнопка мыши)
// то время вторичной атаки меньше либо равно текущему времени
if (pOwner->m_nButtons & IN_ATTACK2)
{
if (m_flNextSecondaryAttack <= gpGlobals->curtime)
{
SecondaryAttack (); // и тут мы вызовем функцию вторичной стрельбы оружия
pOwner->m_nButtons &= ~IN_ATTACK2; // а вот если ненажал кнопку ATTACK2
return;// то будем ждать пока нажмет :)
}
}

BaseClass::ItemPostFrame (); // используем и базовый класс тоже
}
//-----------------------------------------------------------------------------
// Что делаем? определяем что у нас будет вторичной Атакой :)
//-----------------------------------------------------------------------------
void CWeaponAK47::SecondaryAttack (void)
{
// А вот тут пока пусто сюда мы можем сделать :
// Приближение, Выстрел из подстволки, Удар штыком и тд
}
//------------------------------------------------------------------
// Что делаем? Опа самая непонятная чать «приоритеты оружия»
// Короче это определяет насколько крут наш ствол
// Если например в пистолете закончились патроны на что же сменить оружие
// В первую очередь? На самый крутой ствол :)
// Наш ствол будет покруче чем SMG :)
//-----------------------------------------------------------------
const WeaponProficiencyInfo_t *CWeaponAK47::GetProficiencyValues ()
{
static WeaponProficiencyInfo_t proficiencyTable[] =
{
{ 8.0, 0.75 },
{ 6.00, 0.75 },
{ 10.0/2.0, 0.75 },
{ 5.0/3.0, 0.75 },
{ 2.00, 1.0 },
};

COMPILE_TIME_ASSERT (ARRAYSIZE (proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); // а это нам сократит время компила пушки :)

return proficiencyTable;
}
Теперь зайдем в X:\\папку с вашим проэктом\\src\\cl_dll\\hl2_hud\\c_weapon__stubs_hl2.cpp
Откроем этот файлец и добавим туда строку
после:
STUB_WEAPON_CLASS (weapon_smg1, WeaponSMG1, C_HLSelectFireMachineGun);
вот эту
STUB_WEAPON_CLASS (weapon_ak47, WeaponAK47, C_HLSelectFireMachineGun);
Теперь компельнём проэкт :)
теперь самя малось осталось написать скрипт.
Скрипт напишем следующим образом
зайдем в папку с стимом там в SteamApps\\SourceMods\\папка с вашим модом\\scripts
и создадим там текстовик c именем weapon_ak47 след содержания :

// Small Machine Gun 1

WeaponData
{
// Weapon data is loaded by both the Game and Client DLLs.
«printname» «AK47»
«viewmodel» «models/weapons/v_smg1.mdl» // Замените модельку на вашу
«playermodel» «models/weapons/w_smg1.mdl» //Замените модельку на вашу
«anim_prefix» «smg2»
«bucket» «2»
«bucket_position» «9»

«clip_size» «39»
«default_clip» «30»

«primary_ammo» «SMG1»
«secondary_ammo» «None»

«weight» «3»
«item_flags» «0»

// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 «single_shot» sounds)
SoundData
{
«reload» «Weapon_SMG1.Reload»
«reload_npc» «Weapon_SMG1.NPC_Reload»
«empty» «Weapon_SMG1.Empty»
«single_shot» «Weapon_SMG1.Single»
«single_shot_npc» «Weapon_SMG1.NPC_Single»
«special1» «Weapon_SMG1.Special1»
«special2» «Weapon_SMG1.Special2»
«double_shot» «Weapon_SMG1.Double»
«burst» «Weapon_SMG1.Burst»
}

// Weapon Sprite data is loaded by the Client DLL.
TextureData
{
«weapon»
{
«font» «WeaponIcons»
«character» «a»
}
«weapon_s»
{
«font» «WeaponIconsSelected»
«character» «a»
}
«ammo»
{
«font» «WeaponIcons»
«character» «r»
}
«ammo2»
{
«font» «WeaponIcons»
«character» «t»
}
«crosshair»
{
«font» «Crosshairs»
«character» «Q»
}
«autoaim»
{
«file» «sprites/crosshairs»
«x» «0»
«y» «48»
«width» «24»
«height» «24»
}
}
}

Затем запускаем ваш мод…
В игре прописываем give weapon_ak47
и наблюдаем за тем как это дело работает.
Автор: Lolmen aka Протасов Виталий Александрович.
19 февраля 2006, 18:06