Регенерация здоровья
При помощи данного туториала вы сможете добавить в свой проект систему регенерации здоровья, как в Call Of Duty/Portal для синглплеера, а с небольшими изменениями - и для мультиплеера. Используемый код был взят из Alien Swarm SDK .
Обзор
Как это должно работать:
- Проверяем, что здоровье игрока меньше максимального значения
- Проверяем, что прошло достаточно времени между таймером регенерации и временем последнего получения повреждения игроком
- Добавляем количество здоровья для регенерации, исходя из времени кадра
- Если количество здоровья для регенерации больше одного - добавляем его игроку
Добавляем квары
Для этого туториала мы будем изменять базовый класс игрока. Откройте server/player.cpp и добавьте в него следующие квары:
ConVar sv_regeneration ("sv_regeneration", "0", FCVAR_REPLICATED ); // Регенерация включена/отключена
ConVar sv_regeneration_wait_time ("sv_regeneration_wait_time", "1.0", FCVAR_REPLICATED ); // Время до старта регенерации после получения урона
ConVar sv_regeneration_rate ("sv_regeneration_rate", "0.5", FCVAR_REPLICATED ); // Частота регенерации (раз в пол-секунды, в данном случае)
Это позволит изменять настройки регенерации прямо в игре. Также нам понадобится значение, в котором будет храниться текущее количество здоровья для регенерации. Добавьте:
float m_fRegenRemander;
после
int gEvilImpulse101;
Нам нужно инициализировать нашу переменную, поэтому в файле player.cpp: CBasePlayer::CBasePlayer( )
под m_iHealth = 0;
после строки 552 добавьте это:
m_fRegenRemander = 0;
Получаем время последнего получения урона игроком
Заметка: Если используете HL2 синглплеер базу, просто используйте m_flLastDamageTime , а не добавляйте m_fTimeLastHurt.
Теперь нам нужно получить время с последнего получения урона игроком. Нам нужно это, потому что мы хотим, чтобы имелся промежуток во времени перед стартом регенерации, и игрок не начинал регенерировать сразу после получения урона.
Чтобы сделать это, откройте player.h и добавьте где-нибудь около строки 860
float m_fTimeLastHurt;
А в player.cpp поместите:
DEFINE_FIELD( m_fTimeLastHurt, FIELD_TIME ),
после
DEFINE_FIELD( m_tbdPrev, FIELD_TIME ),
где-нибудь около строки 306.
Теперь, когда мы добавили переменную, которая указывает на время последнего получения игроком урона, нам нужно держать её в актуальном состоянии. Для этого добавьте:
if ( GetHealth() < 100 )
{
m_fTimeLastHurt = gpGlobals->curtime;
}
в конце метода CBasePlayer::OnTakeDamage
.
Регенерация
Теперь настало самое время писать логику регенерации. В конце CBasePlayer::PostThink
добавьте:
// Регенерация здоровья
if ( IsAlive() && GetHealth() < GetMaxHealth() && (sv_regeneration.GetInt() == 1) )
{
// Цвет, которым накладывается на экран игрока при получении урона
color32 hurtScreenOverlay = {80,0,0,64};
if ( gpGlobals->curtime > m_fTimeLastHurt + sv_regeneration_wait_time.GetFloat() )
{
// Регенерация по частоте
m_fRegenRemander += sv_regeneration_rate.GetFloat() * gpGlobals->frametime;
if(m_fRegenRemander >= 1)
{
TakeHealth( m_fRegenRemander, DMG_GENERIC );
m_fRegenRemander = 0;
}
}
else
{
UTIL_ScreenFade( this, hurtScreenOverlay, 1.0f, 0.1f, FFADE_IN|FFADE_PURGE );
}
}
Готово.