Суббота, 23.09.2017, 21:23

logo

Пользовательский поиск

Меню сайта
Категории раздела
Разное [13]
Tutorials
Создание моделей [2]
Создание карт [26]
Кодинг [24]
Форма входа
Логин:
Пароль:
Наш сервер CS 1.6
Поиск
Наш опрос
Ваш возраст
Всего ответов: 148
Атмосфера
Друзья сайта


Главная » Статьи » HL Source Development » Кодинг

HUD элемент с обработкой сообщений из собственной энтити

HUD элемент с обработкой сообщений из собственной энтити

В данном учебнике будет рассмотрен процесс создания собственного HUD элемента для вывода простого текстового сообщения.
Сообщение будет отправлятся при помощи простой энтити на стороне сервера при помощи HUD-сообщения.
Также будет создана консольная переменная и комманда отвечающая за отображение элемента и присвоена новая клавиша для включения/выключения отображения данного элемента.
1. Создаем класс на стороне клиента
Для начала определимся с названием HUD элемента - пусть для данного учебника он будет HudMyTest, при создании собственного класса следуя общепринятой логике называем его добавляя букву C.
Создаем новый файл HudMyTest.cpp:
//Класс HUD элемента HudMyTest

#include "cbase.h"
#include "hud.h"
#include "hudelement.h"
#include "hud_macros.h"

#include <vgui_controls/Panel.h>
#include <vgui_controls/Frame.h>
#include <vgui/IScheme.h>
#include <vgui_controls/Label.h>
#include "iclientmode.h"

using namespace vgui;

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

//Объявление класса
class CHudMyTest : public CHudElement , public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CHudMyTest, vgui::Panel );
public:
    CHudMyTest( const char *pElementName ); //конструктор
    void Init( void ); //вызывается сразу после создания элемента
    void VidInit( void ); //тоже что и Init только вызывается один раз при загрузке карты
    void Reset(); //вызывается при сбросе HUD
    void Paint( void ); //данный метод вызывается в каждом фрейме, для отрисовки элемента на экране
    void OnThink(void); //также вызывается в каждом фрейме, для обновления информации
    void MsgFunc_MyTxtMessage( bf_read &msg );
private:
    vgui::Label *m_pTxtLabel; //Ярлык с названием элемента
    vgui::HScheme scheme; //Объект схемы для использования информации из схем
    char m_pText[1024];
    //C_BasePlayer *player; //указатель на объект игрока
};

//Регистрация класса для HUD элемента
DECLARE_HUDELEMENT( CHudMyTest );
//Регистрация приемника сообщений
DECLARE_HUD_MESSAGE( CHudMyTest, MyTxtMessage );

//Имплементация конструктора
CHudMyTest::CHudMyTest( const char *pElementName ) : CHudElement( pElementName ), vgui::Panel( NULL, "HudMyTest" )
{
    //Установка бита отображения
    SetHiddenBits( HIDEHUD_ALL );
    //можно использовать комбинацию задающую условие при котором будет видимым наш элемент,
    //например: HIDEHUD_NEEDSUIT | HIDEHUD_PLAYERDEAD устанавливает невидимость в случае отсутствия HEV-костюма и смерти игрока

    //Загрузка и применение схемы для данного элемента
    scheme = vgui::scheme()->LoadSchemeFromFile("resource/ClientScheme.res", "ClientScheme");
    SetScheme(scheme);

    //Установка родителя в иерархии экрана
    vgui::Panel *pParent = g_pClientMode->GetViewport();
    SetParent( pParent );

    //Создание ярлыка для отображения текста
    m_pTxtLabel = vgui::SETUP_PANEL(new vgui::Label(this,"NameLabel",""));

    //Применение схемы к ярлыку
    m_pTxtLabel->SetScheme(scheme);
    //установка шрифта
    m_pTxtLabel->SetFont(vgui::scheme()->GetIScheme(scheme)->GetFont("Default"));

    //Не использовать ввод с клавиатуры и мыши
    m_pTxtLabel->SetKeyBoardInputEnabled(false);
    m_pTxtLabel->SetMouseInputEnabled(false);

    //Установка расположения и размера
    m_pTxtLabel->SetPos(0,0);
    m_pTxtLabel->SetSize(GetWide(),GetTall());

    //Не отображать фон и рамку
    m_pTxtLabel->SetPaintBackgroundEnabled( false );
    m_pTxtLabel->SetPaintBorderEnabled( false );

    //Установка выравнивания текста, a_northwest означает влево-вверх
    m_pTxtLabel->SetContentAlignment( vgui::Label::a_northwest );

    //Прозрачный фон
    SetPaintBackgroundEnabled( false );
    SetBgColor(Color(0,0,0,0));
    m_pTxtLabel->SetBgColor(Color(0,0,0,0));
}

//Имплементация других методов

void CHudMyTest::Init( void )
{
    //Устанавливаем перехват сообщений
    HOOK_HUD_MESSAGE( CHudMyTest, MyTxtMessage );
    Reset();
}

void CHudMyTest::VidInit( void )
{
    Reset();
}

void CHudMyTest::Reset( void )
{
    //стираем содержимое текста
    sprintf(m_pText, "Empty");
}

void CHudMyTest::Paint( void )
{
    //определяем требуется ли отображать элемент
    ConVar *is_vis = cvar->FindVar( "myhud_visible" );
    if(!is_vis->GetBool()) return;
    //записать текст
    m_pTxtLabel->SetText(m_pText);
    //сделать видимым
    m_pTxtLabel->SetVisible(true);
    //реорганизовать размеры к новому тексту
    m_pTxtLabel->SizeToContents();
    m_pTxtLabel->SetSize(GetWide(), GetTall());
    //установить цвет
    m_pTxtLabel->SetFgColor(Color(255,255,240,255));
}

void CHudMyTest::OnThink(void)
{
    //определяем требуется ли изменить видимость элемента
    ConVar *is_vis = cvar->FindVar( "myhud_visible" );
    if(is_vis->GetBool()) SetVisible(true);
    else SetVisible(false);
}

void CHudMyTest::MsgFunc_MyTxtMessage( bf_read &msg )

{
    sprintf(m_pText, msg.ReadAndAllocateString());
}


//Создаем консольную переменную на стороне клиента для управления видимостью элемента
ConVar myhud_visible("myhud_visible", "0", FCVAR_NONE, "HudMyTest visibility", true, 0, true, 1);

//Создаем консольную комманду на стороне клиента для переключения видимости элемента
void CC_myhud_visible ( void )
{
    ConVar *is_vis = cvar->FindVar( "myhud_visible" );
    if(is_vis->GetBool())
        engine->ClientCmd( "myhud_visible 0" );
    else
        engine->ClientCmd( "myhud_visible 1" );
}
static ConCommand myhud( "myhud", CC_myhud_visible, "parameter");
Подключаем файл к проекту клиента client. 2. Редактируем scripts/HudLayout.res
В файле HudLayout.res (в директории scripts вашего мода) добавляем новую секцию с описанием нашего элемента
HudMyTest
{
    "fieldName" "HudMyTest"
    "visible" "1"
    "enabled" "1"
    "xpos" "15"
    "ypos" "200"
    "wide" "150"
    "tall" "150"
    "PaintBackgroundType" "0"
}
Если в директории scripts вашего мода нет файла HudLayout.res, вытащите его из source engine.gcf 3. Привязываем комманду к клавише
В файлах cfg/config.cfg и cfg/default_config.cfg добавте комманду
bind "TAB" "myhud"
Если таких файлов нет, вытащите из source engine.gcf. 4. Создаем класс энтити для сообщения Создадим файл MyTxtMessage.cpp и поместим в него класс CMyTxtMessage который будет отвечать за экземпляр энтити на сервере для отправки сообщения на HUD:
//Класс CMyTxtMessage
#include "cbase.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

//объявляем класс
class CMyTxtMessage : public CLogicalEntity
{
public:
    DECLARE_CLASS( CMyTxtMessage, CLogicalEntity );
    DECLARE_DATADESC();
    CMyTxtMessage( void ) {};
    //Input-функция для передачи данных (вызывается при помощи каких-нибудь output на карте)
    void InputSendMessage( inputdata_t &data );
    //Текстовая переменная
    string_t m_strText; };

//объявление данных энтити в таблице данных движка
BEGIN_DATADESC( CMyTxtMessage )

    DEFINE_KEYFIELD( m_strText, FIELD_STRING, "text" ),

    DEFINE_INPUTFUNC( FIELD_STRING, "SendMessage", InputSendMessage ),

END_DATADESC()

void CMyTxtMessage::InputSendMessage( inputdata_t &data )
{
    //Мы хотим отправлять сообщение локальному игроку
    CSingleUserRecipientFilter user( UTIL_PlayerByIndex(1) );
    user.MakeReliable();

    //Начало блока сообщения
    UserMessageBegin( user, "MyTxtMessage" );

    //Отправка текста клиенту
    WRITE_STRING( STRING( m_strText ) );

    //Конец блока сообщения
    MessageEnd();
}

//Связываем имя энтити для Hammer с классом энтити
LINK_ENTITY_TO_CLASS( my_txt_message, CMyTxtMessage );
Добавляем файл в проект сервера hl.
Теперь следует зарегистрировать HUD сообщение.
Для этого потребуется внести изменения в файлы client/usermessages.cpp и shared/hl2_usermessages.cpp добавим в обоих функциях RegisterUserMessages регистрацию сообщения "MyTxtMessage"
Должно получиться так:
void RegisterUserMessages( void )
{
    usermessages->Register( "Geiger", 1 );
    usermessages->Register( "Train", 1 );
    usermessages->Register( "HudText", -1 );

..........

    usermessages->Register( "TextMsg", -1 );
}
Следует обратить внимание что регистрация сообщения производится как на сервере (sharedhl2_usermessages.cpp) так и на клиенте (clientusermessages.cpp)
5. Создаем запись для энтити в .FGD файле
Для того чтоб можно было добавить энтить на карте создаем запись в FGD файле вашего мода:
@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = my_txt_message : "My text message entity"
[
    text(string) : "Value" : "Hello mod" : "Message value"
    input SendMessage(void) : "Input Action"
    output OnMessage(void) : "Output Action"
]
Eсли у вас используется FGD от Half-Life 2, создайте новый пустой текстовый файл с расширением FGD куда поместите данную запись, затем подключите этот файл с помощью опции меню настройки текущего проекта в Hammer. 6. Размещаем энтити на карте
Если правильно была создана запись в FGD файле, теперь можно добавить на карту новые энтити через инструмент добавления точечных энтитей в Hammer.
Добавляем две энтити my_txt_message и в поле Name пишем разные имена - Mymsg1 и Mymsg2, затем создаем два триггера trigger_multiple и также называем по разному - Trig1 и Trig2, и не забудть закрасить триггеры текстурой tools/toolstrigger.

Далее выбираем первый триггер Trig1 и устанавливаем в закладке Outputs связь с Mymsg1, так чтоб триггер реагировал на касание игрока, посилая output триггера в input энтити, как иллюстрирует рисунок ниже:

То же самое проделываем с второй парой Trig2 и Mymsg2
7. Финальные шаги
Компилируем DLL-ы client и server в Visual Studio (меню Build->Build Solution) и компилируем карту где мы размещали энтити.
Запускаем мод, запускаем данную карту, при нажатии клавиши TAB должно переключаться отображение нового HUD элемента с надписью "Empty".
Подходим к первому месту где мы установили триггер связанный с первой энтитью (Mymsg1), как только сработает триггер увидем сменившуюся надпись "Hello from First!", теперь подходим к труггому тригеру, видим новую надпись "Hello from Second!".
Дальше вы уже самостоятельно сможите наращивать функциональность для подобных серверных энтитей и добавлять в интерфейс мода собственные элементы модифицировав под свои потребности.
Автор: DarkLight
Категория: Кодинг | Добавил: SuperStart (18.10.2010)
Просмотров: 638 | Рейтинг: 0.0/0 |


Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Copyright www.akksimo.net © 2017