HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- Half-Life SDK (https://hlfx.ru/forum/forumdisplay.php?forumid=8)
-- как научить монстров следовать игроку ? (https://hlfx.ru/forum/showthread.php?threadid=5944)
Отправлено илья2 18-02-2023 в 17:43:
как научить монстров следовать игроку ?
Хотелось бы как у Баника: нажал на монстра, и он идет за игроком. Как такое реализовать ?
__________________
илья
Отправлено Дядя Миша 18-02-2023 в 18:44:
А Барник что не монстр?
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено Napoleon321 20-02-2023 в 07:56:
Open barney.cpp or scientist.cpp and look for "follow".
All you need is to either base your new monsters on scientists/barneys or copy the same logic to the monster you would like to create.
Another thing you need to take into account would the classify function... Obviously Gordon (the player) is human... so it should be human ally the one thing that should follow it... or it might follow the player with intention of killing it 
__________________
FlatLine Arena | Tutorials
If you don't like something, MOD it!
Отправлено Demiurge 23-02-2023 в 14:57:
Если в HL1 - то там всё намного сложнее. Дело в том, как мне помнится, функция Follow привязана к Барни и Учёным, и просто так не размножается. Для этого надо сделать следующее:
Спасибо Inferno из MilleniumTeam.
C++ Source Code:
9 | { TASK_SET_FAIL_SCHEDULE, (float)SCHED_MOVE_AWAY_FAIL }, |
10 | { TASK_STORE_LASTPOSITION, (float)0 }, |
11 | { TASK_MOVE_AWAY_PATH, (float)100 }, |
12 | { TASK_WALK_PATH_FOR_UNITS, (float)100 }, |
13 | { TASK_STOP_MOVING, (float)0 }, |
14 | { TASK_FACE_PLAYER, (float)0.5 }, |
17 | Schedule_t slMoveAway[] = |
21 | ARRAYSIZE ( tlMoveAway ), |
28 | Task_t tlMoveAwayFail[] = |
30 | { TASK_STOP_MOVING, (float)0 }, |
31 | { TASK_FACE_PLAYER, (float)0.5 }, |
34 | Schedule_t slMoveAwayFail[] = |
38 | ARRAYSIZE ( tlMoveAwayFail ), |
45 | Task_t tlMoveAwayFollow[] = |
47 | { TASK_SET_FAIL_SCHEDULE, (float)SCHED_TARGET_FACE }, |
48 | { TASK_STORE_LASTPOSITION, (float)0 }, |
49 | { TASK_MOVE_AWAY_PATH, (float)100 }, |
50 | { TASK_WALK_PATH_FOR_UNITS, (float)100 }, |
51 | { TASK_STOP_MOVING, (float)0 }, |
52 | { TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE }, |
55 | Schedule_t slMoveAwayFollow[] = |
59 | ARRAYSIZE ( tlMoveAwayFollow ), |
66 | И вставляем это в defaultai.cpp, сразу после define's. |
68 | Опять идем в talkmonster.cpp и находим строку: |
70 | DEFINE_CUSTOM_SCHEDULES( CTalkMonster ) |
80 | Снова идем в defaultai.cpp, находим там: |
81 | DEFINE_CUSTOM_SCHEDULES( CTalkMonster ) |
83 | вставляем вырезанные 3 строки. |
87 | Опять идем в talkmonster.cpp и находим функцию: |
89 | void CTalkMonster :: StartTask( Task_t *pTask ) |
92 | //case TASK_FACE_PLAYER: // эту строчку закоментируем |
93 | case TASK_TLK_LOOK_AT_CLIENT: |
94 | case TASK_TLK_CLIENT_STARE: |
95 | // track head to the client for a while. |
96 | m_flWaitFinished = gpGlobals->time + pTask->flData; |
100 | case TASK_FACE_PLAYER: |
101 | m_flWaitFinished = gpGlobals->time + pTask->flData; |
104 | Теперь идем в файл schedule.cpp и вставляем вырезанный блок кода в функцию: |
106 | void CBaseMonster :: StartTask ( Task_t *pTask ) |
112 | Вырезаем следующий блок кода: |
114 | case TASK_CANT_FOLLOW: |
115 | StopFollowing( FALSE ); |
116 | // PlaySentence( m_szGrp[TLK_STOP], RANDOM_FLOAT(2, 2.5), VOL_NORM, ATTN_NORM ); |
120 | case TASK_WALK_PATH_FOR_UNITS: |
121 | m_movementActivity = ACT_WALK; |
124 | case TASK_MOVE_AWAY_PATH: |
126 | Vector dir = pev->angles; |
127 | dir.y = pev->ideal_yaw + 180; |
130 | UTIL_MakeVectorsPrivate( dir, move, NULL, NULL ); |
131 | dir = pev->origin + move * pTask->flData; |
132 | if ( MoveToLocation( ACT_WALK, 2, dir ) ) |
136 | else if ( FindCover( pev->origin, pev->view_ofs, 0, CoverRadius() ) ) |
138 | // then try for plain ole cover |
139 | m_flMoveWaitFinished = gpGlobals->time + 2; |
151 | Теперь идем в файл schedule.cpp и вставляем вырезанный блок кода в функцию: |
153 | void CBaseMonster :: StartTask ( Task_t *pTask ) |
156 | // возможно по аналогии с другими case надо будет вставить несколько {} |
160 | Опять идем в talkmonster.cpp и находим функцию: |
162 | void CTalkMonster :: RunTask( Task_t *pTask ) |
165 | Вырезаем следующий блок кода: |
167 | case TASK_WALK_PATH_FOR_UNITS: |
171 | distance = (m_vecLastPosition - pev->origin).Length2D(); |
173 | // Walk path until far enough away |
174 | if ( distance > pTask->flData || MovementIsComplete() ) |
177 | RouteClear(); // Stop moving |
182 | case TASK_FACE_PLAYER: |
184 | // Get edict for one player |
185 | edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); |
189 | MakeIdealYaw ( pPlayer->v.origin ); |
190 | ChangeYaw ( pev->yaw_speed ); |
191 | // IdleHeadTurn( pPlayer->v.origin ); |
192 | if ( gpGlobals->time > m_flWaitFinished && FlYawDiff() < 10 ) |
204 | Теперь идем в файл schedule.cpp и вставляем вырезанный блок кода в функцию: |
206 | void CBaseMonster :: RunTask ( Task_t *pTask ) |
209 | // возможно по аналогии с другими case надо будет вставить несколько {} |
213 | Опять идем в talkmonster.cpp и помещаем в /* */ функцию LimitFollowers, во всем коде нужно закомментировать еЈ или удалить. |
215 | Затем вырезаем функцию |
216 | void CTalkMonster :: Touch( CBaseEntity *pOther ) |
220 | и помещаем еЈ в monsters.cpp, изменив еЈ имя и код |
221 | void CBaseMonster :: FollowTouch( CBaseEntity *pOther ) |
225 | // Did the player touch me? |
226 | if ( pOther->IsPlayer() ) |
228 | // Ignore if pissed at player |
229 | if ( m_afMemory & bits_MEMORY_PROVOKED ) |
232 | // Stay put during speech |
233 | // if ( IsTalking() ) |
236 | // Heuristic for determining if the player is pushing me away |
237 | float speed = fabs(pOther->pev->velocity.x) + fabs(pOther->pev->velocity.y); |
241 | SetConditions( bits_COND_CLIENT_PUSH ); |
242 | MakeIdealYaw( pOther->pev->origin ); |
248 | Опять идем в talkmonster.cpp и находим функцию: |
249 | Schedule_t* CTalkMonster :: GetScheduleOfType ( int Type ) |
253 | case SCHED_MOVE_AWAY: |
256 | case SCHED_MOVE_AWAY_FOLLOW: |
257 | return slMoveAwayFollow; |
259 | case SCHED_MOVE_AWAY_FAIL: |
260 | return slMoveAwayFail; |
264 | идем в defaultai.cpp и вставляем в GetScheduleOfType ( int Type ) |
266 | Опять идем в talkmonster.cpp и полностью вырезаем функции: |
268 | void CTalkMonster::StopFollowing( BOOL clearSchedule ) |
269 | здесь нужно закоментировать строки: |
272 | if ( !(m_afMemory & bits_MEMORY_PROVOKED) ) |
274 | PlaySentence(m_szGrp[TLK_UNUSE],RANDOM_FLOAT(2.8, 3.2),VOL_NORM,ATTN_IDLE); |
275 | m_hTalkTarget = m_hTargetEnt; |
278 | void CTalkMonster::StartFollowing( CBaseEntity *pLeader ) |
279 | здесь нужно закоментировать строки: |
281 | // PlaySentence( m_szGrp[TLK_USE], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); |
282 | // m_hTalkTarget = m_hTargetEnt; |
285 | BOOL CTalkMonster::CanFollow( void ) |
287 | void CTalkMonster :: FollowerUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
288 | здесь нужно закоментировать строки: |
289 | // Don't allow use during a scripted_sentence |
290 | /* if ( m_useTime > gpGlobals->time ) |
293 | //SetBits(m_bitsSaid, bit_saidHelloPlayer); // Don't say hi after you've started following |
295 | идем в конец файла monsters.cpp и вставляем вырезанные функции. |
296 | Заменяем в их именах слово Talk на Base. |
297 | например: вместо BOOL CTalkMonster::CanFollow( void ) нужно |
298 | BOOL CBaseMonster::CanFollow( void ) |
300 | Теперь откроем файл talkmonster.h, найдем: |
305 | SCHED_CANT_FOLLOW = LAST_COMMON_SCHEDULE + 1, |
306 | SCHED_MOVE_AWAY, // Try to get out of the player's way |
307 | SCHED_MOVE_AWAY_FOLLOW, // same, but follow afterward |
308 | SCHED_MOVE_AWAY_FAIL, // Turn back toward player |
310 | LAST_TALKMONSTER_SCHEDULE, // MUST be last |
318 | SCHED_FICTION = LAST_COMMON_SCHEDULE + 1, // new |
320 | LAST_TALKMONSTER_SCHEDULE, // MUST be last |
325 | SCHED_MOVE_AWAY, // Try to get out of the player's way |
326 | SCHED_MOVE_AWAY_FOLLOW, // same, but follow afterward |
327 | SCHED_MOVE_AWAY_FAIL, // Turn back toward player |
329 | и вставим в файл schedule.h вот сюда: |
339 | LAST_COMMON_SCHEDULE // Leave this at the bottom |
342 | ниже(в файле talkmonster.h): |
346 | TASK_TLK_RESPOND = LAST_COMMON_TASK + 1, // new |
347 | // TASK_CANT_FOLLOW = LAST_COMMON_TASK + 1, |
348 | // TASK_MOVE_AWAY_PATH, |
349 | // TASK_WALK_PATH_FOR_UNITS, |
350 | // TASK_FACE_PLAYER, // Face the player |
356 | TASK_WALK_PATH_FOR_UNITS, |
360 | и вставим в файл schedule.h вот сюда: |
362 | //========================================================= |
363 | // These are the shared tasks |
364 | //========================================================= |
369 | TASK_WALK_PATH_FOR_UNITS, |
375 | откроем файл talkmonster.h, найдем: |
377 | class CTalkMonster : public CBaseMonster |
381 | BOOL CanFollow( void ); |
382 | BOOL IsFollowing( void ) { return m_hTargetEnt != NULL && m_hTargetEnt->IsPlayer(); } |
383 | void StopFollowing( BOOL clearSchedule ); |
384 | void StartFollowing( CBaseEntity *pLeader ); |
385 | virtual void DeclineFollowing( void ) {} |
387 | void EXPORT FollowerUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
389 | void EXPORT FollowTouch( CBaseEntity *pOther ); // new |
393 | и поместим их в файл basemonster.h, вот сюда: |
395 | class CBaseMonster : public CBaseToggle |
401 | // virtual void StopFollowing( BOOL clearSchedule ) {} |
402 | еЈ нужно поместить в комменты |
407 | В файле talkmonster.h вырезаем: |
408 | #define bits_COND_CLIENT_PUSH ( bits_COND_SPECIAL1 ) |
409 | и вставляем в файл basemonster.h прямо перед #endif // BASEMONSTER_H |
__________________
Что такое РАНО, и что такое ПОЗДНО, когда у нас впереди ВЕЧНОСТЬ.