Ru/Thinking

Think (обновление) позволяет объекту планировать запуск кода в определенное время. Think может работать постоянно, что позволяет создавать автономные энтити объекты.
== Планирование ==
Функция SetNextThink() настраивает следующий момент обновления энтити. Принимает значения float (число с плавающей запятой) .
void CMyEntity::Spawn()
{
	BaseClass::Spawn();
	SetNextThink( gpGlobals->curtime ); // Запустить Think прямо сейчас (обновить)
}
void CMyEntity::Think()
{
	BaseClass::Think(); // Всегда пишите это здесь, если хотите предопределить функцию Think()
	Msg( "Я думаю, следовательно, я существую.\n" );
	SetNextThink( gpGlobals->curtime + 1 ); // Обновить еще раз, через 1 секунду
}
Данный код, после создания энтити, каждую секунду выводит сообщение.
Не забывайте использовать gpGlobals->curtime, чтобы задать следующее время обновления относительно текущего времени, после которого была запущена функция Think, иначе может начаться бесконечный цикл.
== Создание собственных Think функций ==
Энтити может иметь любое количество дополнительных Think функций. Чтобы создать (зарегистрировать) еще одну функцию:
# Создайте свою функцию типа void.
# Добавьте ее в энтити с помощью DEFINE_THINKFUNC().
# Вызовите SetThink() и укажите ссылку на вашу функцию Think (пример внизу).
# Проверьте наличие DECLARE_DATADESC(); в вашем классе.
BEGIN_DATADESC( CMyEntity )
	DEFINE_THINKFUNC( MyThink ), // Регистрация новой Think функции
END_DATADESC()
void CMyEntity::Spawn()
{
	BaseClass::Spawn();
	SetThink( &CMyEntity::MyThink ); // Задать Think указатель на функцию MyThink()
	SetNextThink(gpGlobals->curtime);
}
void CMyEntity::MyThink()
{
	Msg( "Я думаю, следовательно, я существую.\n" );
	SetNextThink( gpGlobals->curtime + 1 );
}
Разделив ваш код на определенные Think функции можно легко переключаться между режимами работы вашей энтити.
== Использование контекстов ==
Можно запланировать (запустить) одновременно несколько Think функций с помощью «think contexts» (контексты). Чтобы создать новый контекст:
# Вызовите RegisterThinkContext( ContextName) указав контекст (название) к Think функции.
# Вызовите SetContextThink(* Function, float NextThinkTime, string ContextName) укажите функцию которая будет вызвана контекстом и название вашего контекста
# Для последующих вызовов Think, используйте SetNextThink(float NextThinkTime, string ContextName)
BEGIN_DATADESC( CMyEntity )
	DEFINE_THINKFUNC( ContextThink ),
END_DATADESC()
void CMyEntity::Spawn()
{
	SetNextThink( gpGlobals->curtime ); // Запуск обычного Think - контекста нет
	
	RegisterThinkContext( "TestContext" );
	SetContextThink( &CMyEntity::ContextThink, gpGlobals->curtime, "TestContext" );
}
void CMyEntity::Think()
{
	BaseClass::Think();
	Msg( "Обновление\n" );
	SetNextThink( gpGlobals->curtime + .1 );
}
void CMyEntity::ContextThink()
{
	Msg( "Контекстное обновление\n" );
	SetNextThink(gpGlobals->curtime + .2, "TestContext" );
}
Это создаст два Think цикла, оба будут выводить определенные сообщения.
== Время ==
Вот некоторые функции определения времени обновления:
float	GetLastThink() // время последнего обновления
float	GetNextThink() // время следующего обновления
int	GetLastThinkTick() // время прошлого обновления в тиках (10,000,000 тик/ 1 секунд)
int	GetNextThinkTick() // время будущего обновления в тиках
Функции GetLast полезны для управления скорости, с которой что-то происходит. 
Это Think код энтити фиксирующий скорость движения языка, при смене частоты обновления:
float dt = gpGlobals->curtime - GetLastThink(); // dt - это "delta time (изменение времени относительно прошлого обновления)"
SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); // смена высоты языка барнакла
Данный код выполняется когда игрока хватает барнакл. Код делает анимацию языка плавной в отличии от скелетной анимации.
==ClientThink() - Обновление клиента==
Обновления могут быть объявлены и со стороны клиента («Client-Side»), однако есть ограничения. Для одной энтити доступна лишь одна Think функция.
void C_MyEntity::ClientThink()
{
	Msg( "Не нагружайте эту функцию слишком сильно!\n" );
	SetNextClientThink( CLIENT_THINK_ALWAYS ); // Обновлять каждый кадр
}
Некоторый примеры client-side обновления:
* Визуальные эффекты / партиклы
* VGUI экран взаимодействия
* Изменение скорости игрока (выполняется на стороне клиента, а также серверов, для избежания ошибок)
* Ноги страйдеров, привязки веревки (изначально отключено)
Функция SetNextClientThink() для запуска ClientThink(). Принимает два значения:
; CLIENT_THINK_ALWAYS: Выполнять Think функцию после каждого кадра клиента. Используйте с осторожностью! 
; CLIENT_THINK_NEVER: Остановка всех Think обновлений клиента.