В жизни каждого кодера под хл наступает такой интересный момент, когда ему нужно активировать что-либопри старте карты. Чаще всего это - передача мессаги на клиент. И тут кодеры сталкиваются с одним оченьнеприятным явлением - ни в обычной халфе, ни в спирите НЕТ нормальных методов, для активации мессаг при страте игры. Из Spawn вызывать нельзя - слишком рано. Activate()срабатыват чуть позже, но он идет перед LinkUserMessage, к тому же его используют другие энтити для своих целей и изменять время срабатывания крайне нежелательно, дабы не нарушить работу того же спирита. Продвинутые кодеры, вроде Бузера, не заморачиваясь вызывают нужные мессаги прямо из CBasePlayer (для спирита 1.6 я и сам так поступил, каюсь), но, во первых это неудобно, во вторых, просто некрасиво. В Спирите Лаури предложил нам свой метод: UTIL_DesiredAction Но... Вы видели, как эта шутка работает? - сначала CBaseEntity:Activate, потом pev->nextthink + а саму месаагу Лаури вызывает из тчинка, а если тчинк нам понадобится для других целей? Все это и побудило меня разработать xash PostActivate System. Система обладает следующими возможностями - она точно определяет время спавна игрока и вызывает некую функцию PostActivate, которая собсна и используется кодерами по их усмотрению - просто вставьте в классе своей энтити.
Функцию void PostActivate( void ); и вызывайте из нее все что хотите - это будет срабатывать каждый раз при старте карты. В класс CBaseEntity добавьте нашу новую функцию virtual void PostActivate ( void ) {} Теперь добавим собсно вызов нашей функции в client.cpp После инклудов вставьте вот это: BOOL MSGSended; float MsgDelay; а перед функцией StartFrame - вот этот код:
void ServerPostActivate( void ) { edict_t *pEdict = INDEXENT( 1 ); CBasePlayer *plr = (CBasePlayer*UTIL_PlayerByIndex(1); CBaseEntity *pClass; if(!pEdict || MSGSended) return;//player spawned ? //NOTE: Time to affect is obsolete delay before sendingmessage //Tune multiplayer time if need if ( MsgDelay > gpGlobals->time ) return; if (plr && !plr->m_fInitHUD && !gInitHUD) { for ( int i = 1; i < gpGlobals->maxEntities; i++,pEdict++ ) { if ( pEdict->free )continue; pClass = CBaseEntity::Instance(pEdict); if ( pClass && !(pClass->pev->flags &FL_DORMANT) ) { pClass->PostActivate(); } } MSGSended = TRUE;//messages sucessfully sended } }
Добавьте вызов этой функции непосредственно в StartFrame Теперь настроим время вызова из ClientPrecache - добавьте в самом начале этой функции следующие строки:
MSGSended = FALSE; if(IsMultiplayer()) MsgDelay = 0.5 + gpGlobals->time; else MsgDelay = 0.03 + gpGlobals->time;
Функция ISMultilplayer - это shared функция самого xash, замените её на g_pGameRules->isMultiplayer или как там оно выглядит в оригинальном хл :) MsgDelay - это время активации нашей фнукции - если поставить его слишком маленьким возможны проблемы. Здесь приведены оптимальные значения для сингла и мульта. Ну собсно и все, наслаждайтесь :)
Источник: http://www.hlfx.ru/forum/showthread.php?s=5ac665d08b0b17fd1b0b22cbbbc86ced&threadid=67 |