Tutorial sur l’AI d’Half-Life 2 et du moteur Source

Publié le 30 septembre 2009 par Confridin @playmod

Voici un très bon tutoriel de RavenITA sur l’AI dans Half-Life 2. Ce tuto explique comment paramétrer au mieux l’Intelligence artificielle du jeu lorsque vous créez un mod, que ce soit avec des nodes, des hints ou des scripts. Et on peut dire que vous allez avoir du pain sur la planche.

IMG

Merci à son auteur de m’avoir autorisé à traduire son très bon tutorial pour les modeurs d’HL2.

Note du traducteur : n’ayant pas l’éditeur d’Half Life 2 sous la main, certaines traductions peuvent être approximatives. N’hésitez pas à commenter l’article si besoin est.

Les problèmes que rencontrent les débutants viennent du fait qu’ils pensent pouvoir créer une bonne scène de combat facilement, grâce à l’AI d’Half-Life 2, qui comme chacun le sait est parfaite. J’ai vu énormément de personnes placer simplement des personnages non joueurs (PNJs) ce qui n’a jamais permit d’avoir une bonne scène de combat. Alors comment résoudre ce problème ?

Tout d’abord, vous devez comprendre que l’AI d’Half-Life 2 ne peut rien « voir » seul. Les soldats et les monstres ne reçoivent aucune donnée sur l’environnement autour d’eux, donc nous avons besoin de leur donner. La seule chose à laquelle les ennemis sont bons lorsque l’on créer une map sans données est de pourchasser le joueur, peu importe où et peu importe les conséquences. Pour les aider, on peut faire appel à plusieurs éléments, dont voici les noms :

  • AI_battle_line
  • AI_changehintgroup
  • AI_changetarget
  • AI_goal
  • AI_goal_follow
  • AI_goal_assault

Et ainsi de suite. Ces éléments peuvent être trouvée dans l’éditeur du jeu (le Hammer) et ont chacun des propriétés uniques. Je ne vais pas expliquer chacune d’elles, mais je vais traiter l’utilisation de certaines.

Note du traducteur : le Hammer est l’éditeur de jeu de Half-Life 2. Un éditeur de jeu vidéo est aussi appelé SDK dans l’univers des mods

Partie 1 du tuto – Navigation

La première chose qu’un monstre a besoin de savoir est ce qui se passe autour de lui. Barrières, caisses, murs, … Avec ces informations, il va suivre des chemins tracés pour l’endroit où il veut se rendre. Pour cela, nous allons utiliser les « info_nodes« . Un « info_node » est un élément utilisée pour la navigation qui indique au PNJ (personnage non joueur) où ils peut aller.

Partons du principe que vous avez créer une carte basique dans Half-Life 2, telle que celle-ci :

Une carte basique pour Half-Life 2

Vous aller commencer par placer des info_nodes autour afin d’aider les soldats et les monstres à trouver leur chemin dans le niveau. Une autre erreur commune que j’ai pu rencontrer est de faire ceci :

Un mauvais exemple de l'utilisation des info_nodes

Vous vous dites « Super, ils sont maintenant super intelligents et peuvent aller n’importe où« . Faux ! Placer un nombre important d’info_nodes sans aucune logique va rendre vos soldats encore plus stupides qu’avant. Pour vérifier cela dans Half-Life 2, compiler votre map. Ensuite entrez dans la console la commande ai_show_connect.

Note du traducteur : si vous ne savez pas comment faire, créez un raccourci vers votre jeu sur le bureau Windows. Ensuite, éditez les propriétés de votre raccourci pour ajouter -toconsole à la fin du champ « Cible ».

Avec cette commande, vous allez pouvoir constater directement dans Half-Life 2 comment vont pouvoir se dérouler les évènements.

Les lignes rouges impliquent des info_nodes mal placés

Vous voyez les lignes vertes ? Ce sont les zones dans lesquelles les PNJ peuvent se déplacer sans problème. Les lignes rouges indiques les zones qui ne peuvent être atteintes par les monstres et soldats. Examinez l’image et vous comprendrez pourquoi :

  1. Les lignes vertes sont placées dans le désordre
  2. Certains info_nodes sont placées dans des zones où aucun personnage ne peut se placer (à cause du décor)

Cela signifie que certains personnages d’Half-Life 2 vont suivre une route étrange, et ne seront pas capable de trouver d’autres info_nodes . Ils seront alors amené à rechercher le joueur, quoi qu’il arrive. Vous devez donc réfléchir à la façon de placer les info_nodes. Utilisez-les avec soin. Vous devez ainsi les placer là où les personnages doivent faire un choix entre deux chemins différents, tout en s’assurant qu’ils sont toujours connectés les uns aux autres.

Un bon exemple de l'utilisation des info_nodes pour Half-Life 2

Voici un bon exemple de placement des info_nodes dans des angles. Pour information, les info_nodes sont aussi appelés info_node_climb et info_node_air. Il n’existe pas de différence entre ces classes, mis à part que la première est destinée aux personnages pouvant escalader et la deuxième à ceux pouvant voler. Placez simplement les infos_nodes_air au dfessus du sol, là où vous souhaitez que vos personnages se déplacent.

Partie 2 du tuto – Les « HINTS »

Les « Hints » sont essentiels pour l’IA des PNJs de HL2. Ils fournissent des données supplémentaires sur l’environnement, ce qui leur permet d’effectuer un nombre impressionnant de tâches supplémentaires. Examinons le Hint Node.

Propriétés de l'objet info_node_hint

Comme vous pouvez le constater, les Hints fonctionnent différement des info_nodes. Il y a deux types de Hints :

  • Les info_hint
  • Les info_node_hint (et info_node_air_hint qui ont à peu près le même rôle)

Dans Half-Life 2, le info_hint fournit des information sur ce qui se passe autour du PNJ, mais ne servira pas au déplacement de celui-ci. Un info_node_hint permettra en revanche de faire les deux : fournir des informations utiles, et servir du point de passage pour que le PNJ se déplace. Libre à vous d’utiliser le premier ou le second dans votre mod Half-life 2. J’utilise habituellement les info_node_hints pour les actions basiques telles que les entrées/sorties et les couvertures.

Note du traducteur : l’auteur a aussi ajouter pinch comme action, mais je n’ai pas trouvé de traduction… Et l’action couverture sera expliquée un peu plus loin dans le tutorial

Les propriétés du Hint sont les suivantes :

  • Hint Activity : Action liée à ce hint
  • Target node : Ce hint peut être lié à un autre node
  • Maximum and Minimum State : Le PNJ n’utilisera pas le hint s’il n’est pas dans l’état défini dans ce champs
  • Hint : quelles informations seront fournies au PNJ

Voici les champs à remplir pour que le PNJ puisse intéragir avec son environnement. Les actions les plus courantes sont s’accroupir, couvrir (comprendre protéger une zone), entrer, sortir, « pinch » et désavantager l’ennemi.

crouch cover medium \ low, entrance \ exit pinch, and enemy disadvantage point

Note du traducteur : désavantager l’ennemi correspond à « tirer sur le joueur tout en se protégeant » tandis que cover correspond à protéger une zone, coûte que coûte.

Il faut toujours avoir en tête que certains Pinch ne fonctionneront que si le joueur peut voir l’ennemi, ou si le PNJ se trouve derrière lui. Tout comme pour les nodes normaux, les hint nodes doivent être placé au bon endroit. Par exemple, il est inutile de placer un « enemy disadvantage point » au milieu d’un lieu à découvert sans endroit pour s’abriter. L’ennemi essaiera de tuer le joueur directement, sans essayer de lui tirer dessus depuis un endroit sûr.

Un autre point très intéressant et utile est que vous pouvez leur donner un nom, et les diviser en groupes, afin d’assigner certains groupes à certains personnages non joueurs. Même si cela n’influera pas sur les déplacements globaux, les PNJs essaieront de suivre les chemins spécifiques que vous leur avez assigné via les Hints, afin de créer des tactiques plus réalistes.

Partie 3 du tuto – On explique !

Même avec ces informations, les PNJs ont encore besoin de votre aide.

Par exemple, une bonne carte d’Half-Life 2 doit toujours avoir des NPC Clips. Le NPC Clip n’est pas un objet, mais une texture avec des propriétés spécifiques qui bloqueront les PNJs là où vous le souhaitez. Sélectionnez le npc clip texture, et créer un block couvert avec cette texture. Dans le jeu, elle sera invisible et le joueur n’en sera pas affecté. Essayer de créer des blocs et des surface avec ces textures vont vous permettre d’éviter que vos PNJ ne tombent ou ne soient bloqué dans un coin. Avec les NPC Clips, vos soldats et monstres peuvent devenir de véritables machines de guerre. Mais il reste toujours un problème à résoudre : la physique ! Car c’est un réel danger pour les personnages d’Half Life 2 :

  1. Les PNJ ne vont pas pousser les obstacles, même s’ils sont petits et facilement déplaçables. Ils vont préféré les contourner
  2. Les info_nodes et les hint nodes ne seront pas bloqués par les objets physiques, ce qui fait que vos PNJs ne sauront se rendre d’un point à un autre si un objet physique est au milieu de leur « chemin de navigation »

Pour éviter cela, vous devez utilisez un autre élément de votre éditeur de jeu : logic_navigation

La propriété logic_navigation va dire au PNJ concerné de pousser certains éléments plutôt que de les contourner. Malheureusement, il semblerait que vous ne pouvez utiliser des noms de classes avec, donc vous serez forcé d’utiliser cette astuce avec certains PNJs ayant le même nom . Les objets physiques affecté par cette propriété auront le même problème, donc pensez-y quand vous créer votre carte.

Note du traducteur : j’avoue avoir eu un peu de mal pour la traduction de ce paragraphe du tutorial. Si j’ai bien compris, il faut attribuer le nom de l’objet et du pnj dans la propriété logic_navigation du Hammer. Il faut donc autant de propriétés que d’objets différents, et que de PNJs différents

Partie 4 du tuto – Les scripts

La partie la plus importante de l’Intelligence artificielle est bien entendu le script. Maintenant, je vais être un peu plus précis pour vous donner une idée des possibilités d’Half-Life 2.

Note de l’auteur : à partir de point, des bases en C++ vous seront nécessaires

Allez dans le dossier folder/src/game/server/hl2/npc_combine.cpp (avec l’orange box d’Half-Life) et regardez la ligne suivante, en dessous du « Spawn Function« . Cela défini ce qu’un PNJ peut faire. Il peut donc tourner sa tête, se déplacer et sauter.

CapabilitiesAdd( bits_CAP_TURN_HEAD | bits_CAP_MOVE_GROUND | bits_CAP_MOVE_JUMP );

Le champs suivant permet de définir si le PNJ peut faire partie d’une équipe, tirer sur ses coéquipiers, … Ajouter des actions à un PNJS peut lui permettre d’améliorer considérablement ses actions.

CapabilitiesAdd( bits_CAP_AIM_GUN );
// Utiliser la grenade à distance CapabilitiesAdd(bits_CAP_INNATE_RANGE_ATTACK2 );
// Se battre au corps à corps CapabilitiesAdd(bits_CAP_INNATE_MELEE_ATTACK1 );
// Peut former une équipe
CapabilitiesAdd( bits_CAP_SQUAD);
CapabilitiesAdd( bits_CAP_USE_WEAPONS );
CapabilitiesAdd( bits_CAP_DUCK );
// Ne pas toucher ses coéquipiers
CapabilitiesAdd( bits_CAP_NO_HIT_SQUADMATES );

Par exemple, supprimer CapabilitiesADD ( bits_CAP_MOVE_SHOOT ), du PNJ npc_combine_s lui supprimera la possibilité de tirer et se déplacer en même temps : il se déplacera donc beaucoup plus pour éviter le joueur, mais sera amené à tirer moins. A l’inverse, ajouter CapabilitiesADD ( bits_CAP_MOVE_CLIMB ) va permettre à votre PNJ d’escalader les échelles et autres éléments ayant un info_node_climb. Et bien entendu, les possibilités sont nombreuses.

Maintenant, vous vous dites « Ok, cela permet de couvrir les déplacements et les actions de mes PNJs, mais qu’en est-il de leurs pensées ?« . Vous avez raison : les PNJs d’Half-Life 2 « pensent » à ce qu’ils vont faire ensuite avec une combinaison de Tasks, Conditions et Schedules. Pour faire simple, une série de tâches sont effectuées selon le Schedule si les conditions sont réunies.

Exemple : si le joueur se place devant moi (le PNJ), alors je vais effectuer les tâches suivantes, sinon je vais en effectuer d’autres.

Une série de tâches créer un schedule (un « emploi du temps »). Les schedules ne sont validés que lorsque toutes les tâches du schedule ont été effectuées. Si une seule tâche n’est pas bonne, alors tout le schedule est mis de côté. Regardons de plus près le schedule d’un soldat lors d’un combat. Cherchez  int CNPC_Combine::SelectCombatSchedule()

Note du traducteur : j’ai ajouté des chiffres au script, pour mieux comprendre

// If I’m scared of this enemy run away
if ( IRelationType( GetEnemy() ) == D_FR )
{
if (HasCondition( COND_SEE_ENEMY ) || (1)
HasCondition( COND_SEE_FEAR ) || (2)
HasCondition( COND_LIGHT_DAMAGE ) || (3)
HasCondition( COND_HEAVY_DAMAGE )) (4)
{
FearSound();
//ClearCommandGoal();
return SCHED_RUN_FROM_ENEMY; (5)
}

Celui-ci est relativement simple. Basiquement, cela vérifie sir le PNJ voit un ennemi (1), et si l’ennemi est quelqu’un dont il a peur (relations égale à D_FR -FR pour la peur, 2), s’il a pris arme légère (3) et une arme lourde (4), alors il va utiliser le schedule pour fuir (5). C’est assez simple en fait.  Si lon connaît les tâches et schedules spécifiques à un monstre ou à un soldate (en génréal stocker dans le fichier header) et celles communes, on peut facilement modifier les comportements pour augmenter la difficultés et/ou le réalisme des scènes de combats de Half-Life 2.

Amusez-vous bien avec vos PNJs.