HLFX.Ru Forum
профиль •  правила •  регистрация •  календарь •  народ •  FAQ •  поиск •  новое •  сутки •  главная •  выход  
HLFX.Ru Forum HLFX.Ru Forum > Теория и практика > Half-Life SDK > Кажется, я починил DispatchAnimEvents
Досконально не тестировал
Страницы (7): [1] 2 3 4 5 » ... Последняя »   Предыдущая тема   Следующая тема
Автор
Тема Новая тема    Ответить
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Кажется, я починил DispatchAnimEvents. Досконально не тестировал, но скрипт на карте gruntbattledemo в спирите стал работать значительно лучше. Да и вроде монстры стали меньше тупить. Проблема поднималась на форуме как минимум один раз тут. Как Дядя Миша писал выше, проблема в обнулении m_fSequenceFinished, и последующем проигрывании секвенции n-ное количество раз, пока, наконец, m_fSequenceFinished не станет true.
Я сравнил код из халфы с кодом из hl2beta, а затем из se2007. SourceSDK 2013 не смотрел, т.к. уверен, что принципиальных отличий нет. Хрен его знает зачем, но в первой халфе вальва сделала в вычислении диапазона эвента привязку к gpGlobals->time. А это, как оказалось, имеет зависимость от фпс и даёт нехорошие погрешности. Вот этот код в animating.cpp, void CBaseAnimating :: DispatchAnimEvents ( float flInterval )

C++ Source Code:
1
// FIXME: I have to do this or some events get missed, and this is probably causing the problem below
2
flInterval = 0.1;
3
 
4
// FIX: this still sometimes hits events twice
5
float flStart = pev->frame + (m_flLastEventCheck - pev->animtime) * m_flFrameRate * pev->framerate;
6
float flEnd = pev->frame + flInterval * m_flFrameRate * pev->framerate;
7
m_flLastEventCheck = pev->animtime + flInterval;
8
 
9
m_fSequenceFinished = FALSE;
10
if (flEnd >= 256 || flEnd <= 0.0)
11
  m_fSequenceFinished = TRUE;

По комментам понятно, что эта фигня глючит, да ещё и m_fSequenceFinished приходится выставлять в TRUE ещё один раз, если StudioFrameAdvance этого не делает. Если приглядеться, то flStart и flEnd это не время, а кадры в диапазоне от 0 до 256. И вот тут-то доходит, в чём отличие сорсовской версии. Там нет привязки к времени. То есть никаких pev->animtime и gpGlobals->time, только диапазон от 0 до 1
C++ Source Code:
1
float flStart = m_flLastEventCheck;
2
float flEnd = m_flCycle;
3
 
4
if (!m_bSequenceLoops && m_bSequenceFinished)
5
{
6
  flEnd = 1.0f;
7
}
8
m_flLastEventCheck = flEnd;

Я взял, да и зменил исходный код на сорсовский с изменениями:
C++ Source Code:
1
float flStart = m_flLastEventCheck;
2
float flEnd = pev->frame;
3
 
4
if (!m_fSequenceLoops && m_fSequenceFinished)
5
  flEnd = 256.0f;
6
 
7
m_flLastEventCheck = flEnd;

Ну и ещё в ResetSequenceInfo поменял m_flLastEventCheck = gpGlobals->time; на m_flLastEventCheck = 0; В коде цыклера это надо тоже сделать.
Короче, вроде бы работает лучше, будем посмотреть.

Добавлено 01-12-2020 в 04:10:

Вдогонку видос с доработанным барником. Разобрался, как грамотно чекать врагов, чтобы монстр убегал от них резвее. Когда добавлю ему это - ближнебойные потенциально не смогут его завалить.

Отредактировано Ku2zoff 30-11-2020 в 19:09

Сообщить модератору | | IP: Записан
Сообщение: 198827

Старое сообщение 30-11-2020 21:10
- За что?
Aynekko
Маппер

Дата регистрации: Jun 2016
Проживает: г. Подольск, Россия
Сообщений: 325
Возраст: 28

Рейтинг



Ku2zoff, это просто отлично хотелось бы видеть тутор по фиксу AI - это очень бы пригодилось всем.

__________________
Мой мод на Xash

Сообщить модератору | | IP: Записан
Сообщение: 198830

Старое сообщение 01-12-2020 08:14
- За что?
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Aynekko по сути это не фикс, а дописывание функционала барника с использованием того, что есть в дефолтном AI. Но кое-что я всё-таки поменял. Обкатаю и протестирую, и может быть напишу тутор. Ещё кое-что сделано не совсем правильно, но результат уже хороший: выживаемость у него выросла. Даже боюсь представить, что будет с грантами и ассассинами - они живучее и подвижнее.

Сообщить модератору | | IP: Записан
Сообщение: 198831

Старое сообщение 01-12-2020 08:39
- За что?
FreeSlave
Житель форума

Дата регистрации: Nov 2007
Проживает: Тула
Сообщений: 903

Рейтинг



Ku2zoff, попозже попробую твои фиксы анимаций тоже. В идеале такие изменения нужно отдельными коммитами выкладывать на какой-нибудь гитхаб. Чтобы заинтересованные могли глянуть, что поменялось в сравнении с оригиналом, и видеть только необходимое множество изменений.

__________________
I'm on github
I'm on Open Build Service
I'm on opendesktop.org

Сообщить модератору | | IP: Записан
Сообщение: 198832

Старое сообщение 01-12-2020 09:06
- За что?
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Цитата:
FreeSlave писал:
попозже попробую твои фиксы анимаций тоже

Дело не только в анимациях, но ещё и в щедъюлях. В некоторых из них есть TASK_WAIT и TASK_STOP_MOVING там, где они вообще не нужны. Например, SCHED_TAKE_COVER_FROM_ENEMY. Монстр теряет целую секунду на этих двух строчках. Если их закомментить, барник отваливает от врагов почти сразу, как они подойдут. Если отредактировать все щедъюли, то ненужных пауз между действиями не будет.

Сообщить модератору | | IP: Записан
Сообщение: 198833

Старое сообщение 01-12-2020 09:46
- За что?
Aynekko
Маппер

Дата регистрации: Jun 2016
Проживает: г. Подольск, Россия
Сообщений: 325
Возраст: 28

Рейтинг



Цитата:
Ku2zoff писал:
Я взял, да и зменил исходный код на сорсовский с изменениями:

Цитата:
Ku2zoff писал:
Ну и ещё в ResetSequenceInfo поменял m_flLastEventCheck = gpGlobals->time; на m_flLastEventCheck = 0;

Сделал это и гранты с дробовиками стали очень быстро стрелять. Автоматчики вроде нормальные остались.

__________________
Мой мод на Xash

Сообщить модератору | | IP: Записан
Сообщение: 198835

Старое сообщение 01-12-2020 10:18
- За что?
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Aynekko а у меня норм стреляют. Сравнивай, чем отличаются гранты и CBaseAnimating в ксашмоде и в халфе.

Сообщить модератору | | IP: Записан
Сообщение: 198836

Старое сообщение 01-12-2020 11:08
- За что?
FreeSlave
Житель форума

Дата регистрации: Nov 2007
Проживает: Тула
Сообщений: 903

Рейтинг



Цитата:
Ku2zoff писал:
Дело не только в анимациях, но ещё и в щедъюлях.


Я про DispatchAnimEvents. Так как проблема двойного срабатывания ивентов действительно существует.

По поводу шедулей я кстати тебе в личку писал свои мысли. Мб ты пропустил сообщение?

Цитата:
Если их закомментить, барник отваливает от врагов почти сразу, как они подойдут. Если отредактировать все щедъюли, то ненужных пауз между действиями не будет.


Мне кажется, ожидания в некоторых местах всё же нужны. Иначе возможна ситуация, когда монстр будет постоянно пытаться построить путь, что может быть трудоёмко для старых компов, особенно если монстров много.
Кстати ошибка построения пути наверно самая частая причина непредусмотренных прерываний (т.е. срабатывающих не по условию в свойствах шедули).

__________________
I'm on github
I'm on Open Build Service
I'm on opendesktop.org

Отредактировано FreeSlave 01-12-2020 в 13:22

Сообщить модератору | | IP: Записан
Сообщение: 198843

Старое сообщение 01-12-2020 13:13
- За что?
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Цитата:
FreeSlave писал:
Мб ты пропустил сообщение?

Нет, я его прочитал и принял к сведению.
Цитата:
FreeSlave писал:
Мне кажется, ожидания в некоторых местах всё же нужны.

Конечно нужны. Иначе выглядит нелепо: на одном из моих видео барник сначала бежит к одной ноде лицом, а потом бежит почти боком к другой. Тут надо сам код FindCover переписывать. В голдсорсе ищется нода, если она подходит по критериям, монстр движется к ней, если достиг её - return TRUE - TaskComplete(). А правильнее надо так: ищется нода, если подходит по критериям, то BuildRoute до ноды, если успешно, монстр движется. Если вдруг не дошёл, пробуем другой маршрут до ноды, или ищем новую ноду. Снова BuildRoute и движение. И вот когда дошёл - TaskComplete(). А то обычным способом (если немного подкрутить функцию на поиск соседних связанных нод) он начинает метаться между нодами не меняя angles, что выглядит по-уродски. А если не подкрутить на поиск, то вообще TaskFailed() и искорки над головой.

Уважаемые админы, вырежьте нам пожалуйста из этой темы посты начиная с этого в отдельную тему. Эта ведь для вопросов, а не обсуждений и демонстрации.

Отредактировано Ku2zoff 01-12-2020 в 14:34

Сообщить модератору | | IP: Записан
Сообщение: 198844

Старое сообщение 01-12-2020 14:32
- За что?
FreeSlave
Житель форума

Дата регистрации: Nov 2007
Проживает: Тула
Сообщений: 903

Рейтинг



Ku2zoff, не совсем тебя понял. FindCover зовёт MoveToLocation, который суть просто непрямой вызов того же BuildRoute. Т.е. ты описал два одинаковых случая (если не брать в расчёт предложенное перестраивание пути). А непосредственно движение выполняется вообще не в шедулях.

Бег боком это тоже что-то новенькое - наверно в твоих библиотеках. В HL то монстры (кроме контроллеров) всегда поворачиваются по направлению движения.

__________________
I'm on github
I'm on Open Build Service
I'm on opendesktop.org

Сообщить модератору | | IP: Записан
Сообщение: 198850

Старое сообщение 01-12-2020 16:04
- За что?
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Цитата:
FreeSlave писал:
MoveToLocation, который суть просто непрямой вызов того же BuildRoute

Точно, тупанул. Казалось, BuildRoute вызывается до начала движения, а не из одной функции с ним.
Цитата:
FreeSlave писал:
В HL то монстры (кроме контроллеров) всегда поворачиваются по направлению движения.

Здесь наверное причина в отсутствии TASK_WAIT и TASK_STOP_MOVING. Монстр просто не успевает повернуться или проиграть ACT_TURN_LEFT/ACT_TURN_RIGHT если нужно. Ладненько, будем посмотреть. Я сейчас откачусь до предыдущих сорцев, где шаренный код монстров ещё не тронут, и буду ковырять только барника. По-грамотному уже, а то в текущей версии у меня всё на скорую руку.

Добавлено 01-12-2020 в 23:33:

FreeSlave а какие у тебя наработки в этой области?

Сообщить модератору | | IP: Записан
Сообщение: 198852

Старое сообщение 01-12-2020 16:33
- За что?
Next Day
Новичок

Дата регистрации: Mar 2017
Проживает: Электросталь
Сообщений: 25
Возраст: 30

Рейтинг



Рад что ты продолжаешь работать над НПС

Сообщить модератору | | IP: Записан
Сообщение: 198853

Старое сообщение 01-12-2020 17:01
- За что?
FreeSlave
Житель форума

Дата регистрации: Nov 2007
Проживает: Тула
Сообщений: 903

Рейтинг



Ku2zoff, в области убегания монстров?

В TASK_FIND_COVER_FROM_BEST_SOUND я помимо поиска пути до укрытия сделал в качестве альтернативы просто поиск отдаленного нода. Т.к. в случае ухода от звука опасности (гранаты, например) суть даже не в том, чтобы найти укрытие, а в том, чтобы просто убежать подальше. Думаю, ты сделал нечто такое и в коде сбегания барника от врага. Тут ничего сложного, по сути тот же FindCover, но без проверки на то, что ориджин "угрозы" не увидит монстра после того, как тот встанет на ноду.

C++ Source Code:
1
BOOL CBaseMonster::FindRunAway( Vector vecThreat, float flMinDist, float flMaxDist )
2
{
3
  int i;
4
  int iMyHullIndex;
5
  int iMyNode;
6
  int iThreatNode;
7
  float flDist;
8
 
9
  if( !flMaxDist )
10
  {
11
    // user didn't supply a MaxDist, so work up a crazy one.
12
    flMaxDist = 784;
13
  }
14
 
15
  if( flMinDist > 0.5 * flMaxDist )
16
  {
17
#if _DEBUG
18
    ALERT( at_console, "FindRunAway MinDist (%.0f) too close to MaxDist (%.0f)\n", flMinDist, flMaxDist );
19
#endif
20
    flMinDist = 0.5 * flMaxDist;
21
  }
22
 
23
  if( !WorldGraph.m_fGraphPresent || !WorldGraph.m_fGraphPointersSet )
24
  {
25
    ALERT( at_aiconsole, "Graph not ready for findcover!\n" );
26
    return FALSE;
27
  }
28
 
29
  iMyNode = WorldGraph.FindNearestNode( pev->origin, this );
30
  iThreatNode = WorldGraph.FindNearestNode ( vecThreat, this );
31
  iMyHullIndex = WorldGraph.HullIndex( this );
32
 
33
  if( iMyNode == NO_NODE )
34
  {
35
    ALERT( at_aiconsole, "FindRunAway() - %s has no nearest node!\n", STRING( pev->classname ) );
36
    return FALSE;
37
  }
38
  if( iThreatNode == NO_NODE )
39
  {
40
    // ALERT( at_aiconsole, "FindRunAway() - Threat has no nearest node!\n" );
41
    iThreatNode = iMyNode;
42
    // return FALSE;
43
  }
44
 
45
  // we'll do a rough sample to find nodes that are relatively nearby
46
  for( i = 0; i < WorldGraph.m_cNodes; i++ )
47
  {
48
    int nodeNumber = ( i + WorldGraph.m_iLastCoverSearch ) % WorldGraph.m_cNodes;
49
 
50
    CNode &node = WorldGraph.Node( nodeNumber );
51
 
52
    // could use an optimization here!!
53
    flDist = ( pev->origin - node.m_vecOrigin ).Length();
54
 
55
    // DON'T do the trace check on a node that is farther away than a node that we've already found to
56
    // provide cover! Also make sure the node is within the mins/maxs of the search.
57
    if( flDist >= flMinDist && flDist < flMaxDist )
58
    {
59
      // node is closer to me than the threat, or the same distance from myself and the threat the node is good.
60
      if( ( iMyNode == iThreatNode ) || WorldGraph.PathLength( iMyNode, nodeNumber, iMyHullIndex, m_afCapability ) <= WorldGraph.PathLength( iThreatNode, nodeNumber, iMyHullIndex, m_afCapability ) )
61
      {
62
        if( FValidateCover( node.m_vecOrigin ) && MoveToLocation( ACT_RUN, 0, node.m_vecOrigin ) )
63
        {
64
          WorldGraph.m_iLastCoverSearch = nodeNumber + 1; // next monster that searches for cover node will start where we left off here.
65
          return TRUE;
66
        }
67
      }
68
    }
69
  }
70
  return FALSE;
71
}


Ну и как крайнее средство добавил убегание по прямой от опасности, если монстр не смог найти подходящую ноду. В итоге получилось вот так:

C++ Source Code:
1
if (FindCover( pBestSound->m_vecOrigin, g_vecZero, pBestSound->m_iVolume, CoverRadius() ))
2
{
3
  // then try for plain ole cover
4
  m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
5
  TaskComplete();
6
}
7
 
8
// The point is to just run away from danger. Try to find a node without actual cover.
9
else if (FindRunAway( pBestSound->m_vecOrigin, pBestSound->m_iVolume, CoverRadius() ))
10
{
11
  //ALERT(at_aiconsole, "Using run away\n");
12
  m_flMoveWaitFinished = gpGlobals->time + pTask->flData;
13
  TaskComplete();
14
}
15
// The last resort, just run straight away
16
else
17
{
18
  Vector dir = pev->origin - pBestSound->m_vecOrigin;
19
  float distance = dir.Length();
20
  distance = Q_max(pBestSound->m_iVolume - distance, 384);
21
  dir.z = 0;
22
  Vector targetLocation = pev->origin + dir.Normalize() * distance;
23
 
24
  if( MoveToLocation( ACT_RUN, 0, targetLocation ) )
25
  {
26
    //ALERT(at_aiconsole, "Using the last resort to run away\n");
27
    TaskComplete();
28
  }
29
}
30
// no coverwhatsoever. or no sound in list
31
if (!TaskIsComplete())
32
  TaskFail();


Если говорить в целом о поведении монстров, то я уже кое-что упоминал в предыдущей теме. Но здесь распишу то, что касается всех передвигающихся монстров, а не отдельных видов.

Добавил Monster Roaming (параметр freeroam) из Sven Co-op, с которым монстры рандомно ходят по нодам даже в idle-состоянии. В принципе может быть полезно для создания иллюзии патрулирования территории без лишних затрат.

Кстати, в HL есть патрулирование по path_track, но в очень урезанном виде - при встрече с препятствием монстр не ищет обходных путей. Это я у себя тоже исправил, плюс добавил возможность использования ожидания выставленного в path_track. И теперь в местах, где достаточно задать только передвижение монстра, использую патрулирование вместо scripted_sequence дабы монстр адекватно реагировал на окружение, ибо во время выполнения скриптов монстры реагируют только на урон.

В качестве экспериментов:


  • Как известно, FTriangulate в HL используется для поиска промежуточной точки, по которой можно обогнуть встреченное на пути препятствие. Я добавил возможность искать не одну, а две точки (это уже получается не триангуляция, а квадрогуляция ), что даёт неплохие результаты и особенно полезно для NPC, следующих за игроком (вас же тоже задолбали союзники, тупящие на каждом углу? )
  • Для союзников следующих за игроком реализована попытка подобраться к игроку как можно ближе, если монстр не смог построить путь до игрока (что случается довольно часто, стоит лишь игроку забраться повыше или пониже). В результате на crossfire барник бегает вдоль края поля перед бункером, если игрок находится на втором этаже. Побочным эффектом тут конечно является то, что монстр будет бегать за игроком вдоль стены аки примагниченный, если игрок находится с другой стороны стены. Замечу, что это сделано без использования нодов. В качестве дополнительной или альтернативной меры можно использовать что-то в духе BuildNearestRoute, но я пока этого не делал (почему-то не подумал в своё время)
  • Способность монстров "забывать" о своём враге, если давно его не видели, пытались-пытались добраться, да не смогли на протяжении некоего промежутка времени. Особенно актуально, если враг - игрок, т.к. ему проще всего убежать от монстра. В HL, если игрок пропустил какого-нибудь хедкраба, тот так и запомнит врага и будет весь остаток игры пытаться до игрока дойти. Монстры в HL вообще не забывают о враге до тех пор пока тот не умрёт либо не исчезнет с карты.
  • Сейчас в связи с последним (да и не только) думаю, чем можно было бы занять монстра в ALERT состоянии. В HL лишь некоторые монстры занимаются чем-то полезным в этом состоянии - буллсквиды ищут чего покушать, солдаты идут к трупу поверженного врага, чтобы убедиться в том, что тот умер. В остальном же монстры просто стоят и смотрят. Тут напрашиваются такие вещи как переход к последней известной позиции врага (если враг был "утерян"), исследование услышанных звуков боя (типа Investigate Sound, который по умолчанию используется только у ассассинок), и тот же freeroam, описанный выше.

__________________
I'm on github
I'm on Open Build Service
I'm on opendesktop.org

Отредактировано FreeSlave 02-12-2020 в 12:57

Сообщить модератору | | IP: Записан
Сообщение: 198919

Старое сообщение 02-12-2020 12:55
- За что?
Next Day
Новичок

Дата регистрации: Mar 2017
Проживает: Электросталь
Сообщений: 25
Возраст: 30

Рейтинг



А куда этот код добавлять если не секрет ?

Сообщить модератору | | IP: Записан
Сообщение: 198920

Старое сообщение 02-12-2020 13:15
- За что?
Ku2zoff
Юзер (типа моддер)

Дата регистрации: Apr 2007
Проживает: В Деревне дураков
Сообщений: 5562
Возраст: 29

Рейтинг



Цитата:
FreeSlave писал:
Тут ничего сложного, по сути тот же FindCover, но без проверки на то, что ориджин "угрозы" не увидит монстра после того, как тот встанет на ноду.

Нет, я сделал не так, а добавил поиск связанных нод. Это немного помогло избавиться от тупняков. Но вчера убрал кактус с тестовой карты, и барник перестал убегать, т.к. прятаться стало не за что. Я сразу смекнул что к чему, вчитался внимательнее в код и тоже решил убрать оттуда трассу, чтобы сделать просто RunAway на открытой местности.

Добавлено 02-12-2020 в 20:51:

Цитата:
Next Day писал:
А куда этот код добавлять если не секрет ?

Какой код?

Сообщить модератору | | IP: Записан
Сообщение: 198921

Старое сообщение 02-12-2020 13:51
- За что?
Тема: (Опционально)
Ваш ответ:



Переводчик транслита


[проверить длину сообщения]
Опции: Автоматическое формирование ссылок: автоматически добавлять [url] и [/url] вокруг интернет адресов.
Уведомление по E-Mail: отправить вам уведомление, если кто-то ответил в тему (только для зарегистрированных пользователей).
Отключить смайлики в сообщении: не преобразовывать текстовые смайлики в картинки.
Показать подпись: добавить вашу подпись в конец сообщения (только зарегистрированные пользователи могут иметь подписи).

Временная зона GMT. Текущее время 23:04. Новая тема    Ответить
Страницы (7): [1] 2 3 4 5 » ... Последняя »   Предыдущая тема   Следующая тема
HLFX.Ru Forum HLFX.Ru Forum > Теория и практика > Half-Life SDK > Кажется, я починил DispatchAnimEvents
Досконально не тестировал
Версия для печати | Отправить тему по E-Mail | Подписаться на эту тему

Быстрый переход:
Оцените эту тему:

Правила Форума:
Вы not можете создавать новые темы
Вы not можете отвечать в темы
Вы not можете прикреплять вложения
Вы not можете редактировать ваши сообщения
HTML Код ВЫКЛ
vB Код ВКЛ
Смайлики ВКЛ
[IMG] Код ВКЛ
 

< Обратная связь - HLFX.ru >

На основе vBulletin
Авторское право © 2000 - 2002, Jelsoft Enterprises Limited.
Дизайн и программирование: Crystice Softworks © 2005 - 2021