Как создать свой мод CS Source

Dudoser228

Местный
Статус
offline
Регистрация
06.04.2016
Сообщения
234
Репутация
55
Здравствуйте, сегодня я попытаюсь доходчиво рассказать, как сделать свой мод CS Source v34.

Естественно я понимаю, версии v34 уже 10 лет (напомню, она 2006 года), и моды для этой игры уже не актуальны, однако я пытаюсь создать собственную игру на основе Source Enige.

И давайте составим план действий.

1. Меняем модели игроков и оружия (соответственно и текстуры)
2. Меняем оформление (HUD и меню) и звуки
3. Добавляем своё название в меню


Ну поехали.
1. Думаю про это достаточно много людей знает, но на всякий случай я вам расскажу.
Есть два варианта развития событий : Сложный и Простой .
Начну с простого - вы просто находите модельки с текстурами и звуками в интернете и просто добавляете в папку cstike Ничего сложного. Другое дело, когда вы хотите создать чисто свои модельки. Для этого вам понадобятся некоторые программы, которые будут предоставлены в Source SDK (его можно скачать со стима, либо же пиратскую версию в интернете) , так же MilkShape 3D (это программа для создания "скелета") , конвертер mdl'ок переводящий в формат читаемый MilkShapом - gmadconv, и плагин для фоторедактора, читающий vtf-формат (он же нам понадобится для изменения фонового изображения) . Сразу скажу, на фотошоп будет проще найти, чем на paint.net, но в интернете есть и для paint.net'a, к сожалению ссылку предоставить не могу. А дальше понадобятся ваши способности в художественной сфере. Дальше не забудьте поменять картинки в меню покупок оружия "cstrike\materials\VGUI\gfx\VGUI" , таким образом мы переходим ко второму пункту.


2. Заходим в папку cstrike\materials\console - видим файлы, которые содержат название "background" и обязательно формата vtf- это и есть фоны для нашей контры. Их мы и будем открывать в фоторедакторе и менять изображение на своё. Таким у вашей контры будет ваш фон. Так же я советую изменить файл startup_loading.vtf - Можно изменить надпись на слово "Загрузка" как это сделал я. Чтобы изменять HUD'ы вам понадобится программа : https://yadi.sk/d/jLfpGpZ8s6WLu .
Что касательно звуков. Все звуки находятся в папке : cstrike\sound , я советую поменять разговоры ботов и команды cstrike\sound\radio , cstrike\sound\bot (Если изначально у вас английская версия, можно поискать и русскую озвучку в интернете) . Так же можно добавить музыку в меню. Это делается проще простого . В папку cstrike\sound\UI заливаем любой музон и переименовываем его в gamestartup1.mp3, так же можно добавить звуки для кликов по кнопкам в меню . Опять же заливаем звуки и переименовываем buttonrollover.wav (звук кнопок), buttonclickrelease.wav (звук при выходе).


3. Как же добавить своё название меню и добавить кнопки подключения к этому серверу.
Заходим в папку cstrike и ищем GameInfo.txt , там меняем название в title "Название игры" (изначально было название Counter-strike) и title2 "название мода" (изначально здесь была надпись Source) , но не меняйте название игры в строке :game "Counter-Strike Source" иначе у вас не будут работать боты и подключение к серверам. Так же вы можете вставить исходник своего сайта в mtod.txt или просто написать себя как автора мода. Когда зайдёте в игру, увидите что название вашего мода в меню отображается некорректно, а почему ? Потому что вам нужно скачать любой шрифт в эту папку и переименовать в CSlogo.ttf в папке cstrike\resource , так же в этой папке вы можете поменять названия сторон, оружия в файле cstrike_russian.txt . Чтобы поменять кнопки в меню вам нужно открыть в этой же папке () файл GameMenu.res блокнотом, и добавить код:
Код:
"1"
    {
        "label" "Посетить Дарквеб"
        "command" "url http://dark2web.info"
    }
После клика на эту кнопку откроется наш любимый форм в браузере, который установлен по умолчанию.
Код:
"2"
    {
        "label" "Подключиться к вашему серверу"
        "command" "engine connect 255.255.255.255:27015"
    }
Все остальные кнопки желательно не трогать и не изменять.

Несколько советов.
1.При создании мода не играйте на серверах в интернете, так как при подключении к серверам к вам скачивается кэш, который утяжеляет вашу сборку.
2. Можно поменять значок ярлычка на рабочем столе вы можете нарисовать свой значок и закинуть в папку с контрой, и поменять название на cs.ico .
3. Чтобы можно было играть в интернете и осуществлять поиск по серверам с вашей сбоки , вам надо проверить наличие serverbrowser.vdf в папке platform, если же нету, скачать можно здесь : https://yadi.sk/d/uI7dH9iks6LGc

Теперь расскажу как добавить своё оружие (к сожалению на серверах не работает)
Статья пригодится тем, кто будет делать свою игру на Source Engine.

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

Обьяснение будет на примере кода.
И так для начала зайдём в Visual Studio и добавим в ваш проэкт с++ файл.
добавим его в Server.dll в src/dlls/hl2_dll.
Что бы добавить в сервер weapon_ak47.cpр надо нажать на него правой кнопкой и выбрать вкладочку add/add new item... а там уже выбрать формат .cрp и внизу написать название, в нашем случае это weapon_ak47, потом нажать open и вписать этот код.
Код:
#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
и наблюдаем за тем как это дело работает.


Благодарю за внимание !
Надеюсь статья была полезной.
 
Последнее редактирование:

klavaaq

Заблокированные
Статус
offline
Регистрация
02.04.2016
Сообщения
430
Репутация
236
Обратите внимание, если Вы хотите провести сделку с данным пользователем, на то, что он заблокирован.
Оформи норм, с
Код:
Кодом
, красивенько, так читать лениво даже
 

Dudoser228

Местный
Статус
offline
Регистрация
06.04.2016
Сообщения
234
Репутация
55
тема будет дополняться
 
Последнее редактирование: