Функции движка - как и для чего их использовать?
Функции движка - как и для чего
Функции движка - как и для чего их использовать?
Author/s of tutorial : XaeroX Views : 1752 ( +1 ) Uploader : Streit Created : 04/07/2011 9:28:24 PM Source : http://www.hlfx.ru/forum Rating : ( 0 ) Share :
Following translations are available : |
russian |
Большая часть функциональности игровых DLL определяется функциями, предоставляемыми движком игры. Чтобы создавать собственные объекты и эффекты, вам необходимо хорошо в них разбираться. В этой статье я хочу рассмотреть функции серверной DLL, которые могут быть вам полезны – для чего они нужны и как им применять.
Все функции движка находятся в структуре enginefuncs_t, которая передается в DLL в функции GiveFnptrsToDll (“Give function pointers to DLL”). Она вызывается движком сразу после инициализации библиотеки и заполняет локальную копию структуры – переменную g_engfuncs. Вы можете вызывать эти функции двумя способами:
1) Прямой вызов по указателю, например: g_engfuncs. pfnMessageEnd();
2) Вызов при помощи макроса или инлайн-функции, предопределенных в файле enginecallback.h, например: MESSAGE_END();
Последний способ предпочтительнее, т.к. позволяет более гибко передавать параметры, например, использовать параметры по умолчанию. Впрочем, если вы в этом пока не очень хорошо разбираетесь, просто используйте второй способ. Я же буду приводить синтаксис вызова для обоих вариантов – название для первого и псевдоним для второго.
Хотелось бы сразу устранить некоторую путаницу со строками. В серверной части игры часто строки хранятся как целочисленные смещения (string_t), а функции движка работают только с массивами символов (char*). Поэтому string_t нужно преобразовать к char* вот таким способом:
char *pszTarget = const_cast<char*>(STRING(pev->target));
Таким образом, если вы получаете ошибку компиляции вида «cannot convert parameter 1 from int to 'char '», вам нужно сделать это преобразование.
Вы привыкли работать с классами, а функции движка понимают только edict_t в качестве ссылки на энтити. Тут преобразование просто:
1) Из указателя на класс: edict_t *pEdict = pMyClass→edict();
2) Из pev класса: edict_t *pEdict = ENT(pev);
Некоторые функции записывают свои значения по указателям, переданным в качестве параметров. Например, векторы записываются в указатель на массив float. Вам нужно самим проследить, что вы передали правильные параметры! Например, если функция заполняет вектор, то выглядеть вызов будет так:
float flVec[3];
MyFunctionThatFillsVector(flVec); //или MyFunctionThatFillsVector(&flVec[0]);
Vector vVec = Vector(flVec);
И с vVec вы уже можете работать, как привыкли.
Итак, переходим к рассмотрению самих функций.
pfnPrecacheModel
pfnPrecacheSound
pfnPrecacheGeneric
pfnSetModel
pfnModelIndex
pfnModelFrames
pfnSetSize
pfnChangeLevel
pfnGetSpawnParms
pfnSaveSpawnParms
pfnVecToYaw
pfnVecToAngles
pfnMoveToOrigin
pfnChangeYaw
pfnChangePitch
pfnGetEntityIllum
pfnSetClientMaxspeed
pfnGetGameDir
Название: pfnPrecacheModel
Псевдоним: PRECACHE_MODEL
Синтаксис: int PRECACHE_MODEL(char* s);
Эта функция загружает модель или спрайт в память и возвращает его индекс. Если модель не найдена, сервер отключит вас с ошибкой. Параметр s – имя модели или спрайта, например, “models/player.mdl”. Прежде чем использовать модель или спрайт в игре, их необходимо прекэшировать. Эта функция может быть вызвана только в функции Spawn класса (хотя ее обычно выносят в отдельную функцию Precache, чтобы ресурсы кэшировалась также после загрузки сохраненной игры, когда Spawn не вызывается).
Название: pfnPrecacheSound
Псевдоним: PRECACHE_SOUND
Синтаксис: int PRECACHE_SOUND(char* s);
Эта функция загружает звук в память (производя при необходимости конвертацию в поддерживаемый формат, если это возможно) и возвращает его индекс. Если звук не найдет, сервер создаст пустой звук. Параметр s – имя звукового файла, например, “common/null.wav”. Прежде чем использовать звук в игре, его необходимо прекэшировать. Ограничения на вызов те же, что и у pfnPrecacheModel (см. выше).
Название: pfnPrecacheGeneric
Псевдоним: PRECACHE_GENERIC
Синтаксис: int PRECACHE_GENERIC(char* s);
Эта функция проверяет наличие произвольного ресурса, загружает его и возвращает его индекс. Зачем этот индекс может понадобиться, знают только разработчики… А польза от функции в том, что при сетевой игре, если файл отсутствует у клиента, он будет ему закачан с сервера, и клиентская DLL сможет получить к нему доступ. Ограничения на вызов те же, что и у pfnPrecacheModel (см. выше).
Название: pfnSetModel
Псевдоним: SET_MODEL
Синтаксис: void SET_MODEL(edict_t *e, const char *m);
Устанавливает модель или спрайт для энтити. Ресурс должен быть прекэширован (при помощи PRECACHE_MODEL). Первый параметр – энтити (как правило, текущая, так что можете написать ENT(pev), второй – название модели (такое же, как в PRECACHE_MODEL, только для преобразования из string_t достаточно просто STRING, без const_cast’а).
Название: pfnModelIndex
Псевдоним: MODEL_INDEX
Синтаксис: int MODEL_INDEX(const char *m);
Возвращает индекс модели или спрайта (тот же, что и функция PRECACHE_MODEL). Параметр – имя модели (см. pfnSetModel).
Название: pfnModelFrames
Псевдоним: MODEL_FRAMES
Синтаксис: int MODEL_FRAMES(int modelIndex);
Функция работает со спрайтами и возвращает количество кадров анимации в них. Параметр – индекс спрайта, возвращаемый функциями PRECACHE_MODEL или MODEL_INDEX. Если была вызвана SET_MODEL, то для текущего спрайта вы также можете использовать pev→modelindex.
Название: pfnSetSize
Псевдоним: SET_SIZE
Синтаксис: void SET_SIZE(edict_t *e, const float *rgflMin, const float *rgflMax);
Устанавливает размер Bounding Box энтити (ее размер для проверки столкновений и пересечений). Первый параметр – минимумы по X,Y и Z, второй – максимумы; они задаются в относительных координатах. Удобнее, однако, использовать функцию UTIL_SetSize:
void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax );
UTIL_SetSize(pev, Vector(-8, -8, -8), Vector(8, 8, 8));
Так задается размер 16х16х16 для текущей энтити. Ее центр окажется в центре коробки (центр – это точка (0, 0, 0) в относительных координатах).
Название: pfnChangeLevel
Псевдоним: CHANGE_LEVEL
Синтаксис: void CHANGE_LEVEL(char* s1, char* s2);
Осуществляет смену уровня (см. trigger_changelevel). Первый параметр – имя нового уровня, второй – имя ландмарка (info_landmark). Тут есть одна тонкость – чтобы правильно вычислить относительные координаты игрока по отношению к ландмарку нового уровня (абсолютные-то другие!), нужно сохранить положение ландмарка на текущем уровне в переменную gpGlobals→vecLandmarkOffset.
Название: pfnGetSpawnParms
Псевдоним: GET_SPAWN_PARMS
Синтаксис: void GET_SPAWN_PARMS(edict_t *ent);
О назначении этой функции можно лишь догадываться. В Quake существовал набор 16 уникальных значений, закрепленных за клиентом – spawn_parms. Они хранились в структуре движка, но могли передаваться в progs.dat для обработки. В Half-Life это, похоже, было упразднено. Таким образом, данная функция не используется.
Название: pfnSaveSpawnParms
Псевдоним: SET_SPAWN_PARMS
Синтаксис: void SET_SPAWN_PARMS(edict_t *ent);
Как и pfnGetSpawnParms, эта функция не используется в Half-Life.
Название: pfnVecToYaw
Псевдоним: VEC_TO_YAW
Синтаксис: float VEC_TO_YAW(const float *rgflVector);
Возвращает yaw-компонент угла (поворот относительно оси oZ), в который конвертируется вектор rgflVector. Сам вектор – обычно разность конечной и начальной точек. Удобнее использовать функцию UTIL_VecToYaw:
float UTIL_VecToYaw( const Vector &vec );
Пример: вы хотите сделать голограмму, которая всегда повернута к игроку. Допустим, у вас есть указатель на класс игрока и функция CMyHologram::Think, вызываемая каждые 0.1 с. Тогда код будет выглядеть так:
pev->angles.y = UTIL_VecToYaw(m_pPlayer->pev->origin – pev->origin);
Название: pfnVecToAngles
Псевдоним: VEC_TO_ANGLES
Синтаксис: void VEC_TO_ANGLES(const float *rgflVectorIn, float *rgflVectorOut);
Более общая функция, чем pfnVecToYaw: она также вычисляет pitch и roll-компоненты угла, иными словами, полное значение угла. Сам вектор – обычно разность конечной и начальной точек. Удобнее использовать функцию UTIL_VecToAngles:
Vector UTIL_VecToAngles( const Vector &vec );
В вышеупомянутом примере можно заставить модель вести себя подобно спрайту, то есть поворачиваться к игроку всегда «лицом»:
pev->angles = UTIL_VecToAngles(m_pPlayer->pev->origin – pev->origin);
Название: pfnMoveToOrigin
Псевдоним: MOVE_TO_ORIGIN
Синтаксис: void MOVE_TO_ORIGIN(edict_t *ent, const float *pflGoal, float dist, int iMoveType);
Эта функция заставляет монстров ходить и летать. Первый параметр – edict монстра, второй – массив из трех значений с плавающей точкой – координаты точки, куда надо переместиться. Третий – размер «шага» монстра, т.е. на сколько его нужно переместить в заданном направлении. Обычно для наземных монстров это значение не превышает 16, иначе будут проблемы со ступеньками лестниц. Последний параметр – тип перемещения. Он может быть равен MOVE_NORMAL (монстр идет туда, куда смотрит, при необходимости поворачиваясь – характерно для наземных) или MOVE_STRAFE (монстр не поворачивается – характерно для летающих). Удобнее использовать функцию UTIL_MoveToOrigin:
void UTIL_MoveToOrigin( edict_t *pent, const Vector &vecGoal, float flDist, int iMoveType );
Название: pfnChangeYaw
Псевдоним: -
Синтаксис: void g_engfuncs.pfnChangeYaw (edict_t* ent);
Эта функция изменяет yaw-компонент угла энтити следующим образом: приближает значение pev→angles.y к pev→ideal_yaw со скоростью pev→yaw_speed и приводит угол в диапазон 0..360. Ничего особо оригинального, в Half-Life это делается в функции CBaseMonster::ChangeYaw. Эта функция досталась нам в наследство от Quake, где был интерпретируемый код и все часто вызываемые функции старались сделать частью движка, а не progs.dat.
Название: pfnChangePitch
Псевдоним: CHANGE_PITCH
Синтаксис: void CHANGE_PITCH(edict_t* ent);
Аналогично pfnChangeYaw, функция изменяет pitch-компонент угла энтити следующим образом: приближает значение pev→angles.x к pev→idealpitch со скоростью pev→ pitch_speed и приводит угол в диапазон 0..360. В Half-Life эта функция, как и значения pev→idealpitch и pev→pitch_speed, не используется.
Название: pfnGetEntityIllum
Псевдоним: GETENTITYILLUM
Синтаксис: int GETENTITYILLUM(edict_t* pEnt);
Очень интересная функция – возвращает освещенность данной энтити. Освещенность берется из лайтмапы под энтитей или над энтитей (если указан эффект EF_INVLIGHT). Значение лежит в интервале от 0 (полная темнота) до 255 (абсолютно яркая лайтмапа). Это может не работать для энтитей с невидимыми моделями (например, для игрока всегда возвращается значение 0). Если вы хотите определять освещенность игрока, вам нужно будет сделать энтитю, которая будет «привязана» к нему (постоянно перемещаться с игроком) и брать ее уровень освещенности (в качестве модели удобно использовать пустышку – модель без полигонов). В классе CBaseEntity есть перегружаемая функция Illumination, и лучше использовать ее (например, для игрока к этому значению прибавляется яркость вспышки, если игрок стреляет).
Название: pfnSetClientMaxspeed
Псевдоним: -
Синтаксис: void g_engfuncs.pfnSetClientMaxspeed(const edict_t *pEdict, float fNewMaxspeed);
Эта функция позволяет установить максимальную скорость для одного конкретного игрока. Первый параметр – его edict, второй – значение максимальной скорости. Если указать 0, то будет установлено значение по умолчанию (задаваемое переменными sv_maxspeed и/или cl_forwardspeed).
Название: pfnGetGameDir
Псевдоним: GET_GAME_DIR
Синтаксис: void GET_GAME_DIR(char *szGetGameDir);
Эта функция служит для получения игровой директории мода. Параметр – адрес массива символов, в который запишется путь (убедитесь, что он достаточного размера). Пример:
char szDirName[MAX_PATH];
GET_GAME_DIR( szDirName ); //или GET_GAME_DIR( &szDirName[0] );
Например, если вы запускаете мод mymod, то в переменной szDirName будет путь вида «C:\Games\Half-Life\mymod».
Similar 1. Новый монстр - В общем-то это самый лёгкий тутор который можно придумать. 2. Цвет HUD - Цвет HUD 3. Как сделать вортигонта из HL1 другом - Моя первая статья
You cannot comment, because you are not logged-in.