HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- Half-Life SDK (https://hlfx.ru/forum/forumdisplay.php?forumid=8)
-- проблема с вылетом игры. (https://hlfx.ru/forum/showthread.php?threadid=6149)
Отправлено илья2 13-02-2026 в 10:10:
проблема с вылетом игры.
в общем я делаю новый худ бар для игрока добавляя к монстру в функцию:
C++ Source Code:
1 | void CGargantua :: PrescheduleThink( void ) |
3 | MESSAGE_BEGIN( MSG_ONE, gmsgTankView, NULL, UTIL_PlayerByIndex( 1 )->pev ); |
но есть одна проблема когда я ставлю переменную в функции:
C++ Source Code:
cvar_t allowmonsters={"mp_allowmonsters","0", FCVAR_SERVER }; |
mp_allowmonsters с 0 на 1 игра в мультиплеере не запускается почему так происходит и как это исправить ?__________________
илья
Отправлено Ku2zoff 13-02-2026 в 14:32:
илья2 вывод консоли бы показал, что ли. Там должна быть написана причина. У тебя скорее всего мессага gmsgTankView ещё не зарегана на момент вызова CGargantua :: PrescheduleThink, поскольку вызывается эта функция через цепочку других функций из спавна монстра. Из спавна сообщения отправлять нельзя, чтобы это обойти в спирите была придумана функция DesiredAction. В старом ксашмоде PostActivate. В первой паранойе SendInitMessage. Лично мне больше всего нравится паранойевская реализация, она работает в мультиплеере для всех игроков, и не только при старте карты, а при коннекте игрока к серверу.
C++ Source Code:
1 | void CBasePlayer::SendInitMessages(void) |
3 | edict_t* pEdict = g_engfuncs.pfnPEntityOfEntIndex(1); |
8 | for (int i = 1; i < gpGlobals->maxEntities; i++, pEdict++) |
10 | if (pEdict->free) continue; |
12 | pEntity = CBaseEntity::Instance(pEdict); |
13 | if (!pEntity) continue; |
15 | pEntity->SendInitMessage(this); |
Это функция для игрока, она перебирает все энтити на уровне, и отсылает этому игроку сообщения от них.
C++ Source Code:
if (!m_bInitMessagesSent) |
m_bInitMessagesSent = TRUE; |
Это нужно вставить в UpdateClientData игрока. m_bInitMessagesSent = FALSE вставить в CBasePlayer :: Precache
Ну, собсно, добавить классу CBaseEntity функцию virtual void SendInitMessage(CBasePlayer* pPlayer) {};
И уже в коде гаргантюа сделать вот так:
C++ Source Code:
1 | void CGargantua::SendInitMessage(CBasePlayer* pPlayer) |
3 | MESSAGE_BEGIN( MSG_ONE, gmsgTankView, NULL, pPlayer->pev ); |
Отправлено илья2 13-02-2026 в 21:01:
да сработало офигеть спасибо после этого кода заработало как надо не вылетает теперь 
правда у меня тоже есть своя вариация исправления вылета но она немного нестандартная но тоже работает вот сам код:
if ( g_pGameRules->IsMultiplayer() )
{
m_iFirePhase++;
switch ( m_iFirePhase )
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
case 15:
MESSAGE_BEGIN( MSG_ONE, gmsgTankView, NULL, UTIL_PlayerByIndex( 1 )->pev );
WRITE_BYTE( 1 );
MESSAGE_END();
m_iFirePhase = 14;
break;
}
}
else
{
MESSAGE_BEGIN( MSG_ONE, gmsgTankView, NULL, UTIL_PlayerByIndex( 1 )->pev );
WRITE_BYTE ( 1 );
MESSAGE_END();
}
работает так функция идет по таймингу и запускается через некоторое время но потом запускается обратно через m_iFirePhase = 14; но здесь есть условие g_pGameRules->IsMultiplayer которая работает по двум пути если сингл то else без m_iFirePhase если мультиплеер то с m_iFirePhase вот как то так
но это функция тоже работает. Я так подумал что если функция не работает сразу то ей нужно некоторое время чтобы заработала вот и придумал совой самостоятельный костыль и был прав.
Добавлено 14-02-2026 в 00:01:
Видать после некоторого время она сама по себе регается и вылет исправляется сам по себе. Но это я уже не совсем втюкиваю как это работает но тоже работает.
__________________
илья
Отправлено Ku2zoff 14-02-2026 в 06:47:
Цитата:
илья2 писал:
работает так функция идет по таймингу и запускается через некоторое время
К этому времени срабатывает LinkUserMessages из player.cpp, и пользовательские мессаги успевают зарегаться.
Цитата:
илья2 писал:
после некоторого время она сама по себе регается
LinkUserMessages вызывается из двух мест: ServerActivate и CBasePlayer::Precache. Продублировано скорее всего именно по причине мультиплеера. Из ServerActivate вызывается и гарантированно срабатывает в сингле, а из CBasePlayer::Precache для каждого игрока в мультиплеере. Потому что игроки могут коннектиться к серверу в разное время.
Цитата:
илья2 писал:
ей нужно некоторое время чтобы заработала
Подход с плюсованием переменной ненадёжный. Нужно знать конкретную точку, когда мессаги зареганы, чтобы не промахнуться. То, что я предложил - система для всех энтить, чтобы при заходе на сервер каждый игрок получал мессагу от энтити, если есть необходимость. В твоём случае (если только один гарг отправляет сообщения, а остальные энтити нет) можно сильно всё упростить, и привести код вот к такому виду:
C++ Source Code:
1 | void CGargantua :: PrescheduleThink( void ) |
3 | CBaseMonster::PrescheduleThink(); |
5 | if ( !gmsgSelAmmo ) // проверка, обратная той, что используется в LinkUserMessages. Если сообщения не зареганы, ничего не отправляем |
12 | MESSAGE_BEGIN( MSG_ONE, gmsgTankView, NULL, UTIL_PlayerByIndex( 1 )->pev ); |
15 | tank_view_sent = TRUE; |
BOOL tank_view_sent добавить в класс гарга. В CGargantua::Precache tank_view_sent = FALSE.
Добавлено 14-02-2026 в 13:47:
А, блин. Опять же последний вариант только для сингла, потому что UTIL_PlayerByIndex(1). Надо ещё перебирать игроков.